diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/ConstantsDataTransfer.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/ConstantsDataTransfer.java index 7511f1ac..67247c59 100644 --- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/ConstantsDataTransfer.java +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/ConstantsDataTransfer.java @@ -2,6 +2,8 @@ import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.DataTransferProcessPluginDefinition.VERSION; +import java.nio.charset.StandardCharsets; + public interface ConstantsDataTransfer { String BPMN_EXECUTION_VARIABLE_PATIENT_REFERENCE_LIST = "patientReferenceList"; @@ -13,9 +15,16 @@ public interface ConstantsDataTransfer String BPMN_EXECUTION_VARIABLE_EXPORT_FROM_PRECISION = "exportFromPrecision"; String BPMN_EXECUTION_VARIABLE_EXPORT_TO = "exportTo"; String BPMN_EXECUTION_VARIABLE_BUNDLE = "bundle"; + String BPMN_EXECUTION_VARIABLE_AES_RETURN_KEY = "aes-return-key"; String BPMN_EXECUTION_VARIABLE_IDAT_MERGE_GRANTED = "idatMergeGranted"; String BPMN_EXECUTION_VARIABLE_USAGE_AND_TRANSFER_GRANTED = "usageAndTransferGranted"; String BPMN_EXECUTION_VARIABLE_BINARY_URL = "binaryUrl"; + String BPMN_EXECUTION_VARIABLE_ERROR_CODE = "errorCode"; + String BPMN_EXECUTION_VARIABLE_ERROR_MESSAGE = "errorMessage"; + String BPMN_EXECUTION_VARIABLE_ERROR_SOURCE = "errorSource"; + String BPMN_EXECUTION_VARIABLE_CONTINUE_STATUS = "continueStatus"; + String BPMN_EXECUTION_VARIABLE_RETURN_TARGET = "returnTarget"; + String BPMN_EXECUTION_VARIABLE_SOURCE_IDS_BY_BUNDLE_UUID = "sourceIdsByBundleUuid"; String NAMING_SYSTEM_NUM_CODEX_DIC_PSEUDONYM = "http://www.netzwerk-universitaetsmedizin.de/sid/dic-pseudonym"; String NAMING_SYSTEM_NUM_CODEX_CRR_PSEUDONYM = "http://www.netzwerk-universitaetsmedizin.de/sid/crr-pseudonym"; @@ -33,30 +42,42 @@ public interface ConstantsDataTransfer String CODESYSTEM_NUM_CODEX_DATA_TRANSFER_VALUE_EXPORT_TO = "export-to"; String CODESYSTEM_NUM_CODEX_DATA_TRANSFER_VALUE_DATA_REFERENCE = "data-reference"; - String PROFILE_NUM_CODEX_TASK_START_DATA_TRIGGER = "http://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-start-data-trigger"; - String PROFILE_NUM_CODEX_TASK_STOP_DATA_TRIGGER = "http://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-stop-data-trigger"; String PROFILE_NUM_CODEX_TASK_DATA_TRIGGER_PROCESS_URI = "http://www.netzwerk-universitaetsmedizin.de/bpe/Process/dataTrigger/"; String PROFILE_NUM_CODEX_TASK_DATA_TRIGGER_PROCESS_URI_AND_LATEST_VERSION = PROFILE_NUM_CODEX_TASK_DATA_TRIGGER_PROCESS_URI + VERSION; + String PROFILE_NUM_CODEX_TASK_START_DATA_TRIGGER = "http://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-start-data-trigger"; String PROFILE_NUM_CODEX_TASK_START_DATA_TRIGGER_MESSAGE_NAME = "startDataTrigger"; + String PROFILE_NUM_CODEX_TASK_STOP_DATA_TRIGGER = "http://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-stop-data-trigger"; String PROFILE_NUM_CODEX_TASK_STOP_DATA_TRIGGER_MESSAGE_NAME = "stopDataTrigger"; - String PROFILE_NUM_CODEX_TASK_START_DATA_SEND = "http://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-start-data-send"; String PROFILE_NUM_CODEX_TASK_DATA_SEND_PROCESS_URI = "http://www.netzwerk-universitaetsmedizin.de/bpe/Process/dataSend/"; String PROFILE_NUM_CODEX_TASK_DATA_SEND_PROCESS_URI_AND_LATEST_VERSION = PROFILE_NUM_CODEX_TASK_DATA_SEND_PROCESS_URI + VERSION; + String PROFILE_NUM_CODEX_TASK_START_DATA_SEND = "http://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-start-data-send"; String PROFILE_NUM_CODEX_TASK_START_DATA_SEND_MESSAGE_NAME = "startDataSend"; + String PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_SEND = "http://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-continue-data-send"; + String PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_SEND_MESSAGE_NAME = "continueDataSend"; + String PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_SEND_WITH_VALIDATION_ERROR = "http://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-continue-data-send-with-validation-error"; + String PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_SEND_WITH_VALIDATION_ERROR_MESSAGE_NAME = "continueDataSendWithValidationError"; + String PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_SEND_WITH_ERROR = "http://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-continue-data-send-with-error"; + String PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_SEND_WITH_ERROR_MESSAGE_NAME = "continueDataSendWithError"; - String PROFILE_NUM_CODEX_TASK_START_DATA_TRANSLATE = "http://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-start-data-translate"; String PROFILE_NUM_CODEX_TASK_DATA_TRANSLATE_PROCESS_URI = "http://www.netzwerk-universitaetsmedizin.de/bpe/Process/dataTranslate/"; String PROFILE_NUM_CODEX_TASK_DATA_TRANSLATE_PROCESS_URI_AND_LATEST_VERSION = PROFILE_NUM_CODEX_TASK_DATA_TRANSLATE_PROCESS_URI + VERSION; + String PROFILE_NUM_CODEX_TASK_START_DATA_TRANSLATE = "http://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-start-data-translate"; String PROFILE_NUM_CODEX_TASK_START_DATA_TRANSLATE_MESSAGE_NAME = "startDataTranslate"; + String PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_TRANSLATE = "http://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-continue-data-translate"; + String PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_TRANSLATE_MESSAGE_NAME = "continueDataTranslate"; + String PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_TRANSLATE_WITH_VALIDATION_ERROR = "http://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-continue-data-translate-with-validation-error"; + String PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_TRANSLATE_WITH_VALIDATION_ERROR_MESSAGE_NAME = "continueDataTranslateWithValidationError"; + String PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_TRANSLATE_WITH_ERROR = "http://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-continue-data-translate-with-error"; + String PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_TRANSLATE_WITH_ERROR_MESSAGE_NAME = "continueDataTranslateWithError"; - String PROFILE_NUM_CODEX_TASK_START_DATA_RECEIVE = "http://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-start-data-receive"; String PROFILE_NUM_CODEX_TASK_DATA_RECEIVE_PROCESS_URI = "http://www.netzwerk-universitaetsmedizin.de/bpe/Process/dataReceive/"; String PROFILE_NUM_CODEX_TASK_DATA_RECEIVE_PROCESS_URI_AND_LATEST_VERSION = PROFILE_NUM_CODEX_TASK_DATA_RECEIVE_PROCESS_URI + VERSION; + String PROFILE_NUM_CODEX_TASK_START_DATA_RECEIVE = "http://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-start-data-receive"; String PROFILE_NUM_CODEX_TASK_START_DATA_RECEIVE_MESSAGE_NAME = "startDataReceive"; String PSEUDONYM_PLACEHOLDER = "${pseudonym}"; @@ -68,16 +89,27 @@ public interface ConstantsDataTransfer String HAPI_USER_DATA_SOURCE_ID_ELEMENT = "source-id"; String CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR = "http://www.netzwerk-universitaetsmedizin.de/fhir/CodeSystem/data-transfer-error"; + String CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_PATIENT_NOT_FOUND = "patient-not-found"; + String CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_BAD_PATIENT_REFERENCE = "bad-patient-reference"; + String CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_FTTP_NOT_REACHABLE = "fttp-not-reachable"; + String CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_NO_DIC_PSEUDONYM_FOR_BLOOMFILTER = "no-dic-pseudonym-for-bloomfilter"; String CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_VALIDATION_FAILED = "validation-failed"; + String CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_TIMEOUT_WAITING_FOR_RESPONSE_FROM_CRR = "timeout-waiting-for-response-from-crr"; + String CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_DOWNLOAD_DATA_FROM_DIC_FAILED = "download-data-from-dic-failed"; + String CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_NO_CRR_PSEUDONYM_FOR_DIC_PSEUDONYM = "no-crr-pseudonym-for-dic-pseudonym"; + String CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_TIMEOUT_WAITING_FOR_RESPONSE_FROM_GTH = "timeout-waiting-for-response-from-gth"; + String CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_DOWNLOAD_DATA_FROM_GTH_FAILED = "download-data-from-gth-failed"; + String CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_INSERT_INTO_CRR_FHIR_REPOSITORY_FAILED = "insert-into-crr-fhir-respository-failed"; String CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_SOURCE = "http://www.netzwerk-universitaetsmedizin.de/fhir/CodeSystem/data-transfer-error-source"; String CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_SOURCE_VALUE_MEDIC = "MeDIC"; String CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_SOURCE_VALUE_GTH = "GTH"; - String CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_SOURCE_VALUE_FTTP = "fTTP"; String CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_SOURCE_VALUE_CRR = "CRR"; String EXTENSION_ERROR_METADATA = "https://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/error-metadata"; String EXTENSION_ERROR_METADATA_TYPE = "type"; String EXTENSION_ERROR_METADATA_SOURCE = "source"; String EXTENSION_ERROR_METADATA_REFERENCE = "reference"; + + byte[] RETURN_AAD = "aLCdSbI55VAv2BaKs4ypnDw3AaRfSBWXa8Bxl78BJw".getBytes(StandardCharsets.UTF_8); } diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/DataTransferProcessPluginDefinition.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/DataTransferProcessPluginDefinition.java index 5959137c..bc72b591 100644 --- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/DataTransferProcessPluginDefinition.java +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/DataTransferProcessPluginDefinition.java @@ -22,9 +22,14 @@ import ca.uhn.fhir.context.FhirContext; import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.client.FttpClientFactory; import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.client.GeccoClientFactory; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.spring.config.ReceiveConfig; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.spring.config.SendConfig; import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.spring.config.TransferDataConfig; import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.spring.config.TransferDataSerializerConfig; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.spring.config.TranslateConfig; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.spring.config.TriggerConfig; import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.spring.config.ValidationConfig; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.spring.config.ValidationConfig.TerminologyServerConnectionTestStatus; import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.validation.BundleValidatorFactory; public class DataTransferProcessPluginDefinition implements ProcessPluginDefinition @@ -61,7 +66,8 @@ public Stream getBpmnFiles() @Override public Stream> getSpringConfigClasses() { - return Stream.of(TransferDataConfig.class, TransferDataSerializerConfig.class, ValidationConfig.class); + return Stream.of(TransferDataConfig.class, TransferDataSerializerConfig.class, ValidationConfig.class, + TriggerConfig.class, SendConfig.class, TranslateConfig.class, ReceiveConfig.class); } @Override @@ -83,29 +89,42 @@ public ResourceProvider getResourceProvider(FhirContext fhirContext, ClassLoader var sTexErMe = StructureDefinitionResource .file("fhir/StructureDefinition/num-codex-extension-error-metadata.xml"); - var sTstaDrec = StructureDefinitionResource - .file("fhir/StructureDefinition/num-codex-task-start-data-receive.xml"); - var sTstaDsen = StructureDefinitionResource.file("fhir/StructureDefinition/num-codex-task-start-data-send.xml"); - var sTstaDtra = StructureDefinitionResource - .file("fhir/StructureDefinition/num-codex-task-start-data-translate.xml"); var sTstaDtri = StructureDefinitionResource .file("fhir/StructureDefinition/num-codex-task-start-data-trigger.xml"); var sTstoDtri = StructureDefinitionResource .file("fhir/StructureDefinition/num-codex-task-stop-data-trigger.xml"); + var sTstaDsen = StructureDefinitionResource.file("fhir/StructureDefinition/num-codex-task-start-data-send.xml"); + var sTconDsen = StructureDefinitionResource + .file("fhir/StructureDefinition/num-codex-task-continue-data-send.xml"); + var sTconDsenWvE = StructureDefinitionResource + .file("fhir/StructureDefinition/num-codex-task-continue-data-send-with-validation-error.xml"); + var sTconDsenWe = StructureDefinitionResource + .file("fhir/StructureDefinition/num-codex-task-continue-data-send-with-error.xml"); + var sTstaDtra = StructureDefinitionResource + .file("fhir/StructureDefinition/num-codex-task-start-data-translate.xml"); + var sTconDtra = StructureDefinitionResource + .file("fhir/StructureDefinition/num-codex-task-continue-data-translate.xml"); + var sTconDtraWvE = StructureDefinitionResource + .file("fhir/StructureDefinition/num-codex-task-continue-data-translate-with-validation-error.xml"); + var sTconDtraWe = StructureDefinitionResource + .file("fhir/StructureDefinition/num-codex-task-continue-data-translate-with-error.xml"); + var sTstaDrec = StructureDefinitionResource + .file("fhir/StructureDefinition/num-codex-task-start-data-receive.xml"); var vD = ValueSetResource.file("fhir/ValueSet/num-codex-data-transfer.xml"); var vDeS = ValueSetResource.file("fhir/ValueSet/num-codex-data-transfer-error-source.xml"); var vDe = ValueSetResource.file("fhir/ValueSet/num-codex-data-transfer-error.xml"); - Map> resourcesByProcessKeyAndVersion = Map.of( // + Map> resourcesByProcessKeyAndVersion = Map.of( "wwwnetzwerk-universitaetsmedizinde_dataTrigger/" + VERSION, - Arrays.asList(aTri, cD, nD, sTstaDtri, sTstoDtri, vD), // - "wwwnetzwerk-universitaetsmedizinde_dataSend/" + VERSION, - Arrays.asList(aSen, cD, cDeS, cDe, nD, nB, sTexErMe, sTstaDsen, vD, vDeS, vDe), // + Arrays.asList(aTri, cD, nD, sTstaDtri, sTstoDtri, vD), + "wwwnetzwerk-universitaetsmedizinde_dataSend/" + VERSION, Arrays.asList(aSen, cD, cDeS, cDe, nB, nD, + sTexErMe, sTstaDsen, sTconDsen, sTconDsenWvE, sTconDsenWe, vD, vDeS, vDe), "wwwnetzwerk-universitaetsmedizinde_dataTranslate/" + VERSION, - Arrays.asList(aTra, cD, nD, nC, sTstaDtra, vD), // + Arrays.asList(aTra, cD, cDeS, cDe, nD, nC, sTexErMe, sTstaDtra, sTconDtra, sTconDtraWvE, sTconDtraWe, + vD), "wwwnetzwerk-universitaetsmedizinde_dataReceive/" + VERSION, - Arrays.asList(aRec, cD, nC, sTstaDrec, vD)); + Arrays.asList(aRec, cD, cDeS, cDe, nC, sTexErMe, sTstaDrec, vD)); return ResourceProvider.read(VERSION, DATE, () -> fhirContext.newXmlParser().setStripVersionsFromReferences(false), classLoader, propertyResolver, @@ -129,12 +148,12 @@ public void onProcessesDeployed(ApplicationContext pluginApplicationContext, Lis if (activeProcesses.contains("wwwnetzwerk-universitaetsmedizinde_dataSend")) { - boolean testOk = pluginApplicationContext.getBean(ValidationConfig.class) + TerminologyServerConnectionTestStatus status = pluginApplicationContext.getBean(ValidationConfig.class) .testConnectionToTerminologyServer(); - if (testOk) + if (TerminologyServerConnectionTestStatus.OK.equals(status)) pluginApplicationContext.getBean(BundleValidatorFactory.class).init(); - else + else if (TerminologyServerConnectionTestStatus.NOT_OK.equals(status)) logger.warn( "Due to an error while testing the connection to the terminology server {} was not initialized, validation of bundles will be skipped.", BundleValidatorFactory.class.getSimpleName()); diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/client/FttpClientImpl.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/client/FttpClientImpl.java index 2d513827..5b95253b 100644 --- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/client/FttpClientImpl.java +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/client/FttpClientImpl.java @@ -1,5 +1,6 @@ package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.client; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_FTTP_NOT_REACHABLE; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.PSEUDONYM_PATTERN_STRING; import java.net.MalformedURLException; @@ -10,6 +11,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.camunda.bpm.engine.delegate.BpmnError; import org.hl7.fhir.r4.model.Base64BinaryType; import org.hl7.fhir.r4.model.CapabilityStatement; import org.hl7.fhir.r4.model.Identifier; @@ -128,8 +130,8 @@ public Optional getCrrPseudonym(String dicSourceAndPseudonym) } catch (Exception e) { - logger.error("Error while retrieving CRR pseudonym", e); - return Optional.empty(); + logger.error("Error while retrieving CRR pseudonym: {} - {}", e.getClass().getName(), e.getMessage()); + throw new BpmnError(CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_FTTP_NOT_REACHABLE, e.getMessage()); } } @@ -171,8 +173,8 @@ public Optional getDicPseudonym(String bloomFilter) } catch (Exception e) { - logger.error("Error while retrieving DIC pseudonym", e); - return Optional.empty(); + logger.error("Error while retrieving DIC pseudonym: {} - {}", e.getClass().getName(), e.getMessage()); + throw new BpmnError(CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_FTTP_NOT_REACHABLE, e.getMessage()); } } diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/client/fhir/AbstractFhirClient.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/client/fhir/AbstractFhirClient.java index 5bfe464d..e0a4fa6c 100644 --- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/client/fhir/AbstractFhirClient.java +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/client/fhir/AbstractFhirClient.java @@ -1,5 +1,6 @@ package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.client.fhir; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_BAD_PATIENT_REFERENCE; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.NAMING_SYSTEM_NUM_CODEX_DIC_PSEUDONYM; import java.io.IOException; @@ -23,6 +24,7 @@ import java.util.stream.IntStream; import java.util.stream.Stream; +import org.camunda.bpm.engine.delegate.BpmnError; import org.hl7.fhir.instance.model.api.IBaseOperationOutcome; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent; @@ -578,8 +580,9 @@ public Optional getPatient(String reference) } } else - throw new RuntimeException( - "Reference should be an absolute local fhir store url to " + client.getServerBase()); + throw new BpmnError(CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_BAD_PATIENT_REFERENCE, + "Patient reference not an absolute reference to a resouce at the local GECCO FHIR server: " + + client.getServerBase()); } @Override diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/client/fhir/FhirBridgeClient.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/client/fhir/FhirBridgeClient.java index 11e3bef9..8e3f227d 100644 --- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/client/fhir/FhirBridgeClient.java +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/client/fhir/FhirBridgeClient.java @@ -72,17 +72,18 @@ private boolean isEntrySupported(BundleEntryComponent entry, Predicate createOrUpdatePatient(Bundle bundle) { - Optional bundlePatient = bundle.getEntry().stream() - .filter(entry -> isEntrySupported(entry, e -> e.getResource() instanceof Patient)).findFirst() - .map(e -> (Patient) e.getResource()); + Optional bundlePatientEntry = bundle.getEntry().stream() + .filter(entry -> isEntrySupported(entry, e -> e.getResource() instanceof Patient)).findFirst(); - if (bundlePatient.isPresent()) + if (bundlePatientEntry.isPresent()) { - String pseudonym = getPseudonym(bundlePatient.get()); + Patient newPatient = (Patient) bundlePatientEntry.get().getResource(); + String pseudonym = getPseudonym(newPatient); Optional existingPatient = findPatientInLocalFhirStore(pseudonym); - return existingPatient.map(existing -> update(existing, bundlePatient.get(), pseudonym)) - .orElseGet(() -> create(bundlePatient.get(), pseudonym)); + return existingPatient + .map(existing -> update(existing, newPatient, pseudonym, bundlePatientEntry.get().getFullUrl())) + .orElseGet(() -> create(newPatient, pseudonym, bundlePatientEntry.get().getFullUrl())); } else { @@ -91,7 +92,8 @@ private Optional createOrUpdatePatient(Bundle bundle) } } - private Optional update(Patient existingPatient, Patient newPatient, String pseudonym) + private Optional update(Patient existingPatient, Patient newPatient, String pseudonym, + String bundleFullUrl) { logger.debug("Updating Patient with pseudonym {}", pseudonym); @@ -124,7 +126,11 @@ private Optional update(Patient existingPatient, Patient newPatient, St IBaseOperationOutcome outcome = e.getOperationOutcome(); if (outcome != null && outcome instanceof OperationOutcome) + { outcomeLogger.logOutcome((OperationOutcome) outcome); + throw new ValidationException(newPatient.getResourceType().name(), bundleFullUrl, + (OperationOutcome) outcome); + } throw e; } @@ -132,6 +138,16 @@ private Optional update(Patient existingPatient, Patient newPatient, St { logger.warn("Could not update patient {}, message: {}, status: {}, body: {}", newPatient.getIdElement().toString(), e.getMessage(), e.getStatusCode(), e.getResponseBody()); + + IBaseOperationOutcome outcome = e.getOperationOutcome(); + + if (outcome != null && outcome instanceof OperationOutcome) + { + outcomeLogger.logOutcome((OperationOutcome) outcome); + throw new ValidationException(newPatient.getResourceType().name(), bundleFullUrl, + (OperationOutcome) outcome); + } + throw e; } catch (Exception e) @@ -141,7 +157,7 @@ private Optional update(Patient existingPatient, Patient newPatient, St } } - private Optional create(Patient newPatient, String pseudonym) + private Optional create(Patient newPatient, String pseudonym, String bundleFullUrl) { logger.debug("Creating Patient with pseudonym {}", pseudonym); @@ -173,7 +189,11 @@ private Optional create(Patient newPatient, String pseudonym) IBaseOperationOutcome outcome = e.getOperationOutcome(); if (outcome != null && outcome instanceof OperationOutcome) + { outcomeLogger.logOutcome((OperationOutcome) outcome); + throw new ValidationException(newPatient.getResourceType().name(), bundleFullUrl, + (OperationOutcome) outcome); + } throw e; } @@ -181,6 +201,16 @@ private Optional create(Patient newPatient, String pseudonym) { logger.warn("Could not create patient {}, message: {}, status: {}, body: {}", newPatient.getIdElement().toString(), e.getMessage(), e.getStatusCode(), e.getResponseBody()); + + IBaseOperationOutcome outcome = e.getOperationOutcome(); + + if (outcome != null && outcome instanceof OperationOutcome) + { + outcomeLogger.logOutcome((OperationOutcome) outcome); + throw new ValidationException(newPatient.getResourceType().name(), bundleFullUrl, + (OperationOutcome) outcome); + } + throw e; } catch (Exception e) @@ -196,7 +226,8 @@ private void createOrUpdateEntry(int index, BundleEntryComponent entry, Patient String url = entry.getRequest().getUrl(); Optional existingResource = findResourceInLocalFhirStore(url, resource.getClass()); - existingResource.ifPresentOrElse(existing -> update(existing, resource), () -> create(resource)); + existingResource.ifPresentOrElse(existing -> update(existing, resource, entry.getFullUrl()), + () -> create(resource, entry.getFullUrl())); } private Optional findResourceInLocalFhirStore(String url, Class resourceType) @@ -265,7 +296,7 @@ private Optional findResourceInLocalFhirStore(String url, Class createMeDicValidationError(IdType sourceId, OperationOutcome outcome) + public Stream createMeDicValidationError(IdType reference, OperationOutcome outcome) { return outcome.getIssue().stream() .filter(i -> IssueSeverity.FATAL.equals(i.getSeverity()) || IssueSeverity.ERROR.equals(i.getSeverity())) - .map(i -> createMeDicValidationError(sourceId, i)); + .map(i -> createValidationError(reference, i, + CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_SOURCE_VALUE_MEDIC)); } - private TaskOutputComponent createMeDicValidationError(IdType sourceId, OperationOutcomeIssueComponent i) + public Stream createCrrValidationError(IdType reference, OperationOutcome outcome) + { + return outcome.getIssue().stream() + .filter(i -> IssueSeverity.FATAL.equals(i.getSeverity()) || IssueSeverity.ERROR.equals(i.getSeverity())) + .map(i -> createValidationError(reference, i, + CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_SOURCE_VALUE_CRR)); + } + + public Stream createCrrValidationError(OperationOutcome outcome) + { + return outcome.getIssue().stream() + .filter(i -> IssueSeverity.FATAL.equals(i.getSeverity()) || IssueSeverity.ERROR.equals(i.getSeverity())) + .map(i -> createValidationError(null, i, CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_SOURCE_VALUE_CRR)); + } + + private TaskOutputComponent createValidationError(IdType reference, OperationOutcomeIssueComponent i, String source) { TaskOutputComponent output = new TaskOutputComponent(); output.getType().getCodingFirstRep().setSystem(CODESYSTEM_HIGHMED_BPMN) @@ -44,16 +61,33 @@ private TaskOutputComponent createMeDicValidationError(IdType sourceId, Operatio .setValue(new Coding().setSystem(CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR) .setCode(CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_VALIDATION_FAILED)); metaData.addExtension().setUrl(EXTENSION_ERROR_METADATA_SOURCE) - .setValue(new Coding().setSystem(CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_SOURCE) - .setCode(CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_SOURCE_VALUE_MEDIC)); + .setValue(new Coding().setSystem(CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_SOURCE).setCode(source)); - if (sourceId != null) + if (reference != null) metaData.addExtension().setUrl(EXTENSION_ERROR_METADATA_REFERENCE) - .setValue(new Reference().setReferenceElement(sourceId)); + .setValue(new Reference().setReferenceElement(reference)); output.setValue(new StringType( "Validation faild at " + i.getLocation().stream().map(StringType::getValue).findFirst().orElse("?"))); return output; } + + public TaskOutputComponent createError(String source, String code, String message) + { + TaskOutputComponent output = new TaskOutputComponent(); + output.getType().getCodingFirstRep().setSystem(CODESYSTEM_HIGHMED_BPMN) + .setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_ERROR); + + Extension metaData = output.addExtension(); + metaData.setUrl(EXTENSION_ERROR_METADATA); + metaData.addExtension().setUrl(EXTENSION_ERROR_METADATA_TYPE) + .setValue(new Coding().setSystem(CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR).setCode(code)); + metaData.addExtension().setUrl(EXTENSION_ERROR_METADATA_SOURCE) + .setValue(new Coding().setSystem(CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_SOURCE).setCode(source)); + + output.setValue(new StringType(message)); + + return output; + } } diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/logging/ErrorLogger.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/logging/ErrorLogger.java index 8dd25985..d9eee869 100644 --- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/logging/ErrorLogger.java +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/logging/ErrorLogger.java @@ -7,11 +7,35 @@ public class ErrorLogger { private static final Logger validationLogger = LoggerFactory.getLogger("validation-error-logger"); + private static final Logger errorLogger = LoggerFactory.getLogger("error-logger"); public void logValidationFailed(IdType taskId) { - validationLogger.debug( - "Validation of FHIR resources faild during execution of data-send process started by Task {}", - taskId.getValue()); + validationLogger.debug("Validation of FHIR resources failed, started by Task {}", taskId.getValue()); + } + + public void logValidationFailedLocal(IdType taskId) + { + validationLogger.debug("Local validation of FHIR resources failed, started by Task {}", taskId.getValue()); + } + + public void logValidationFailedRemote(IdType taskId) + { + validationLogger.debug("Remote validation of FHIR resources failed, started by Task {}", taskId.getValue()); + } + + public void logDataSendFailed(IdType taskId) + { + errorLogger.debug("Send process failed, started by Task {}", taskId.getValue()); + } + + public void logDataTranslateFailed(IdType taskId) + { + errorLogger.debug("Translate process failed, started by Task {}", taskId.getValue()); + } + + public void logDataReceiveFailed(IdType taskId) + { + errorLogger.debug("Receive process failed, started by Task {}", taskId.getValue()); } } diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/message/ContinueSendProcess.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/message/ContinueSendProcess.java new file mode 100644 index 00000000..ca48fb0e --- /dev/null +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/message/ContinueSendProcess.java @@ -0,0 +1,44 @@ +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.message; + +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_RETURN_TARGET; + +import java.util.stream.Stream; + +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.ParameterComponent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ca.uhn.fhir.context.FhirContext; + +public class ContinueSendProcess extends AbstractTaskMessageSend +{ + private static final Logger logger = LoggerFactory.getLogger(ContinueSendProcess.class); + + public ContinueSendProcess(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, OrganizationProvider organizationProvider, FhirContext fhirContext) + { + super(clientProvider, taskHelper, readAccessHelper, organizationProvider, fhirContext); + } + + @Override + protected Target getTarget() + { + return (Target) execution.getVariable(BPMN_EXECUTION_VARIABLE_RETURN_TARGET); + } + + @Override + protected void sendTask(Target target, String instantiatesUri, String messageName, String businessKey, + String profile, Stream additionalInputParameters) + { + // TODO implement continue send + logger.debug("implement continue send"); + + super.sendTask(target, instantiatesUri, messageName, businessKey, profile, additionalInputParameters); + } +} diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/message/ContinueSendProcessWithError.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/message/ContinueSendProcessWithError.java new file mode 100644 index 00000000..d3691201 --- /dev/null +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/message/ContinueSendProcessWithError.java @@ -0,0 +1,61 @@ +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.message; + +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_ERROR_CODE; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_ERROR_MESSAGE; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_ERROR_SOURCE; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_RETURN_TARGET; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_SOURCE_VALUE_GTH; + +import java.util.Objects; +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.Target; +import org.hl7.fhir.r4.model.Task.ParameterComponent; + +import ca.uhn.fhir.context.FhirContext; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.error.ErrorInputParameterGenerator; + +public class ContinueSendProcessWithError extends AbstractTaskMessageSend +{ + private final ErrorInputParameterGenerator errorInputParameterGenerator; + + public ContinueSendProcessWithError(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, OrganizationProvider organizationProvider, FhirContext fhirContext, + ErrorInputParameterGenerator errorInputParameterGenerator) + { + super(clientProvider, taskHelper, readAccessHelper, organizationProvider, fhirContext); + + this.errorInputParameterGenerator = errorInputParameterGenerator; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(errorInputParameterGenerator, "errorInputParameterGenerator"); + } + + @Override + protected Target getTarget() + { + return (Target) execution.getVariable(BPMN_EXECUTION_VARIABLE_RETURN_TARGET); + } + + @Override + protected Stream getAdditionalInputParameters(DelegateExecution execution) + { + String errorCode = (String) execution.getVariable(BPMN_EXECUTION_VARIABLE_ERROR_CODE); + String errorMessage = (String) execution.getVariable(BPMN_EXECUTION_VARIABLE_ERROR_MESSAGE); + String errorSource = (String) execution.getVariable(BPMN_EXECUTION_VARIABLE_ERROR_SOURCE); + + return Stream.of(errorInputParameterGenerator.createError(errorCode, errorMessage, + errorSource != null ? errorSource : CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_SOURCE_VALUE_GTH)); + } +} diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/message/ContinueSendProcessWithValidationError.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/message/ContinueSendProcessWithValidationError.java new file mode 100644 index 00000000..eababd11 --- /dev/null +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/message/ContinueSendProcessWithValidationError.java @@ -0,0 +1,55 @@ +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.message; + +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_BINARY_URL; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_RETURN_TARGET; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER_VALUE_DATA_REFERENCE; + +import java.util.Objects; +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.Target; +import org.hl7.fhir.r4.model.Reference; +import org.hl7.fhir.r4.model.Task.ParameterComponent; + +import ca.uhn.fhir.context.FhirContext; + +public class ContinueSendProcessWithValidationError extends AbstractTaskMessageSend +{ + public ContinueSendProcessWithValidationError(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, OrganizationProvider organizationProvider, FhirContext fhirContext) + { + super(clientProvider, taskHelper, readAccessHelper, organizationProvider, fhirContext); + } + + @Override + protected Target getTarget() + { + return (Target) execution.getVariable(BPMN_EXECUTION_VARIABLE_RETURN_TARGET); + } + + @Override + protected Stream getAdditionalInputParameters(DelegateExecution execution) + { + return Stream.of(dataReferenceParameter(execution)); + } + + private ParameterComponent dataReferenceParameter(DelegateExecution execution) + { + String binaryReference = (String) execution.getVariable(BPMN_EXECUTION_VARIABLE_BINARY_URL); + + Objects.requireNonNull(binaryReference, "binaryReference"); + + ParameterComponent param = new ParameterComponent(); + param.getType().addCoding().setSystem(CODESYSTEM_NUM_CODEX_DATA_TRANSFER) + .setCode(CODESYSTEM_NUM_CODEX_DATA_TRANSFER_VALUE_DATA_REFERENCE); + param.setValue(new Reference().setReference(binaryReference)); + return param; + } +} diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/message/ContinueTranslateProcess.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/message/ContinueTranslateProcess.java new file mode 100644 index 00000000..6957fda9 --- /dev/null +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/message/ContinueTranslateProcess.java @@ -0,0 +1,45 @@ +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.message; + +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_RETURN_TARGET; + +import java.util.stream.Stream; + +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.ParameterComponent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ca.uhn.fhir.context.FhirContext; + +public class ContinueTranslateProcess extends AbstractTaskMessageSend +{ + private static final Logger logger = LoggerFactory.getLogger(ContinueTranslateProcess.class); + + public ContinueTranslateProcess(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, OrganizationProvider organizationProvider, FhirContext fhirContext) + { + super(clientProvider, taskHelper, readAccessHelper, organizationProvider, fhirContext); + } + + @Override + protected Target getTarget() + { + return (Target) execution.getVariable(BPMN_EXECUTION_VARIABLE_RETURN_TARGET); + } + + @Override + protected void sendTask(Target target, String instantiatesUri, String messageName, String businessKey, + String profile, Stream additionalInputParameters) + { + + // TODO implement continue translate + logger.debug("implement continue translate"); + + super.sendTask(target, instantiatesUri, messageName, businessKey, profile, additionalInputParameters); + } +} diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/message/ContinueTranslateProcessWithError.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/message/ContinueTranslateProcessWithError.java new file mode 100644 index 00000000..9e7b46ad --- /dev/null +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/message/ContinueTranslateProcessWithError.java @@ -0,0 +1,61 @@ +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.message; + +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_ERROR_CODE; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_ERROR_MESSAGE; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_ERROR_SOURCE; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_RETURN_TARGET; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_SOURCE_VALUE_CRR; + +import java.util.Objects; +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.Target; +import org.hl7.fhir.r4.model.Task.ParameterComponent; + +import ca.uhn.fhir.context.FhirContext; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.error.ErrorInputParameterGenerator; + +public class ContinueTranslateProcessWithError extends AbstractTaskMessageSend +{ + private final ErrorInputParameterGenerator errorInputParameterGenerator; + + public ContinueTranslateProcessWithError(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, OrganizationProvider organizationProvider, FhirContext fhirContext, + ErrorInputParameterGenerator errorInputParameterGenerator) + { + super(clientProvider, taskHelper, readAccessHelper, organizationProvider, fhirContext); + + this.errorInputParameterGenerator = errorInputParameterGenerator; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(errorInputParameterGenerator, "errorInputParameterGenerator"); + } + + @Override + protected Target getTarget() + { + return (Target) execution.getVariable(BPMN_EXECUTION_VARIABLE_RETURN_TARGET); + } + + @Override + protected Stream getAdditionalInputParameters(DelegateExecution execution) + { + String errorCode = (String) execution.getVariable(BPMN_EXECUTION_VARIABLE_ERROR_CODE); + String errorMessage = (String) execution.getVariable(BPMN_EXECUTION_VARIABLE_ERROR_MESSAGE); + String errorSource = (String) execution.getVariable(BPMN_EXECUTION_VARIABLE_ERROR_SOURCE); + + return Stream.of(errorInputParameterGenerator.createError(errorCode, errorMessage, + errorSource != null ? errorSource : CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_SOURCE_VALUE_CRR)); + } +} diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/message/ContinueTranslateProcessWithValidationError.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/message/ContinueTranslateProcessWithValidationError.java new file mode 100644 index 00000000..58d5e0a6 --- /dev/null +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/message/ContinueTranslateProcessWithValidationError.java @@ -0,0 +1,56 @@ +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.message; + +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_BINARY_URL; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_RETURN_TARGET; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER_VALUE_DATA_REFERENCE; + +import java.util.Objects; +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.Target; +import org.hl7.fhir.r4.model.Reference; +import org.hl7.fhir.r4.model.Task.ParameterComponent; + +import ca.uhn.fhir.context.FhirContext; + +public class ContinueTranslateProcessWithValidationError extends AbstractTaskMessageSend +{ + public ContinueTranslateProcessWithValidationError(FhirWebserviceClientProvider clientProvider, + TaskHelper taskHelper, ReadAccessHelper readAccessHelper, OrganizationProvider organizationProvider, + FhirContext fhirContext) + { + super(clientProvider, taskHelper, readAccessHelper, organizationProvider, fhirContext); + } + + @Override + protected Target getTarget() + { + return (Target) execution.getVariable(BPMN_EXECUTION_VARIABLE_RETURN_TARGET); + } + + @Override + protected Stream getAdditionalInputParameters(DelegateExecution execution) + { + return Stream.of(dataReferenceParameter(execution)); + } + + private ParameterComponent dataReferenceParameter(DelegateExecution execution) + { + String binaryReference = (String) execution.getVariable(BPMN_EXECUTION_VARIABLE_BINARY_URL); + + Objects.requireNonNull(binaryReference, "binaryReference"); + + ParameterComponent param = new ParameterComponent(); + param.getType().addCoding().setSystem(CODESYSTEM_NUM_CODEX_DATA_TRANSFER) + .setCode(CODESYSTEM_NUM_CODEX_DATA_TRANSFER_VALUE_DATA_REFERENCE); + param.setValue(new Reference().setReference(binaryReference)); + return param; + } +} diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/message/StartReceiveProcess.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/message/StartReceiveProcess.java index 2677147c..859a4b61 100644 --- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/message/StartReceiveProcess.java +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/message/StartReceiveProcess.java @@ -7,7 +7,6 @@ import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER_VALUE_PSEUDONYM; import java.util.Objects; -import java.util.UUID; import java.util.stream.Stream; import org.camunda.bpm.engine.delegate.DelegateExecution; @@ -46,9 +45,9 @@ protected Stream getAdditionalInputParameters(DelegateExecut protected void sendTask(Target target, String instantiatesUri, String messageName, String businessKey, String profile, Stream additionalInputParameters) { - String crrBusinessKey = UUID.randomUUID().toString(); + String crrBusinessKey = createAndSaveAlternativeBusinessKey(); - logger.info("DIC businessKey {}, CRR businessKey {}", businessKey, crrBusinessKey); + logger.debug("DIC businessKey {}, CRR businessKey {}", businessKey, crrBusinessKey); super.sendTask(target, instantiatesUri, messageName, crrBusinessKey, profile, additionalInputParameters); } diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/message/StartSendProcess.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/message/StartSendProcess.java index dbe71105..07ea816c 100644 --- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/message/StartSendProcess.java +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/message/StartSendProcess.java @@ -11,6 +11,7 @@ import java.util.Date; import java.util.Objects; +import java.util.UUID; import java.util.stream.Stream; import org.camunda.bpm.engine.delegate.DelegateExecution; @@ -19,6 +20,7 @@ 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.DateTimeType; import org.hl7.fhir.r4.model.Identifier; import org.hl7.fhir.r4.model.InstantType; @@ -43,6 +45,15 @@ public StartSendProcess(FhirWebserviceClientProvider clientProvider, TaskHelper super(clientProvider, taskHelper, readAccessHelper, organizationProvider, fhirContext); } + @Override + protected void sendTask(Target target, String instantiatesUri, String messageName, String businessKey, + String profile, Stream additionalInputParameters) + { + // can't use same business key as trigger process + super.sendTask(target, instantiatesUri, messageName, UUID.randomUUID().toString(), profile, + additionalInputParameters); + } + @Override protected Stream getAdditionalInputParameters(DelegateExecution execution) { diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/ContinueStatus.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/ContinueStatus.java new file mode 100644 index 00000000..b11e76f9 --- /dev/null +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/ContinueStatus.java @@ -0,0 +1,6 @@ +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service; + +public enum ContinueStatus +{ + SUCCESS, ERROR, VALIDATION_ERROR +} diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/DecryptData.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/receive/DecryptData.java similarity index 79% rename from codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/DecryptData.java rename to codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/receive/DecryptData.java index ca1a05ce..2ddfa39f 100644 --- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/DecryptData.java +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/receive/DecryptData.java @@ -1,6 +1,8 @@ -package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service; +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.receive; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_AES_RETURN_KEY; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_BUNDLE; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_PSEUDONYM; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER_VALUE_PSEUDONYM; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.PSEUDONYM_PLACEHOLDER; @@ -13,6 +15,7 @@ import org.camunda.bpm.engine.delegate.BpmnError; 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; @@ -57,11 +60,19 @@ protected void doExecute(DelegateExecution execution) throws BpmnError, Exceptio Optional pseudonym = getPseudonym(task); byte[] encrypted = (byte[]) execution.getVariable(BPMN_EXECUTION_VARIABLE_BUNDLE); - byte[] deencrypted = RsaAesGcmUtil.decrypt(crrKeyProvider.getPrivateKey(), encrypted); + byte[] decrypted = RsaAesGcmUtil.decrypt(crrKeyProvider.getPrivateKey(), encrypted); - Bundle bundle = fromByteArray(pseudonym.get(), deencrypted); + byte[] returnKey = new byte[32]; + byte[] bundleData = new byte[decrypted.length - 32]; + + System.arraycopy(decrypted, 0, returnKey, 0, 32); + System.arraycopy(decrypted, 32, bundleData, 0, decrypted.length - 32); + + Bundle bundle = fromByteArray(pseudonym.get(), bundleData); execution.setVariable(BPMN_EXECUTION_VARIABLE_BUNDLE, FhirResourceValues.create(bundle)); + execution.setVariable(BPMN_EXECUTION_VARIABLE_AES_RETURN_KEY, Variables.byteArrayValue(returnKey)); + execution.setVariable(BPMN_EXECUTION_VARIABLE_PSEUDONYM, Variables.stringValue(pseudonym.get())); } private Optional getPseudonym(Task task) diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/receive/DeleteValidationErrorForGth.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/receive/DeleteValidationErrorForGth.java new file mode 100644 index 00000000..ce155727 --- /dev/null +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/receive/DeleteValidationErrorForGth.java @@ -0,0 +1,37 @@ +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.receive; + +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_BINARY_URL; + +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; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.hl7.fhir.r4.model.Binary; +import org.hl7.fhir.r4.model.IdType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DeleteValidationErrorForGth extends AbstractServiceDelegate +{ + private static final Logger logger = LoggerFactory.getLogger(DeleteValidationErrorForGth.class); + + public DeleteValidationErrorForGth(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper) + { + super(clientProvider, taskHelper, readAccessHelper); + } + + @Override + protected void doExecute(DelegateExecution execution) throws BpmnError, Exception + { + String binaryUrl = (String) execution.getVariable(BPMN_EXECUTION_VARIABLE_BINARY_URL); + IdType binaryId = new IdType(binaryUrl); + + logger.info("Deleting validation error binary {} permanently", binaryId.getValue()); + getFhirWebserviceClientProvider().getLocalWebserviceClient().delete(Binary.class, binaryId.getIdPart()); + getFhirWebserviceClientProvider().getLocalWebserviceClient().deletePermanently(Binary.class, + binaryId.getIdPart()); + } +} diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/receive/DownloadDataFromGth.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/receive/DownloadDataFromGth.java new file mode 100644 index 00000000..c14efc8c --- /dev/null +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/receive/DownloadDataFromGth.java @@ -0,0 +1,131 @@ +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.receive; + +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_BUNDLE; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_RETURN_TARGET; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER_VALUE_DATA_REFERENCE; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_ORGANIZATION_ROLE; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_ORGANIZATION_ROLE_VALUE_DTS; +import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ENDPOINT_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_NUM_CODEX_CONSORTIUM; + +import java.io.InputStream; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Stream; + +import javax.ws.rs.core.MediaType; + +import org.camunda.bpm.engine.delegate.BpmnError; +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.task.TaskHelper; +import org.highmed.dsf.fhir.variables.Target; +import org.highmed.dsf.fhir.variables.TargetValues; +import org.highmed.fhir.client.FhirWebserviceClient; +import org.hl7.fhir.r4.model.Endpoint; +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.Task; +import org.hl7.fhir.r4.model.Type; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DownloadDataFromGth extends AbstractServiceDelegate +{ + private static final Logger logger = LoggerFactory.getLogger(DownloadDataFromGth.class); + + private final EndpointProvider endpointProvider; + private final String gthIdentifierValue; + + public DownloadDataFromGth(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, EndpointProvider endpointProvider, String gthIdentifierValue) + { + super(clientProvider, taskHelper, readAccessHelper); + + this.endpointProvider = endpointProvider; + this.gthIdentifierValue = gthIdentifierValue; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(endpointProvider, "endpointProvider"); + Objects.requireNonNull(gthIdentifierValue, "gthIdentifierValue"); + } + + @Override + protected void doExecute(DelegateExecution execution) throws BpmnError, Exception + { + Endpoint targetEndpoint = getEndpoint(CODESYSTEM_HIGHMED_ORGANIZATION_ROLE_VALUE_DTS, gthIdentifierValue); + execution.setVariable(BPMN_EXECUTION_VARIABLE_RETURN_TARGET, + TargetValues.create(Target.createUniDirectionalTarget(gthIdentifierValue, + getEndpointIdentifier(targetEndpoint), targetEndpoint.getAddress()))); + + Task task = getCurrentTaskFromExecutionVariables(); + + IdType id = getDataReference(task).map(ref -> new IdType(ref)).get(); + + FhirWebserviceClient client = getFhirWebserviceClientProvider().getWebserviceClient(id.getBaseUrl()); + + try (InputStream binary = readBinaryResource(client, id.getIdPart(), id.getVersionIdPart())) + { + byte[] encrypted = binary.readAllBytes(); + execution.setVariable(BPMN_EXECUTION_VARIABLE_BUNDLE, Variables.byteArrayValue(encrypted)); + } + } + + private Optional getDataReference(Task task) + { + return getInputParameterValues(task, CODESYSTEM_NUM_CODEX_DATA_TRANSFER, + CODESYSTEM_NUM_CODEX_DATA_TRANSFER_VALUE_DATA_REFERENCE, Reference.class).findFirst() + .map(Reference::getReference); + } + + private Stream getInputParameterValues(Task task, String system, String code, Class type) + { + return task.getInput().stream().filter(c -> type.isInstance(c.getValue())) + .filter(c -> c.getType().getCoding().stream() + .anyMatch(co -> system.equals(co.getSystem()) && code.equals(co.getCode()))) + .map(c -> type.cast(c.getValue())); + } + + private InputStream readBinaryResource(FhirWebserviceClient client, String id, String version) + { + try + { + logger.info("Reading binary from {} with id {}/{}", client.getBaseUrl(), id, version); + if (version != null && !version.isEmpty()) + return client.readBinary(id, version, MediaType.valueOf(MediaType.APPLICATION_OCTET_STREAM)); + else + return client.readBinary(id, MediaType.valueOf(MediaType.APPLICATION_OCTET_STREAM)); + } + catch (Exception e) + { + logger.warn("Error while reading Binary resoruce: " + e.getMessage(), e); + throw e; + } + } + + private Endpoint getEndpoint(String role, String identifier) + { + return endpointProvider + .getFirstConsortiumEndpoint(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_NUM_CODEX_CONSORTIUM, + CODESYSTEM_HIGHMED_ORGANIZATION_ROLE, role, identifier) + .get(); + } + + private String getEndpointIdentifier(Endpoint endpoint) + { + return endpoint.getIdentifier().stream() + .filter(i -> NAMINGSYSTEM_HIGHMED_ENDPOINT_IDENTIFIER.equals(i.getSystem())).findFirst() + .map(Identifier::getValue).get(); + } +} diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/receive/EncryptValidationError.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/receive/EncryptValidationError.java new file mode 100644 index 00000000..d76a497a --- /dev/null +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/receive/EncryptValidationError.java @@ -0,0 +1,70 @@ +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.receive; + +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_AES_RETURN_KEY; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_BUNDLE; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_PSEUDONYM; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.NAMING_SYSTEM_NUM_CODEX_CRR_PSEUDONYM; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.NAMING_SYSTEM_NUM_CODEX_DIC_PSEUDONYM; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.PSEUDONYM_PLACEHOLDER; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.RETURN_AAD; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Objects; + +import javax.crypto.spec.SecretKeySpec; + +import org.camunda.bpm.engine.delegate.BpmnError; +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.highmed.pseudonymization.crypto.AesGcmUtil; +import org.hl7.fhir.r4.model.Bundle; + +import ca.uhn.fhir.context.FhirContext; + +public class EncryptValidationError extends AbstractServiceDelegate +{ + private final FhirContext fhirContext; + + public EncryptValidationError(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, FhirContext fhirContext) + { + super(clientProvider, taskHelper, readAccessHelper); + + this.fhirContext = fhirContext; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(fhirContext, "fhirContext"); + } + + @Override + protected void doExecute(DelegateExecution execution) throws BpmnError, Exception + { + Bundle bundle = (Bundle) execution.getVariable(BPMN_EXECUTION_VARIABLE_BUNDLE); + String pseudonym = (String) execution.getVariable(BPMN_EXECUTION_VARIABLE_PSEUDONYM); + byte[] returnKey = (byte[]) execution.getVariable(BPMN_EXECUTION_VARIABLE_AES_RETURN_KEY); + + byte[] bundleData = toByteArray(pseudonym, bundle); + byte[] encrypted = AesGcmUtil.encrypt(bundleData, RETURN_AAD, new SecretKeySpec(returnKey, "AES")); + + execution.setVariable(BPMN_EXECUTION_VARIABLE_BUNDLE, Variables.byteArrayValue(encrypted)); + } + + private byte[] toByteArray(String pseudonym, Bundle bundle) throws IOException + { + String bundleString = fhirContext.newJsonParser().encodeResourceToString(bundle); + + return bundleString.replace(pseudonym, PSEUDONYM_PLACEHOLDER) + .replace(NAMING_SYSTEM_NUM_CODEX_DIC_PSEUDONYM, NAMING_SYSTEM_NUM_CODEX_CRR_PSEUDONYM) + .getBytes(StandardCharsets.UTF_8); + } +} diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/InsertDataIntoCodex.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/receive/InsertDataIntoCodex.java similarity index 56% rename from codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/InsertDataIntoCodex.java rename to codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/receive/InsertDataIntoCodex.java index b2edf4e7..9094cffe 100644 --- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/InsertDataIntoCodex.java +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/receive/InsertDataIntoCodex.java @@ -1,6 +1,8 @@ -package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service; +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.receive; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_BUNDLE; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_CONTINUE_STATUS; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_INSERT_INTO_CRR_FHIR_REPOSITORY_FAILED; import java.util.Objects; @@ -16,6 +18,8 @@ import ca.uhn.fhir.context.FhirContext; import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.client.GeccoClientFactory; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.client.fhir.ValidationException; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.ContinueStatus; public class InsertDataIntoCodex extends AbstractServiceDelegate { @@ -49,16 +53,28 @@ protected void doExecute(DelegateExecution execution) throws BpmnError, Exceptio try { - logger.info("Executing bundle against FHIR store ..."); - if (logger.isDebugEnabled()) - logger.debug("Received bundle: {}", fhirContext.newJsonParser().encodeResourceToString(bundle)); + try + { + logger.info("Executing bundle against FHIR store ..."); + if (logger.isDebugEnabled()) + logger.debug("Received bundle: {}", fhirContext.newJsonParser().encodeResourceToString(bundle)); - geccoClientFactory.getGeccoClient().getFhirClient().storeBundle(bundle); + geccoClientFactory.getGeccoClient().getFhirClient().storeBundle(bundle); + + execution.setVariable(BPMN_EXECUTION_VARIABLE_CONTINUE_STATUS, ContinueStatus.SUCCESS); + } + catch (ValidationException e) + { + logger.info("Validation error"); + execution.setVariable(BPMN_EXECUTION_VARIABLE_CONTINUE_STATUS, ContinueStatus.VALIDATION_ERROR); + execution.setVariable(BPMN_EXECUTION_VARIABLE_BUNDLE, e.getResultBundle()); + } } catch (Exception e) { - logger.warn("Error while executing bundle", e); - throw e; + logger.warn("Unable to insert data into CRR: {} - {}", e.getClass().getName(), e.getMessage()); + throw new BpmnError(CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_INSERT_INTO_CRR_FHIR_REPOSITORY_FAILED, + "Unable to insert data into CRR"); } } } diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/receive/LogError.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/receive/LogError.java new file mode 100644 index 00000000..12900e97 --- /dev/null +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/receive/LogError.java @@ -0,0 +1,79 @@ +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.receive; + +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_ERROR_CODE; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_ERROR_MESSAGE; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_ERROR_SOURCE; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_SOURCE_VALUE_CRR; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_VALIDATION_FAILED; + +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; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.hl7.fhir.r4.model.ResourceType; +import org.hl7.fhir.r4.model.Task; +import org.hl7.fhir.r4.model.Task.TaskOutputComponent; +import org.hl7.fhir.r4.model.Task.TaskStatus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.error.ErrorOutputParameterGenerator; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.logging.ErrorLogger; + +public class LogError extends AbstractServiceDelegate +{ + private static final Logger logger = LoggerFactory.getLogger(LogError.class); + + private final ErrorOutputParameterGenerator errorOutputParameterGenerator; + private final ErrorLogger errorLogger; + + public LogError(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, ErrorOutputParameterGenerator errorOutputParameterGenerator, + ErrorLogger errorLogger) + { + super(clientProvider, taskHelper, readAccessHelper); + + this.errorOutputParameterGenerator = errorOutputParameterGenerator; + this.errorLogger = errorLogger; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(errorOutputParameterGenerator, "errorOutputParameterGenerator"); + Objects.requireNonNull(errorLogger, "errorLogger"); + } + + @Override + protected void doExecute(DelegateExecution execution) throws BpmnError, Exception + { + logger.debug("Setting Task.status failed, adding error"); + + Task task = getLeadingTaskFromExecutionVariables(); + task.setStatus(TaskStatus.FAILED); + + String errorCode = (String) execution.getVariable(BPMN_EXECUTION_VARIABLE_ERROR_CODE); + String errorMessage = (String) execution.getVariable(BPMN_EXECUTION_VARIABLE_ERROR_MESSAGE); + String errorSource = (String) execution.getVariable(BPMN_EXECUTION_VARIABLE_ERROR_SOURCE); + + if (!CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_VALIDATION_FAILED.equals(errorCode)) + { + TaskOutputComponent output = errorOutputParameterGenerator.createError( + errorSource != null ? errorSource : CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_SOURCE_VALUE_CRR, + errorCode, errorMessage); + + task.addOutput(output); + + logger.warn("Error while transfering data to CRR: {} - {}", errorCode, errorMessage); + + errorLogger.logDataReceiveFailed(getLeadingTaskFromExecutionVariables().getIdElement() + .withServerBase(getFhirWebserviceClientProvider().getLocalBaseUrl(), ResourceType.Task.name())); + } + } +} diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/HandleNoConsentIdatMerge.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/receive/LogSuccess.java similarity index 58% rename from codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/HandleNoConsentIdatMerge.java rename to codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/receive/LogSuccess.java index b7e28f20..f1697d6d 100644 --- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/HandleNoConsentIdatMerge.java +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/receive/LogSuccess.java @@ -1,4 +1,4 @@ -package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service; +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.receive; import org.camunda.bpm.engine.delegate.BpmnError; import org.camunda.bpm.engine.delegate.DelegateExecution; @@ -9,20 +9,19 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class HandleNoConsentIdatMerge extends AbstractServiceDelegate +public class LogSuccess extends AbstractServiceDelegate { - private static final Logger logger = LoggerFactory.getLogger(HandleNoConsentIdatMerge.class); + private static final Logger logger = LoggerFactory.getLogger(LogSuccess.class); - public HandleNoConsentIdatMerge(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + public LogSuccess(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, ReadAccessHelper readAccessHelper) { super(clientProvider, taskHelper, readAccessHelper); } @Override - protected void doExecute(DelegateExecution arg0) throws BpmnError, Exception + protected void doExecute(DelegateExecution execution) throws BpmnError, Exception { - // TODO Auto-generated method stub - logger.debug("TODO"); + logger.info("All resources successfully added to CRR FHIR repository"); } } diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/receive/LogValidationError.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/receive/LogValidationError.java new file mode 100644 index 00000000..950c05c8 --- /dev/null +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/receive/LogValidationError.java @@ -0,0 +1,77 @@ +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.receive; + +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_BUNDLE; + +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; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.hl7.fhir.r4.model.Bundle; +import org.hl7.fhir.r4.model.OperationOutcome; +import org.hl7.fhir.r4.model.OperationOutcome.IssueSeverity; +import org.hl7.fhir.r4.model.ResourceType; +import org.hl7.fhir.r4.model.Task; +import org.hl7.fhir.r4.model.Task.TaskStatus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.error.ErrorOutputParameterGenerator; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.logging.ErrorLogger; + +public class LogValidationError extends AbstractServiceDelegate +{ + private static final Logger logger = LoggerFactory.getLogger(LogValidationError.class); + + private final ErrorOutputParameterGenerator errorOutputParameterGenerator; + private final ErrorLogger errorLogger; + + public LogValidationError(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, ErrorOutputParameterGenerator errorOutputParameterGenerator, + ErrorLogger errorLogger) + { + super(clientProvider, taskHelper, readAccessHelper); + + this.errorOutputParameterGenerator = errorOutputParameterGenerator; + this.errorLogger = errorLogger; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(errorOutputParameterGenerator, "errorOutputParameterGenerator"); + Objects.requireNonNull(errorLogger, "errorLogger"); + } + + @Override + protected void doExecute(DelegateExecution execution) throws BpmnError, Exception + { + logger.info("Validation error while adding resources to CRR FHIR repository"); + errorLogger.logValidationFailed(getLeadingTaskFromExecutionVariables().getIdElement() + .withServerBase(getFhirWebserviceClientProvider().getLocalBaseUrl(), ResourceType.Task.name())); + + logger.debug("Setting Task.status failed, adding validation errors"); + + Task task = getLeadingTaskFromExecutionVariables(); + task.setStatus(TaskStatus.FAILED); + + Bundle bundle = (Bundle) execution.getVariable(BPMN_EXECUTION_VARIABLE_BUNDLE); + + bundle.getEntry().stream() + .filter(e -> e.hasResponse() && e.getResponse().hasOutcome() + && (e.getResponse().getOutcome() instanceof OperationOutcome) + && ((OperationOutcome) e.getResponse().getOutcome()).getIssue().stream() + .anyMatch(i -> IssueSeverity.FATAL.equals(i.getSeverity()) + || IssueSeverity.ERROR.equals(i.getSeverity()))) + .forEach(entry -> + { + OperationOutcome outcome = (OperationOutcome) entry.getResponse().getOutcome(); + errorOutputParameterGenerator.createCrrValidationError(outcome).forEach(task::addOutput); + }); + } +} diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/receive/StoreValidationErrorForGth.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/receive/StoreValidationErrorForGth.java new file mode 100644 index 00000000..cc7d028d --- /dev/null +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/receive/StoreValidationErrorForGth.java @@ -0,0 +1,118 @@ +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.receive; + +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_BINARY_URL; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_BUNDLE; +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_DTS; +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.ConstantsBase.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_NUM_CODEX_CONSORTIUM; + +import java.util.Objects; + +import javax.ws.rs.core.MediaType; + +import org.camunda.bpm.engine.delegate.BpmnError; +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.task.TaskHelper; +import org.highmed.dsf.fhir.variables.Target; +import org.highmed.dsf.fhir.variables.TargetValues; +import org.hl7.fhir.r4.model.Binary; +import org.hl7.fhir.r4.model.Endpoint; +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.ResourceType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ca.uhn.fhir.context.FhirContext; + +public class StoreValidationErrorForGth extends AbstractServiceDelegate +{ + private static final Logger logger = LoggerFactory.getLogger(StoreValidationErrorForGth.class); + + private final EndpointProvider endpointProvider; + private final String gthIdentifierValue; + + public StoreValidationErrorForGth(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, EndpointProvider endpointProvider, String gthIdentifierValue) + { + super(clientProvider, taskHelper, readAccessHelper); + + this.endpointProvider = endpointProvider; + this.gthIdentifierValue = gthIdentifierValue; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(endpointProvider, "endpointProvider"); + Objects.requireNonNull(gthIdentifierValue, "gthIdentifierValue"); + } + + @Override + protected void doExecute(DelegateExecution execution) throws BpmnError, Exception + { + byte[] encrypted = (byte[]) execution.getVariable(BPMN_EXECUTION_VARIABLE_BUNDLE); + + String downloadUrl = saveBinary(encrypted, gthIdentifierValue); + + execution.setVariable(BPMN_EXECUTION_VARIABLE_BINARY_URL, Variables.stringValue(downloadUrl)); + + Endpoint targetEndpoint = getEndpoint(CODESYSTEM_HIGHMED_ORGANIZATION_ROLE_VALUE_DTS, gthIdentifierValue); + execution.setVariable(BPMN_EXECUTION_VARIABLE_TARGET, + TargetValues.create(Target.createUniDirectionalTarget(gthIdentifierValue, + getEndpointIdentifier(targetEndpoint), targetEndpoint.getAddress()))); + } + + protected String saveBinary(byte[] encryptedContent, String gthIdentifierValue) + { + Reference securityContext = new Reference(); + securityContext.setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue(gthIdentifierValue); + Binary binary = new Binary().setContentType(MediaType.APPLICATION_OCTET_STREAM) + .setSecurityContext(securityContext).setData(encryptedContent); + + IdType created = createBinaryResource(binary); + return new IdType(getFhirWebserviceClientProvider().getLocalBaseUrl(), ResourceType.Binary.name(), + created.getIdPart(), created.getVersionIdPart()).getValue(); + } + + private IdType createBinaryResource(Binary binary) + { + try + { + return getFhirWebserviceClientProvider().getLocalWebserviceClient().withMinimalReturn().create(binary); + } + catch (Exception e) + { + logger.debug("Binary to create {}", FhirContext.forR4().newJsonParser().encodeResourceToString(binary)); + logger.warn("Error while creating Binary resource: " + e.getMessage(), e); + throw e; + } + } + + private Endpoint getEndpoint(String role, String identifier) + { + return endpointProvider + .getFirstConsortiumEndpoint(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_NUM_CODEX_CONSORTIUM, + CODESYSTEM_HIGHMED_ORGANIZATION_ROLE, role, identifier) + .get(); + } + + private String getEndpointIdentifier(Endpoint endpoint) + { + return endpoint.getIdentifier().stream() + .filter(i -> NAMINGSYSTEM_HIGHMED_ENDPOINT_IDENTIFIER.equals(i.getSystem())).findFirst() + .map(Identifier::getValue).get(); + } +} diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/CheckConsent.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/CheckConsent.java similarity index 99% rename from codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/CheckConsent.java rename to codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/CheckConsent.java index eab645d4..1ede2081 100644 --- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/CheckConsent.java +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/CheckConsent.java @@ -1,4 +1,4 @@ -package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service; +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.send; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_IDAT_MERGE_GRANTED; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_PATIENT_REFERENCE; diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/CheckForError.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/CheckForError.java new file mode 100644 index 00000000..bfb75bae --- /dev/null +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/CheckForError.java @@ -0,0 +1,67 @@ +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.send; + +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_CONTINUE_STATUS; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_SEND; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_SEND_WITH_VALIDATION_ERROR; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.DataTransferProcessPluginDefinition.VERSION; + +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; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.hl7.fhir.r4.model.Task; +import org.hl7.fhir.r4.model.Task.TaskStatus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.ContinueStatus; + +public class CheckForError extends AbstractServiceDelegate +{ + private static final Logger logger = LoggerFactory.getLogger(CheckForError.class); + + public CheckForError(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper) + { + super(clientProvider, taskHelper, readAccessHelper); + } + + @Override + protected void doExecute(DelegateExecution execution) throws BpmnError, Exception + { + ContinueStatus continueStatus; + + // continue OK + if (currentTaskHasProfile(PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_SEND + "|" + VERSION)) + continueStatus = ContinueStatus.SUCCESS; + + // continue Validation ERROR + else if (currentTaskHasProfile(PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_SEND_WITH_VALIDATION_ERROR + "|" + VERSION)) + continueStatus = ContinueStatus.VALIDATION_ERROR; + + // continue ERROR / Timeout + else + continueStatus = ContinueStatus.VALIDATION_ERROR; + + execution.setVariable(BPMN_EXECUTION_VARIABLE_CONTINUE_STATUS, continueStatus); + + try + { + Task continueTask = getCurrentTaskFromExecutionVariables(); + continueTask.setStatus(TaskStatus.COMPLETED); + getFhirWebserviceClientProvider().getLocalWebserviceClient().update(continueTask); + } + catch (Exception e) + { + logger.warn("Unable to update continue Task from GTH", e); + } + } + + private boolean currentTaskHasProfile(String profile) + { + Task currentTask = getCurrentTaskFromExecutionVariables(); + return currentTask.getMeta().getProfile().stream().anyMatch(p -> profile.equals(p.getValue())); + } +} diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/DecryptValidationErrorFromGth.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/DecryptValidationErrorFromGth.java new file mode 100644 index 00000000..9aeb522a --- /dev/null +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/DecryptValidationErrorFromGth.java @@ -0,0 +1,69 @@ +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.send; + +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_AES_RETURN_KEY; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_BUNDLE; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_PATIENT_REFERENCE; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.PSEUDONYM_PLACEHOLDER; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.RETURN_AAD; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Objects; + +import javax.crypto.spec.SecretKeySpec; + +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; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.highmed.dsf.fhir.variables.FhirResourceValues; +import org.highmed.pseudonymization.crypto.AesGcmUtil; +import org.hl7.fhir.r4.model.Bundle; + +import ca.uhn.fhir.context.FhirContext; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.variables.PatientReference; + +public class DecryptValidationErrorFromGth extends AbstractServiceDelegate +{ + private final FhirContext fhirContext; + + public DecryptValidationErrorFromGth(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, FhirContext fhirContext) + { + super(clientProvider, taskHelper, readAccessHelper); + + this.fhirContext = fhirContext; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(fhirContext, "fhirContext"); + } + + @Override + protected void doExecute(DelegateExecution execution) throws BpmnError, Exception + { + String pseudonym = ((PatientReference) execution.getVariable(BPMN_EXECUTION_VARIABLE_PATIENT_REFERENCE)) + .getIdentifier().getValue(); + + byte[] returnKey = (byte[]) execution.getVariable(BPMN_EXECUTION_VARIABLE_AES_RETURN_KEY); + + byte[] encrypted = (byte[]) execution.getVariable(BPMN_EXECUTION_VARIABLE_BUNDLE); + byte[] decrypted = AesGcmUtil.decrypt(encrypted, RETURN_AAD, new SecretKeySpec(returnKey, "AES")); + + Bundle bundle = fromByteArray(pseudonym, decrypted); + + execution.setVariable(BPMN_EXECUTION_VARIABLE_BUNDLE, FhirResourceValues.create(bundle)); + } + + private Bundle fromByteArray(String pseudonym, byte[] bundle) throws IOException + { + String bundleString = new String(bundle, StandardCharsets.UTF_8).replace(PSEUDONYM_PLACEHOLDER, pseudonym); + return fhirContext.newJsonParser().parseResource(Bundle.class, bundleString); + } +} diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/DeleteDataForGth.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/DeleteDataForGth.java new file mode 100644 index 00000000..72f87991 --- /dev/null +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/DeleteDataForGth.java @@ -0,0 +1,37 @@ +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.send; + +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_BINARY_URL; + +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; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.hl7.fhir.r4.model.Binary; +import org.hl7.fhir.r4.model.IdType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DeleteDataForGth extends AbstractServiceDelegate +{ + private static final Logger logger = LoggerFactory.getLogger(DeleteDataForGth.class); + + public DeleteDataForGth(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper) + { + super(clientProvider, taskHelper, readAccessHelper); + } + + @Override + protected void doExecute(DelegateExecution execution) throws BpmnError, Exception + { + String binaryUrl = (String) execution.getVariable(BPMN_EXECUTION_VARIABLE_BINARY_URL); + IdType binaryId = new IdType(binaryUrl); + + logger.info("Deleting gecco data binary {} permanently", binaryId.getValue()); + getFhirWebserviceClientProvider().getLocalWebserviceClient().delete(Binary.class, binaryId.getIdPart()); + getFhirWebserviceClientProvider().getLocalWebserviceClient().deletePermanently(Binary.class, + binaryId.getIdPart()); + } +} diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/DownloadValidationErrorFromGth.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/DownloadValidationErrorFromGth.java new file mode 100644 index 00000000..f6c3046e --- /dev/null +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/DownloadValidationErrorFromGth.java @@ -0,0 +1,130 @@ +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.send; + +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_BUNDLE; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_RETURN_TARGET; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER_VALUE_DATA_REFERENCE; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_ORGANIZATION_ROLE; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_ORGANIZATION_ROLE_VALUE_DTS; +import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ENDPOINT_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_NUM_CODEX_CONSORTIUM; + +import java.io.InputStream; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Stream; + +import javax.ws.rs.core.MediaType; + +import org.camunda.bpm.engine.delegate.BpmnError; +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.task.TaskHelper; +import org.highmed.dsf.fhir.variables.Target; +import org.highmed.dsf.fhir.variables.TargetValues; +import org.highmed.fhir.client.FhirWebserviceClient; +import org.hl7.fhir.r4.model.Endpoint; +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.Task; +import org.hl7.fhir.r4.model.Type; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DownloadValidationErrorFromGth extends AbstractServiceDelegate +{ + private static final Logger logger = LoggerFactory.getLogger(DownloadValidationErrorFromGth.class); + + private final EndpointProvider endpointProvider; + private final String gthIdentifierValue; + + public DownloadValidationErrorFromGth(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, EndpointProvider endpointProvider, String gthIdentifierValue) + { + super(clientProvider, taskHelper, readAccessHelper); + + this.endpointProvider = endpointProvider; + this.gthIdentifierValue = gthIdentifierValue; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(endpointProvider, "endpointProvider"); + Objects.requireNonNull(gthIdentifierValue, "gthIdentifierValue"); + } + + @Override + protected void doExecute(DelegateExecution execution) throws BpmnError, Exception + { + Endpoint targetEndpoint = getEndpoint(CODESYSTEM_HIGHMED_ORGANIZATION_ROLE_VALUE_DTS, gthIdentifierValue); + execution.setVariable(BPMN_EXECUTION_VARIABLE_RETURN_TARGET, + TargetValues.create(Target.createUniDirectionalTarget(gthIdentifierValue, + getEndpointIdentifier(targetEndpoint), targetEndpoint.getAddress()))); + + Task task = getCurrentTaskFromExecutionVariables(); + IdType id = getDataReference(task).map(ref -> new IdType(ref)).get(); + + FhirWebserviceClient client = getFhirWebserviceClientProvider().getWebserviceClient(id.getBaseUrl()); + + try (InputStream binary = readBinaryResource(client, id.getIdPart(), id.getVersionIdPart())) + { + byte[] encrypted = binary.readAllBytes(); + execution.setVariable(BPMN_EXECUTION_VARIABLE_BUNDLE, Variables.byteArrayValue(encrypted)); + } + } + + private Optional getDataReference(Task task) + { + return getInputParameterValues(task, CODESYSTEM_NUM_CODEX_DATA_TRANSFER, + CODESYSTEM_NUM_CODEX_DATA_TRANSFER_VALUE_DATA_REFERENCE, Reference.class).findFirst() + .map(Reference::getReference); + } + + private Stream getInputParameterValues(Task task, String system, String code, Class type) + { + return task.getInput().stream().filter(c -> type.isInstance(c.getValue())) + .filter(c -> c.getType().getCoding().stream() + .anyMatch(co -> system.equals(co.getSystem()) && code.equals(co.getCode()))) + .map(c -> type.cast(c.getValue())); + } + + private InputStream readBinaryResource(FhirWebserviceClient client, String id, String version) + { + try + { + logger.info("Reading binary from {} with id {}/{}", client.getBaseUrl(), id, version); + if (version != null && !version.isEmpty()) + return client.readBinary(id, version, MediaType.valueOf(MediaType.APPLICATION_OCTET_STREAM)); + else + return client.readBinary(id, MediaType.valueOf(MediaType.APPLICATION_OCTET_STREAM)); + } + catch (Exception e) + { + logger.warn("Error while reading Binary resoruce: " + e.getMessage(), e); + throw e; + } + } + + private Endpoint getEndpoint(String role, String identifier) + { + return endpointProvider + .getFirstConsortiumEndpoint(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_NUM_CODEX_CONSORTIUM, + CODESYSTEM_HIGHMED_ORGANIZATION_ROLE, role, identifier) + .get(); + } + + private String getEndpointIdentifier(Endpoint endpoint) + { + return endpoint.getIdentifier().stream() + .filter(i -> NAMINGSYSTEM_HIGHMED_ENDPOINT_IDENTIFIER.equals(i.getSystem())).findFirst() + .map(Identifier::getValue).get(); + } +} diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/EncryptData.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/EncryptData.java similarity index 84% rename from codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/EncryptData.java rename to codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/EncryptData.java index fe003d2c..6d1f7dd8 100644 --- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/EncryptData.java +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/EncryptData.java @@ -1,5 +1,6 @@ -package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service; +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.send; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_AES_RETURN_KEY; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_BUNDLE; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_PATIENT_REFERENCE; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.NAMING_SYSTEM_NUM_CODEX_CRR_PSEUDONYM; @@ -17,6 +18,7 @@ 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.crypto.AesGcmUtil; import org.hl7.fhir.r4.model.Bundle; import ca.uhn.fhir.context.FhirContext; @@ -55,9 +57,15 @@ protected void doExecute(DelegateExecution execution) throws BpmnError, Exceptio Bundle bundle = (Bundle) execution.getVariable(BPMN_EXECUTION_VARIABLE_BUNDLE); byte[] bundleData = toByteArray(pseudonym, bundle); + byte[] returnKey = AesGcmUtil.generateAES256Key().getEncoded(); - byte[] encrypted = RsaAesGcmUtil.encrypt(crrKeyProvider.getPublicKey(), bundleData); + byte[] data = new byte[returnKey.length + bundleData.length]; + System.arraycopy(returnKey, 0, data, 0, returnKey.length); + System.arraycopy(bundleData, 0, data, returnKey.length, bundleData.length); + byte[] encrypted = RsaAesGcmUtil.encrypt(crrKeyProvider.getPublicKey(), data); + + execution.setVariable(BPMN_EXECUTION_VARIABLE_AES_RETURN_KEY, Variables.byteArrayValue(returnKey)); execution.setVariable(BPMN_EXECUTION_VARIABLE_BUNDLE, Variables.byteArrayValue(encrypted)); } diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/ExtractPatientReference.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/ExtractPatientReference.java similarity index 99% rename from codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/ExtractPatientReference.java rename to codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/ExtractPatientReference.java index 292b243a..97698e0a 100644 --- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/ExtractPatientReference.java +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/ExtractPatientReference.java @@ -1,4 +1,4 @@ -package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service; +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.send; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_PATIENT_REFERENCE; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER; diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/LogError.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/LogError.java new file mode 100644 index 00000000..2ce4145c --- /dev/null +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/LogError.java @@ -0,0 +1,79 @@ +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.send; + +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_ERROR_CODE; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_ERROR_MESSAGE; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_ERROR_SOURCE; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_SOURCE_VALUE_MEDIC; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_VALIDATION_FAILED; + +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; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.hl7.fhir.r4.model.ResourceType; +import org.hl7.fhir.r4.model.Task; +import org.hl7.fhir.r4.model.Task.TaskOutputComponent; +import org.hl7.fhir.r4.model.Task.TaskStatus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.error.ErrorOutputParameterGenerator; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.logging.ErrorLogger; + +public class LogError extends AbstractServiceDelegate +{ + private static final Logger logger = LoggerFactory.getLogger(LogError.class); + + private final ErrorOutputParameterGenerator errorOutputParameterGenerator; + private final ErrorLogger errorLogger; + + public LogError(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, ErrorOutputParameterGenerator errorOutputParameterGenerator, + ErrorLogger errorLogger) + { + super(clientProvider, taskHelper, readAccessHelper); + + this.errorOutputParameterGenerator = errorOutputParameterGenerator; + this.errorLogger = errorLogger; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(errorOutputParameterGenerator, "errorOutputParameterGenerator"); + Objects.requireNonNull(errorLogger, "errorLogger"); + } + + @Override + protected void doExecute(DelegateExecution execution) throws BpmnError, Exception + { + logger.debug("Setting Task.status failed, adding error"); + + Task task = getLeadingTaskFromExecutionVariables(); + task.setStatus(TaskStatus.FAILED); + + String errorCode = (String) execution.getVariable(BPMN_EXECUTION_VARIABLE_ERROR_CODE); + String errorMessage = (String) execution.getVariable(BPMN_EXECUTION_VARIABLE_ERROR_MESSAGE); + String errorSource = (String) execution.getVariable(BPMN_EXECUTION_VARIABLE_ERROR_SOURCE); + + if (!CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_VALIDATION_FAILED.equals(errorCode)) + { + TaskOutputComponent output = errorOutputParameterGenerator.createError( + errorSource != null ? errorSource : CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_SOURCE_VALUE_MEDIC, + errorCode, errorMessage); + + task.addOutput(output); + + logger.warn("Error while transfering data to CRR: {} - {}", errorCode, errorMessage); + + errorLogger.logDataReceiveFailed(getLeadingTaskFromExecutionVariables().getIdElement() + .withServerBase(getFhirWebserviceClientProvider().getLocalBaseUrl(), ResourceType.Task.name())); + } + } +} diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/HandleNoConsentUsageAndTransfer.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/LogSuccess.java similarity index 57% rename from codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/HandleNoConsentUsageAndTransfer.java rename to codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/LogSuccess.java index b0e8f4ec..193b2a43 100644 --- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/HandleNoConsentUsageAndTransfer.java +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/LogSuccess.java @@ -1,4 +1,4 @@ -package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service; +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.send; import org.camunda.bpm.engine.delegate.BpmnError; import org.camunda.bpm.engine.delegate.DelegateExecution; @@ -9,20 +9,19 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class HandleNoConsentUsageAndTransfer extends AbstractServiceDelegate +public class LogSuccess extends AbstractServiceDelegate { - private static final Logger logger = LoggerFactory.getLogger(HandleNoConsentUsageAndTransfer.class); + private static final Logger logger = LoggerFactory.getLogger(LogSuccess.class); - public HandleNoConsentUsageAndTransfer(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + public LogSuccess(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, ReadAccessHelper readAccessHelper) { super(clientProvider, taskHelper, readAccessHelper); } @Override - protected void doExecute(DelegateExecution arg0) throws BpmnError, Exception + protected void doExecute(DelegateExecution execution) throws BpmnError, Exception { - // TODO Auto-generated method stub - logger.debug("TODO"); + logger.info("All resources successfully added to CRR FHIR repository"); } } diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/LogValidationError.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/LogValidationError.java new file mode 100644 index 00000000..a7ac6852 --- /dev/null +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/LogValidationError.java @@ -0,0 +1,148 @@ +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.send; + +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_BUNDLE; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_SOURCE_IDS_BY_BUNDLE_UUID; + +import java.util.Map; +import java.util.Objects; +import java.util.Optional; + +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; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.hl7.fhir.r4.model.Bundle; +import org.hl7.fhir.r4.model.IdType; +import org.hl7.fhir.r4.model.OperationOutcome; +import org.hl7.fhir.r4.model.OperationOutcome.IssueSeverity; +import org.hl7.fhir.r4.model.OperationOutcome.OperationOutcomeIssueComponent; +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.TaskStatus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.error.ErrorOutputParameterGenerator; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.logging.ErrorLogger; + +public class LogValidationError extends AbstractServiceDelegate +{ + private static final Logger logger = LoggerFactory.getLogger(LogValidationError.class); + + private final ErrorOutputParameterGenerator errorOutputParameterGenerator; + private final ErrorLogger errorLogger; + + public LogValidationError(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, ErrorOutputParameterGenerator errorOutputParameterGenerator, + ErrorLogger errorLogger) + { + super(clientProvider, taskHelper, readAccessHelper); + + this.errorOutputParameterGenerator = errorOutputParameterGenerator; + this.errorLogger = errorLogger; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(errorOutputParameterGenerator, "errorOutputParameterGenerator"); + Objects.requireNonNull(errorLogger, "errorLogger"); + } + + @Override + protected void doExecute(DelegateExecution execution) throws BpmnError, Exception + { + logger.info("Validation error while adding resources to CRR FHIR repository"); + + Bundle bundle = (Bundle) execution.getVariable(BPMN_EXECUTION_VARIABLE_BUNDLE); + + @SuppressWarnings("unchecked") + Map sourceIdsByBundleUuid = (Map) execution + .getVariable(BPMN_EXECUTION_VARIABLE_SOURCE_IDS_BY_BUNDLE_UUID); + + errorLogger.logValidationFailedRemote(getLeadingTaskFromExecutionVariables().getIdElement() + .withServerBase(getFhirWebserviceClientProvider().getLocalBaseUrl(), ResourceType.Task.name())); + logValidationDetails(bundle, sourceIdsByBundleUuid); + addErrorsToTask(bundle, sourceIdsByBundleUuid); + } + + private void addErrorsToTask(Bundle bundle, Map sourceIdsByBundleUuid) + { + logger.debug("Setting Task.status failed, adding validation errors"); + + Task task = getLeadingTaskFromExecutionVariables(); + task.setStatus(TaskStatus.FAILED); + + bundle.getEntry().stream() + .filter(e -> e.hasResponse() && e.getResponse().hasOutcome() + && (e.getResponse().getOutcome() instanceof OperationOutcome) + && ((OperationOutcome) e.getResponse().getOutcome()).getIssue().stream() + .anyMatch(i -> IssueSeverity.FATAL.equals(i.getSeverity()) + || IssueSeverity.ERROR.equals(i.getSeverity()))) + .forEach(entry -> + { + IdType sourceId = Optional.ofNullable(sourceIdsByBundleUuid.get(entry.getFullUrl())) + .map(IdType::new).orElse(null); + OperationOutcome outcome = (OperationOutcome) entry.getResponse().getOutcome(); + + errorOutputParameterGenerator.createCrrValidationError(sourceId, outcome).forEach(task::addOutput); + }); + } + + private void logValidationDetails(Bundle bundle, Map sourceIdsByBundleUuid) + { + bundle.getEntry().stream().filter(e -> e.hasResponse() && e.getResponse().hasOutcome() + && (e.getResponse().getOutcome() instanceof OperationOutcome)).forEach(entry -> + { + IdType sourceId = Optional.ofNullable(sourceIdsByBundleUuid.get(entry.getFullUrl())) + .map(IdType::new).orElse(null); + OperationOutcome outcome = (OperationOutcome) entry.getResponse().getOutcome(); + + outcome.getIssue().forEach(i -> logValidationDetails(sourceId, i)); + }); + } + + private void logValidationDetails(IdType sourceId, OperationOutcomeIssueComponent i) + { + if (i.getSeverity() != null) + { + switch (i.getSeverity()) + { + case FATAL: + case ERROR: + logger.error( + "CRR validation error for {}{}: {}", sourceId.getValue(), i.getLocation().stream() + .map(StringType::getValue).findFirst().map(l -> " location " + l).orElse(""), + i.getDiagnostics()); + break; + case WARNING: + logger.warn( + "CRR validation warning for {}{}: {}", sourceId.getValue(), i.getLocation().stream() + .map(StringType::getValue).findFirst().map(l -> " location " + l).orElse(""), + i.getDiagnostics()); + break; + case INFORMATION: + case NULL: + default: + logger.info( + "CRR validation info for {}{}: {}", sourceId.getValue(), i.getLocation().stream() + .map(StringType::getValue).findFirst().map(l -> " location " + l).orElse(""), + i.getDiagnostics()); + break; + } + } + else + { + logger.info( + "Validation info for {}{}: {}", sourceId.getValue(), i.getLocation().stream() + .map(StringType::getValue).findFirst().map(l -> " location " + l).orElse(""), + i.getDiagnostics()); + } + } + +} diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/ReadData.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/ReadData.java similarity index 99% rename from codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/ReadData.java rename to codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/ReadData.java index b416c717..327349f9 100644 --- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/ReadData.java +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/ReadData.java @@ -1,4 +1,4 @@ -package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service; +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.send; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_BUNDLE; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_PATIENT_REFERENCE; @@ -72,8 +72,7 @@ public class ReadData extends AbstractServiceDelegate private final GeccoClientFactory geccoClientFactory; public ReadData(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, - ReadAccessHelper readAccessHelper, FhirContext fhirContext, GeccoClientFactory geccoClientFactory, - String geccoServerBase) + ReadAccessHelper readAccessHelper, FhirContext fhirContext, GeccoClientFactory geccoClientFactory) { super(clientProvider, taskHelper, readAccessHelper); diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/ResolvePseudonym.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/ResolvePsn.java similarity index 85% rename from codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/ResolvePseudonym.java rename to codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/ResolvePsn.java index b1f957f2..93f2d97e 100644 --- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/ResolvePseudonym.java +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/ResolvePsn.java @@ -1,6 +1,8 @@ -package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service; +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.send; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_PATIENT_REFERENCE; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_NO_DIC_PSEUDONYM_FOR_BLOOMFILTER; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_PATIENT_NOT_FOUND; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.IDENTIFIER_NUM_CODEX_DIC_PSEUDONYM_TYPE_CODE; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.IDENTIFIER_NUM_CODEX_DIC_PSEUDONYM_TYPE_SYSTEM; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.NAMING_SYSTEM_NUM_CODEX_BLOOM_FILTER; @@ -9,6 +11,7 @@ import java.util.Objects; import java.util.Optional; +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; @@ -26,14 +29,14 @@ import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.variables.PatientReferenceValues; import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.variables.PatientReferenceValues.PatientReferenceValue; -public class ResolvePseudonym extends AbstractServiceDelegate implements InitializingBean +public class ResolvePsn extends AbstractServiceDelegate implements InitializingBean { - private static final Logger logger = LoggerFactory.getLogger(ResolvePseudonym.class); + private static final Logger logger = LoggerFactory.getLogger(ResolvePsn.class); private final GeccoClientFactory geccoClientFactory; private final FttpClientFactory fttpClientFactory; - public ResolvePseudonym(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + public ResolvePsn(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, ReadAccessHelper readAccessHelper, GeccoClientFactory geccoClientFactory, FttpClientFactory fttpClientFactory) { @@ -75,7 +78,8 @@ protected void doExecute(DelegateExecution execution) throws Exception }, () -> { logger.warn("Patient {} not found", reference); - throw new RuntimeException("Patient " + reference + " not found"); + throw new BpmnError(CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_PATIENT_NOT_FOUND, + "Patient at " + reference + " not found"); }); } @@ -116,7 +120,9 @@ private String getBloomFilter(Patient patient) private String resolveBloomFilter(String bloomFilter) { return fttpClientFactory.getFttpClient().getDicPseudonym(bloomFilter) - .orElseThrow(() -> new RuntimeException("Could not get DIC pseudonym with bloom filter")); + .orElseThrow(() -> new BpmnError( + CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_NO_DIC_PSEUDONYM_FOR_BLOOMFILTER, + "Unable to get DIC pseudonym for given BloomFilter")); } private void updatePatient(Patient patient) diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/SetNoConsentIdatMergeError.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/SetNoConsentIdatMergeError.java new file mode 100644 index 00000000..7f80b24b --- /dev/null +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/SetNoConsentIdatMergeError.java @@ -0,0 +1,28 @@ +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.send; + +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; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SetNoConsentIdatMergeError extends AbstractServiceDelegate +{ + private static final Logger logger = LoggerFactory.getLogger(SetNoConsentIdatMergeError.class); + + public SetNoConsentIdatMergeError(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper) + { + super(clientProvider, taskHelper, readAccessHelper); + } + + @Override + protected void doExecute(DelegateExecution execution) throws BpmnError, Exception + { + // TODO set Variable errorCode, errorMessage + logger.debug("TODO set Variable errorCode, errorMessage"); + } +} diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/SetNoConsentUsageAndTransferError.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/SetNoConsentUsageAndTransferError.java new file mode 100644 index 00000000..e2a15c73 --- /dev/null +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/SetNoConsentUsageAndTransferError.java @@ -0,0 +1,28 @@ +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.send; + +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; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SetNoConsentUsageAndTransferError extends AbstractServiceDelegate +{ + private static final Logger logger = LoggerFactory.getLogger(SetNoConsentUsageAndTransferError.class); + + public SetNoConsentUsageAndTransferError(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper) + { + super(clientProvider, taskHelper, readAccessHelper); + } + + @Override + protected void doExecute(DelegateExecution execution) throws BpmnError, Exception + { + // TODO set Variable errorCode, errorMessage + logger.debug("TODO set Variable errorCode, errorMessage"); + } +} diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/SetTimeoutError.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/SetTimeoutError.java new file mode 100644 index 00000000..c9a1b788 --- /dev/null +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/SetTimeoutError.java @@ -0,0 +1,30 @@ +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.send; + +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_ERROR_CODE; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_ERROR_MESSAGE; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_TIMEOUT_WAITING_FOR_RESPONSE_FROM_GTH; + +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; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; + +public class SetTimeoutError extends AbstractServiceDelegate +{ + public SetTimeoutError(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper) + { + super(clientProvider, taskHelper, readAccessHelper); + } + + @Override + protected void doExecute(DelegateExecution execution) throws BpmnError, Exception + { + execution.setVariable(BPMN_EXECUTION_VARIABLE_ERROR_CODE, + CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_TIMEOUT_WAITING_FOR_RESPONSE_FROM_GTH); + execution.setVariable(BPMN_EXECUTION_VARIABLE_ERROR_MESSAGE, + "Timeout while waiting for continue task from GTH"); + } +} diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/StoreDataForTransferHub.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/StoreDataForGth.java similarity index 95% rename from codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/StoreDataForTransferHub.java rename to codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/StoreDataForGth.java index 88017ae8..135884e3 100644 --- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/StoreDataForTransferHub.java +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/StoreDataForGth.java @@ -1,4 +1,4 @@ -package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service; +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.send; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_BINARY_URL; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_BUNDLE; @@ -34,14 +34,14 @@ import ca.uhn.fhir.context.FhirContext; -public class StoreDataForTransferHub extends AbstractServiceDelegate +public class StoreDataForGth extends AbstractServiceDelegate { - private static final Logger logger = LoggerFactory.getLogger(StoreDataForTransferHub.class); + private static final Logger logger = LoggerFactory.getLogger(StoreDataForGth.class); private final EndpointProvider endpointProvider; private final String geccoTransferHubIdentifierValue; - public StoreDataForTransferHub(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + public StoreDataForGth(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, ReadAccessHelper readAccessHelper, EndpointProvider endpointProvider, String geccoTransferHubIdentifierValue) { diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/ValidateData.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/ValidateData.java similarity index 84% rename from codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/ValidateData.java rename to codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/ValidateData.java index 9f9af31f..205323cb 100644 --- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/ValidateData.java +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/send/ValidateData.java @@ -1,9 +1,12 @@ -package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service; +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.send; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_BUNDLE; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_SOURCE_IDS_BY_BUNDLE_UUID; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_VALIDATION_FAILED; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.HAPI_USER_DATA_SOURCE_ID_ELEMENT; +import java.util.HashMap; +import java.util.Map; import java.util.Objects; import org.camunda.bpm.engine.delegate.BpmnError; @@ -20,9 +23,9 @@ import org.hl7.fhir.r4.model.OperationOutcome; import org.hl7.fhir.r4.model.OperationOutcome.IssueSeverity; import org.hl7.fhir.r4.model.OperationOutcome.OperationOutcomeIssueComponent; +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.TaskStatus; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -65,6 +68,12 @@ protected void doExecute(DelegateExecution execution) throws BpmnError, Exceptio if (!bundleValidatorSupplier.isEnabled()) { logger.warn("Validation disabled, skipping validation. Modify configuration to enable validation"); + + Bundle bundle = (Bundle) execution.getVariable(BPMN_EXECUTION_VARIABLE_BUNDLE); + + Map sourceIdsByBundleUuid = removeValidationResultsCollectSourceIdsIntoMap(bundle); + execution.setVariable(BPMN_EXECUTION_VARIABLE_SOURCE_IDS_BY_BUNDLE_UUID, sourceIdsByBundleUuid); + return; } @@ -103,10 +112,10 @@ protected void doExecute(DelegateExecution execution) throws BpmnError, Exceptio logger.error("Validation of transfer bundle failed, {} resource{} with error", resourcesWithErrorCount, resourcesWithErrorCount != 1 ? "s" : ""); - addErrorsToTaskAndSetFailed(bundle); - errorLogger.logValidationFailed(getLeadingTaskFromExecutionVariables().getIdElement() - .withServerBase(getFhirWebserviceClientProvider().getLocalBaseUrl(), - getLeadingTaskFromExecutionVariables().getIdElement().getResourceType())); + addErrorsToTask(bundle); + errorLogger.logValidationFailedLocal( + getLeadingTaskFromExecutionVariables().getIdElement().withServerBase( + getFhirWebserviceClientProvider().getLocalBaseUrl(), ResourceType.Task.name())); throw new BpmnError(CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_VALIDATION_FAILED, "Validation of transfer bundle failed, " + resourcesWithErrorCount + " resource" @@ -114,7 +123,9 @@ protected void doExecute(DelegateExecution execution) throws BpmnError, Exceptio } else { - removeValidationResultsAndUserData(bundle); + Map sourceIdsByBundleUuid = removeValidationResultsCollectSourceIdsIntoMap( + bundle); + execution.setVariable(BPMN_EXECUTION_VARIABLE_SOURCE_IDS_BY_BUNDLE_UUID, sourceIdsByBundleUuid); } } } @@ -180,11 +191,10 @@ private void logValidationDetails(IdType sourceId, OperationOutcomeIssueComponen } } - private void addErrorsToTaskAndSetFailed(Bundle bundle) + private void addErrorsToTask(Bundle bundle) { Task task = getLeadingTaskFromExecutionVariables(); - task.setStatus(TaskStatus.FAILED); bundle.getEntry().stream() .filter(e -> e.hasResponse() && e.getResponse().hasOutcome() && (e.getResponse().getOutcome() instanceof OperationOutcome) @@ -201,13 +211,19 @@ private void addErrorsToTaskAndSetFailed(Bundle bundle) }); } - private void removeValidationResultsAndUserData(Bundle bundle) + private Map removeValidationResultsCollectSourceIdsIntoMap(Bundle bundle) { + Map sourceIdByBundleUuid = new HashMap<>(); bundle.getEntry().stream().forEach(e -> { + IdType sourceId = (IdType) e.getUserData(HAPI_USER_DATA_SOURCE_ID_ELEMENT); + sourceIdByBundleUuid.put(e.getFullUrl(), sourceId.getValue()); + e.clearUserData(HAPI_USER_DATA_SOURCE_ID_ELEMENT); e.setResponse(null); }); execution.setVariable(BPMN_EXECUTION_VARIABLE_BUNDLE, FhirResourceValues.create(bundle)); + + return sourceIdByBundleUuid; } } diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/translate/CheckForError.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/translate/CheckForError.java new file mode 100644 index 00000000..1845e29c --- /dev/null +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/translate/CheckForError.java @@ -0,0 +1,68 @@ +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.translate; + +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_CONTINUE_STATUS; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_TRANSLATE; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_TRANSLATE_WITH_VALIDATION_ERROR; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.DataTransferProcessPluginDefinition.VERSION; + +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; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.hl7.fhir.r4.model.Task; +import org.hl7.fhir.r4.model.Task.TaskStatus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.ContinueStatus; + +public class CheckForError extends AbstractServiceDelegate +{ + private static final Logger logger = LoggerFactory.getLogger(CheckForError.class); + + public CheckForError(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper) + { + super(clientProvider, taskHelper, readAccessHelper); + } + + @Override + protected void doExecute(DelegateExecution execution) throws BpmnError, Exception + { + ContinueStatus continueStatus; + + // continue OK + if (currentTaskHasProfile(PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_TRANSLATE + "|" + VERSION)) + continueStatus = ContinueStatus.SUCCESS; + + // continue Validation ERROR + else if (currentTaskHasProfile( + PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_TRANSLATE_WITH_VALIDATION_ERROR + "|" + VERSION)) + continueStatus = ContinueStatus.VALIDATION_ERROR; + + // continue ERROR / Timeout + else + continueStatus = ContinueStatus.VALIDATION_ERROR; + + execution.setVariable(BPMN_EXECUTION_VARIABLE_CONTINUE_STATUS, continueStatus); + + try + { + Task continueTask = getCurrentTaskFromExecutionVariables(); + continueTask.setStatus(TaskStatus.COMPLETED); + getFhirWebserviceClientProvider().getLocalWebserviceClient().update(continueTask); + } + catch (Exception e) + { + logger.warn("Unable to update continue Task from CRR", e); + } + } + + private boolean currentTaskHasProfile(String profile) + { + Task currentTask = getCurrentTaskFromExecutionVariables(); + return currentTask.getMeta().getProfile().stream().anyMatch(p -> profile.equals(p.getValue())); + } +} diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/translate/DeleteDataForCrr.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/translate/DeleteDataForCrr.java new file mode 100644 index 00000000..4c06a01b --- /dev/null +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/translate/DeleteDataForCrr.java @@ -0,0 +1,37 @@ +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.translate; + +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_BINARY_URL; + +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; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.hl7.fhir.r4.model.Binary; +import org.hl7.fhir.r4.model.IdType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DeleteDataForCrr extends AbstractServiceDelegate +{ + private static final Logger logger = LoggerFactory.getLogger(DeleteDataForCrr.class); + + public DeleteDataForCrr(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper) + { + super(clientProvider, taskHelper, readAccessHelper); + } + + @Override + protected void doExecute(DelegateExecution execution) throws BpmnError, Exception + { + String binaryUrl = (String) execution.getVariable(BPMN_EXECUTION_VARIABLE_BINARY_URL); + IdType binaryId = new IdType(binaryUrl); + + logger.info("Deleting gecco data binary {} permanently", binaryId.getValue()); + getFhirWebserviceClientProvider().getLocalWebserviceClient().delete(Binary.class, binaryId.getIdPart()); + getFhirWebserviceClientProvider().getLocalWebserviceClient().deletePermanently(Binary.class, + binaryId.getIdPart()); + } +} diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/translate/DeleteValidationErrorForDic.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/translate/DeleteValidationErrorForDic.java new file mode 100644 index 00000000..fac55396 --- /dev/null +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/translate/DeleteValidationErrorForDic.java @@ -0,0 +1,37 @@ +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.translate; + +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_BINARY_URL; + +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; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.hl7.fhir.r4.model.Binary; +import org.hl7.fhir.r4.model.IdType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DeleteValidationErrorForDic extends AbstractServiceDelegate +{ + private static final Logger logger = LoggerFactory.getLogger(DeleteValidationErrorForDic.class); + + public DeleteValidationErrorForDic(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper) + { + super(clientProvider, taskHelper, readAccessHelper); + } + + @Override + protected void doExecute(DelegateExecution execution) throws BpmnError, Exception + { + String binaryUrl = (String) execution.getVariable(BPMN_EXECUTION_VARIABLE_BINARY_URL); + IdType binaryId = new IdType(binaryUrl); + + logger.info("Deleting validation error binary {} permanently", binaryId.getValue()); + getFhirWebserviceClientProvider().getLocalWebserviceClient().delete(Binary.class, binaryId.getIdPart()); + getFhirWebserviceClientProvider().getLocalWebserviceClient().deletePermanently(Binary.class, + binaryId.getIdPart()); + } +} diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/DownloadDataFromTransferHub.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/translate/DownloadDataFromDic.java similarity index 58% rename from codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/DownloadDataFromTransferHub.java rename to codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/translate/DownloadDataFromDic.java index d0edd430..7c2d8780 100644 --- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/DownloadDataFromTransferHub.java +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/translate/DownloadDataFromDic.java @@ -1,10 +1,16 @@ -package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service; +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.translate; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_BUNDLE; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_RETURN_TARGET; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER_VALUE_DATA_REFERENCE; +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_NUM_CODEX_CONSORTIUM; import java.io.InputStream; +import java.util.Objects; import java.util.Optional; import java.util.stream.Stream; @@ -16,29 +22,52 @@ 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.highmed.fhir.client.FhirWebserviceClient; +import org.hl7.fhir.r4.model.Endpoint; 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.Task; import org.hl7.fhir.r4.model.Type; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class DownloadDataFromTransferHub extends AbstractServiceDelegate +public class DownloadDataFromDic extends AbstractServiceDelegate { - private static final Logger logger = LoggerFactory.getLogger(DownloadDataFromTransferHub.class); + private static final Logger logger = LoggerFactory.getLogger(DownloadDataFromDic.class); - public DownloadDataFromTransferHub(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, - ReadAccessHelper readAccessHelper) + private final EndpointProvider endpointProvider; + + public DownloadDataFromDic(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 BpmnError, Exception { Task task = getCurrentTaskFromExecutionVariables(); + String dicIdentifierValue = task.getRequester().getIdentifier().getValue(); + + Endpoint targetEndpoint = getEndpoint(CODESYSTEM_HIGHMED_ORGANIZATION_ROLE_VALUE_MEDIC, dicIdentifierValue); + execution.setVariable(BPMN_EXECUTION_VARIABLE_RETURN_TARGET, + TargetValues.create(Target.createUniDirectionalTarget(dicIdentifierValue, + getEndpointIdentifier(targetEndpoint), targetEndpoint.getAddress()))); IdType id = getDataReference(task).map(ref -> new IdType(ref)).get(); @@ -82,4 +111,19 @@ private InputStream readBinaryResource(FhirWebserviceClient client, String id, S throw e; } } + + private Endpoint getEndpoint(String role, String identifier) + { + return endpointProvider + .getFirstConsortiumEndpoint(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_NUM_CODEX_CONSORTIUM, + CODESYSTEM_HIGHMED_ORGANIZATION_ROLE, role, identifier) + .get(); + } + + private String getEndpointIdentifier(Endpoint endpoint) + { + return endpoint.getIdentifier().stream() + .filter(i -> NAMINGSYSTEM_HIGHMED_ENDPOINT_IDENTIFIER.equals(i.getSystem())).findFirst() + .map(Identifier::getValue).get(); + } } diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/DownloadDataFromDic.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/translate/DownloadValidationErrorFromCrr.java similarity index 92% rename from codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/DownloadDataFromDic.java rename to codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/translate/DownloadValidationErrorFromCrr.java index 484b24a1..3dc84b43 100644 --- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/DownloadDataFromDic.java +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/translate/DownloadValidationErrorFromCrr.java @@ -1,4 +1,4 @@ -package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service; +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.translate; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_BUNDLE; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER; @@ -25,11 +25,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class DownloadDataFromDic extends AbstractServiceDelegate +public class DownloadValidationErrorFromCrr extends AbstractServiceDelegate { - private static final Logger logger = LoggerFactory.getLogger(DownloadDataFromDic.class); + private static final Logger logger = LoggerFactory.getLogger(DownloadValidationErrorFromCrr.class); - public DownloadDataFromDic(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + public DownloadValidationErrorFromCrr(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, ReadAccessHelper readAccessHelper) { super(clientProvider, taskHelper, readAccessHelper); @@ -39,7 +39,6 @@ public DownloadDataFromDic(FhirWebserviceClientProvider clientProvider, TaskHelp protected void doExecute(DelegateExecution execution) throws BpmnError, Exception { Task task = getCurrentTaskFromExecutionVariables(); - IdType id = getDataReference(task).map(ref -> new IdType(ref)).get(); FhirWebserviceClient client = getFhirWebserviceClientProvider().getWebserviceClient(id.getBaseUrl()); diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/translate/LogError.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/translate/LogError.java new file mode 100644 index 00000000..5aad5e7e --- /dev/null +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/translate/LogError.java @@ -0,0 +1,79 @@ +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.translate; + +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_ERROR_CODE; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_ERROR_MESSAGE; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_ERROR_SOURCE; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_SOURCE_VALUE_GTH; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_VALIDATION_FAILED; + +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; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.hl7.fhir.r4.model.ResourceType; +import org.hl7.fhir.r4.model.Task; +import org.hl7.fhir.r4.model.Task.TaskOutputComponent; +import org.hl7.fhir.r4.model.Task.TaskStatus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.error.ErrorOutputParameterGenerator; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.logging.ErrorLogger; + +public class LogError extends AbstractServiceDelegate +{ + private static final Logger logger = LoggerFactory.getLogger(LogError.class); + + private final ErrorOutputParameterGenerator errorOutputParameterGenerator; + private final ErrorLogger errorLogger; + + public LogError(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, ErrorOutputParameterGenerator errorOutputParameterGenerator, + ErrorLogger errorLogger) + { + super(clientProvider, taskHelper, readAccessHelper); + + this.errorOutputParameterGenerator = errorOutputParameterGenerator; + this.errorLogger = errorLogger; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(errorOutputParameterGenerator, "errorOutputParameterGenerator"); + Objects.requireNonNull(errorLogger, "errorLogger"); + } + + @Override + protected void doExecute(DelegateExecution execution) throws BpmnError, Exception + { + logger.debug("Setting Task.status failed, adding error"); + + Task task = getLeadingTaskFromExecutionVariables(); + task.setStatus(TaskStatus.FAILED); + + String errorCode = (String) execution.getVariable(BPMN_EXECUTION_VARIABLE_ERROR_CODE); + String errorMessage = (String) execution.getVariable(BPMN_EXECUTION_VARIABLE_ERROR_MESSAGE); + String errorSource = (String) execution.getVariable(BPMN_EXECUTION_VARIABLE_ERROR_SOURCE); + + if (!CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_VALIDATION_FAILED.equals(errorCode)) + { + TaskOutputComponent output = errorOutputParameterGenerator.createError( + errorSource != null ? errorSource : CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_SOURCE_VALUE_GTH, + errorCode, errorMessage); + + task.addOutput(output); + + logger.warn("Error while transfering data to CRR: {} - {}", errorCode, errorMessage); + + errorLogger.logDataReceiveFailed(getLeadingTaskFromExecutionVariables().getIdElement() + .withServerBase(getFhirWebserviceClientProvider().getLocalBaseUrl(), ResourceType.Task.name())); + } + } +} diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/translate/LogSuccess.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/translate/LogSuccess.java new file mode 100644 index 00000000..753ac21a --- /dev/null +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/translate/LogSuccess.java @@ -0,0 +1,27 @@ +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.translate; + +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; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class LogSuccess extends AbstractServiceDelegate +{ + private static final Logger logger = LoggerFactory.getLogger(LogSuccess.class); + + public LogSuccess(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper) + { + super(clientProvider, taskHelper, readAccessHelper); + } + + @Override + protected void doExecute(DelegateExecution execution) throws BpmnError, Exception + { + logger.info("All resources successfully added to CRR FHIR repository"); + } +} diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/translate/LogValidationError.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/translate/LogValidationError.java new file mode 100644 index 00000000..9eea9f05 --- /dev/null +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/translate/LogValidationError.java @@ -0,0 +1,63 @@ +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.translate; + +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_SOURCE_VALUE_CRR; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_VALIDATION_FAILED; + +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; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.hl7.fhir.r4.model.ResourceType; +import org.hl7.fhir.r4.model.Task; +import org.hl7.fhir.r4.model.Task.TaskOutputComponent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.error.ErrorOutputParameterGenerator; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.logging.ErrorLogger; + +public class LogValidationError extends AbstractServiceDelegate +{ + private static final Logger logger = LoggerFactory.getLogger(LogValidationError.class); + + private final ErrorOutputParameterGenerator errorOutputParameterGenerator; + private final ErrorLogger errorLogger; + + public LogValidationError(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, ErrorOutputParameterGenerator errorOutputParameterGenerator, + ErrorLogger errorLogger) + { + super(clientProvider, taskHelper, readAccessHelper); + + this.errorOutputParameterGenerator = errorOutputParameterGenerator; + this.errorLogger = errorLogger; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(errorOutputParameterGenerator, "errorOutputParameterGenerator"); + Objects.requireNonNull(errorLogger, "errorLogger"); + } + + @Override + protected void doExecute(DelegateExecution execution) throws BpmnError, Exception + { + logger.info("Validation error while adding resources to CRR FHIR repository"); + errorLogger.logValidationFailedRemote(getLeadingTaskFromExecutionVariables().getIdElement() + .withServerBase(getFhirWebserviceClientProvider().getLocalBaseUrl(), ResourceType.Task.name())); + + Task task = getLeadingTaskFromExecutionVariables(); + TaskOutputComponent output = errorOutputParameterGenerator.createError( + CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_SOURCE_VALUE_CRR, + CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_VALIDATION_FAILED, + "Validation failed while inserting into CRR"); + task.addOutput(output); + } +} diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/ReplacePseudonym.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/translate/ReplacePseudonym.java similarity index 86% rename from codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/ReplacePseudonym.java rename to codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/translate/ReplacePseudonym.java index 71760ae5..dbd18ea1 100644 --- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/ReplacePseudonym.java +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/translate/ReplacePseudonym.java @@ -1,7 +1,8 @@ -package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service; +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.translate; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_PSEUDONYM; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_NO_CRR_PSEUDONYM_FOR_DIC_PSEUDONYM; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER_VALUE_PSEUDONYM; import java.util.Objects; @@ -48,7 +49,10 @@ protected void doExecute(DelegateExecution execution) throws BpmnError, Exceptio String dicPseudonym = getPseudonym(task).get(); - String crrPseudonym = fttpClientFactory.getFttpClient().getCrrPseudonym(dicPseudonym).get(); + String crrPseudonym = fttpClientFactory.getFttpClient().getCrrPseudonym(dicPseudonym) + .orElseThrow(() -> new BpmnError( + CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_NO_CRR_PSEUDONYM_FOR_DIC_PSEUDONYM, + "Unable to get CRR pseudonym for given DIC pseudonym")); execution.setVariable(BPMN_EXECUTION_VARIABLE_PSEUDONYM, Variables.stringValue(crrPseudonym)); } diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/translate/SetTimeoutError.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/translate/SetTimeoutError.java new file mode 100644 index 00000000..558d43ca --- /dev/null +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/translate/SetTimeoutError.java @@ -0,0 +1,30 @@ +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.translate; + +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_ERROR_CODE; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_ERROR_MESSAGE; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_TIMEOUT_WAITING_FOR_RESPONSE_FROM_CRR; + +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; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; + +public class SetTimeoutError extends AbstractServiceDelegate +{ + public SetTimeoutError(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper) + { + super(clientProvider, taskHelper, readAccessHelper); + } + + @Override + protected void doExecute(DelegateExecution execution) throws BpmnError, Exception + { + execution.setVariable(BPMN_EXECUTION_VARIABLE_ERROR_CODE, + CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_TIMEOUT_WAITING_FOR_RESPONSE_FROM_CRR); + execution.setVariable(BPMN_EXECUTION_VARIABLE_ERROR_MESSAGE, + "Timeout while waiting for continue task from CRR"); + } +} diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/StoreDataForCrr.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/translate/StoreDataForCrr.java similarity index 95% rename from codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/StoreDataForCrr.java rename to codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/translate/StoreDataForCrr.java index 37eee189..76801743 100644 --- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/StoreDataForCrr.java +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/translate/StoreDataForCrr.java @@ -1,4 +1,4 @@ -package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service; +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.translate; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_BINARY_URL; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_BUNDLE; @@ -64,7 +64,7 @@ protected void doExecute(DelegateExecution execution) throws BpmnError, Exceptio { byte[] encrypted = (byte[]) execution.getVariable(BPMN_EXECUTION_VARIABLE_BUNDLE); - String downloadUrl = saveBinaryForCrr(encrypted, crrIdentifierValue); + String downloadUrl = saveBinary(encrypted, crrIdentifierValue); execution.setVariable(BPMN_EXECUTION_VARIABLE_BINARY_URL, Variables.stringValue(downloadUrl)); @@ -74,11 +74,11 @@ protected void doExecute(DelegateExecution execution) throws BpmnError, Exceptio getEndpointIdentifier(targetEndpoint), targetEndpoint.getAddress()))); } - protected String saveBinaryForCrr(byte[] encryptedContent, String geccoTransferHubIdentifierValue) + protected String saveBinary(byte[] encryptedContent, String crrIdentifierValue) { Reference securityContext = new Reference(); securityContext.setType(ResourceType.Organization.name()).getIdentifier() - .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue(geccoTransferHubIdentifierValue); + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue(crrIdentifierValue); Binary binary = new Binary().setContentType(MediaType.APPLICATION_OCTET_STREAM) .setSecurityContext(securityContext).setData(encryptedContent); diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/translate/StoreValidationErrorForDic.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/translate/StoreValidationErrorForDic.java new file mode 100644 index 00000000..bc8ffeca --- /dev/null +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/translate/StoreValidationErrorForDic.java @@ -0,0 +1,119 @@ +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.translate; + +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_BINARY_URL; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_BUNDLE; +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; +import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_NUM_CODEX_CONSORTIUM; + +import java.util.Objects; + +import javax.ws.rs.core.MediaType; + +import org.camunda.bpm.engine.delegate.BpmnError; +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.task.TaskHelper; +import org.highmed.dsf.fhir.variables.Target; +import org.highmed.dsf.fhir.variables.TargetValues; +import org.hl7.fhir.r4.model.Binary; +import org.hl7.fhir.r4.model.Endpoint; +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.ResourceType; +import org.hl7.fhir.r4.model.Task; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ca.uhn.fhir.context.FhirContext; + +public class StoreValidationErrorForDic extends AbstractServiceDelegate +{ + private static final Logger logger = LoggerFactory.getLogger(StoreValidationErrorForDic.class); + + private final EndpointProvider endpointProvider; + + public StoreValidationErrorForDic(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 BpmnError, Exception + { + byte[] encrypted = (byte[]) execution.getVariable(BPMN_EXECUTION_VARIABLE_BUNDLE); + + Task leadingTask = getLeadingTaskFromExecutionVariables(); + String medicIdentifierValue = leadingTask.getRequester().getIdentifier().getValue(); + + String downloadUrl = saveBinary(encrypted, medicIdentifierValue); + + execution.setVariable(BPMN_EXECUTION_VARIABLE_BINARY_URL, Variables.stringValue(downloadUrl)); + + Endpoint targetEndpoint = getEndpoint(CODESYSTEM_HIGHMED_ORGANIZATION_ROLE_VALUE_MEDIC, medicIdentifierValue); + execution.setVariable(BPMN_EXECUTION_VARIABLE_TARGET, + TargetValues.create(Target.createUniDirectionalTarget(medicIdentifierValue, + getEndpointIdentifier(targetEndpoint), targetEndpoint.getAddress()))); + } + + protected String saveBinary(byte[] encryptedContent, String gthIdentifierValue) + { + Reference securityContext = new Reference(); + securityContext.setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue(gthIdentifierValue); + Binary binary = new Binary().setContentType(MediaType.APPLICATION_OCTET_STREAM) + .setSecurityContext(securityContext).setData(encryptedContent); + + IdType created = createBinaryResource(binary); + return new IdType(getFhirWebserviceClientProvider().getLocalBaseUrl(), ResourceType.Binary.name(), + created.getIdPart(), created.getVersionIdPart()).getValue(); + } + + private IdType createBinaryResource(Binary binary) + { + try + { + return getFhirWebserviceClientProvider().getLocalWebserviceClient().withMinimalReturn().create(binary); + } + catch (Exception e) + { + logger.debug("Binary to create {}", FhirContext.forR4().newJsonParser().encodeResourceToString(binary)); + logger.warn("Error while creating Binary resource: " + e.getMessage(), e); + throw e; + } + } + + private Endpoint getEndpoint(String role, String identifier) + { + return endpointProvider + .getFirstConsortiumEndpoint(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_NUM_CODEX_CONSORTIUM, + CODESYSTEM_HIGHMED_ORGANIZATION_ROLE, role, identifier) + .get(); + } + + private String getEndpointIdentifier(Endpoint endpoint) + { + return endpoint.getIdentifier().stream() + .filter(i -> NAMINGSYSTEM_HIGHMED_ENDPOINT_IDENTIFIER.equals(i.getSystem())).findFirst() + .map(Identifier::getValue).get(); + } +} diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/FindNewData.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/trigger/FindNewData.java similarity index 99% rename from codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/FindNewData.java rename to codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/trigger/FindNewData.java index 414b00c5..5e4256e4 100644 --- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/FindNewData.java +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/trigger/FindNewData.java @@ -1,4 +1,4 @@ -package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service; +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.trigger; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_EXPORT_FROM; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_EXPORT_FROM_PRECISION; diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/SaveLastExportTo.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/trigger/SaveLastExportTo.java similarity index 98% rename from codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/SaveLastExportTo.java rename to codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/trigger/SaveLastExportTo.java index 0c4f7f6a..1375e7ef 100644 --- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/SaveLastExportTo.java +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/trigger/SaveLastExportTo.java @@ -1,4 +1,4 @@ -package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service; +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.trigger; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_LAST_EXPORT_TO; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER; diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/StartTimer.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/trigger/StartTimer.java similarity index 98% rename from codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/StartTimer.java rename to codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/trigger/StartTimer.java index 749f385c..a56edcd7 100644 --- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/StartTimer.java +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/trigger/StartTimer.java @@ -1,4 +1,4 @@ -package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service; +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.trigger; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_STOP_TIMER; diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/StopTimer.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/trigger/StopTimer.java similarity index 98% rename from codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/StopTimer.java rename to codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/trigger/StopTimer.java index 8664f9f7..5d705173 100644 --- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/StopTimer.java +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/trigger/StopTimer.java @@ -1,4 +1,4 @@ -package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service; +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.trigger; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_STOP_TIMER; diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/spring/config/ReceiveConfig.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/spring/config/ReceiveConfig.java new file mode 100644 index 00000000..aafe8620 --- /dev/null +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/spring/config/ReceiveConfig.java @@ -0,0 +1,119 @@ +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.spring.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.message.ContinueTranslateProcess; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.message.ContinueTranslateProcessWithError; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.message.ContinueTranslateProcessWithValidationError; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.receive.DecryptData; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.receive.DeleteValidationErrorForGth; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.receive.DownloadDataFromGth; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.receive.EncryptValidationError; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.receive.InsertDataIntoCodex; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.receive.LogError; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.receive.LogSuccess; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.receive.LogValidationError; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.receive.StoreValidationErrorForGth; + +@Configuration +public class ReceiveConfig +{ + @Autowired + private TransferDataConfig transferDataConfig; + + @Bean + public DownloadDataFromGth downloadDataFromGth() + { + return new DownloadDataFromGth(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper(), transferDataConfig.endpointProvider(), + transferDataConfig.gthIdentifierValue()); + } + + @Bean + public DecryptData decryptData() + { + return new DecryptData(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper(), transferDataConfig.fhirContext(), + transferDataConfig.crrKeyProvider()); + } + + @Bean + public InsertDataIntoCodex insertDataIntoCodex() + { + return new InsertDataIntoCodex(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper(), transferDataConfig.fhirContext(), + transferDataConfig.geccoClientFactory()); + } + + @Bean + public ContinueTranslateProcess continueTranslateProcess() + { + return new ContinueTranslateProcess(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper(), transferDataConfig.organizationProvider(), + transferDataConfig.fhirContext()); + } + + @Bean(name = "Receive-logSuccess") // prefix to force distinct bean names + public LogSuccess logSuccess() + { + return new LogSuccess(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper()); + } + + @Bean(name = "Receive-logValidation") // prefix to force distinct bean names + public LogValidationError logValidationError() + { + return new LogValidationError(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper(), transferDataConfig.errorOutputParameterGenerator(), + transferDataConfig.errorLogger()); + } + + @Bean + public EncryptValidationError encryptValidationError() + { + return new EncryptValidationError(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper(), transferDataConfig.fhirContext()); + } + + @Bean + public StoreValidationErrorForGth storeValidationErrorForGth() + { + return new StoreValidationErrorForGth(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper(), transferDataConfig.endpointProvider(), + transferDataConfig.gthIdentifierValue()); + } + + @Bean + public ContinueTranslateProcessWithValidationError continueTranslateProcessWithValidationError() + { + return new ContinueTranslateProcessWithValidationError(transferDataConfig.fhirClientProvider(), + transferDataConfig.taskHelper(), transferDataConfig.readAccessHelper(), + transferDataConfig.organizationProvider(), transferDataConfig.fhirContext()); + } + + @Bean + public DeleteValidationErrorForGth deleteValidationErrorForGth() + { + return new DeleteValidationErrorForGth(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper()); + } + + @Bean + public ContinueTranslateProcessWithError continueTranslateProcessWithError() + { + return new ContinueTranslateProcessWithError(transferDataConfig.fhirClientProvider(), + transferDataConfig.taskHelper(), transferDataConfig.readAccessHelper(), + transferDataConfig.organizationProvider(), transferDataConfig.fhirContext(), + transferDataConfig.errorInputParameterGenerator()); + } + + @Bean(name = "Receive-logError") // prefix to force distinct bean names + public LogError logError() + { + return new LogError(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper(), transferDataConfig.errorOutputParameterGenerator(), + transferDataConfig.errorLogger()); + } +} diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/spring/config/SendConfig.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/spring/config/SendConfig.java new file mode 100644 index 00000000..dafcf9b2 --- /dev/null +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/spring/config/SendConfig.java @@ -0,0 +1,168 @@ +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.spring.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.message.StartTranslateProcess; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.send.CheckConsent; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.send.CheckForError; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.send.DecryptValidationErrorFromGth; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.send.DeleteDataForGth; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.send.DownloadValidationErrorFromGth; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.send.EncryptData; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.send.ExtractPatientReference; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.send.LogError; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.send.LogSuccess; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.send.LogValidationError; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.send.ReadData; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.send.ResolvePsn; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.send.SetNoConsentIdatMergeError; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.send.SetNoConsentUsageAndTransferError; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.send.SetTimeoutError; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.send.StoreDataForGth; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.send.ValidateData; + +@Configuration +public class SendConfig +{ + @Autowired + private TransferDataConfig transferDataConfig; + + @Bean + public ExtractPatientReference extractPatientReference() + { + return new ExtractPatientReference(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper()); + } + + @Bean + public CheckConsent checkConsent() + { + return new CheckConsent(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper(), transferDataConfig.consentClientFactory(), + transferDataConfig.idatMergeGrantedOids(), transferDataConfig.mdatTransferGrantedOids()); + } + + @Bean + public SetNoConsentIdatMergeError setNoConsentIdatMergeError() + { + return new SetNoConsentIdatMergeError(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper()); + } + + @Bean + public ResolvePsn resolvePsn() + { + return new ResolvePsn(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper(), transferDataConfig.geccoClientFactory(), + transferDataConfig.fttpClientFactory()); + } + + @Bean + public SetNoConsentUsageAndTransferError setNoConsentUsageAndTransferError() + { + return new SetNoConsentUsageAndTransferError(transferDataConfig.fhirClientProvider(), + transferDataConfig.taskHelper(), transferDataConfig.readAccessHelper()); + } + + @Bean + public ReadData readData() + { + return new ReadData(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper(), transferDataConfig.fhirContext(), + transferDataConfig.geccoClientFactory()); + } + + @Bean + public ValidateData validateData() + { + return new ValidateData(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper(), transferDataConfig.bundleValidatorFactory(), + transferDataConfig.errorOutputParameterGenerator(), transferDataConfig.errorLogger()); + } + + @Bean + public EncryptData encryptData() + { + return new EncryptData(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper(), transferDataConfig.fhirContext(), + transferDataConfig.crrKeyProvider()); + } + + @Bean + public StoreDataForGth storeDataForGth() + { + return new StoreDataForGth(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper(), transferDataConfig.endpointProvider(), + transferDataConfig.gthIdentifierValue()); + } + + @Bean + public StartTranslateProcess startTranslateProcess() + { + return new StartTranslateProcess(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper(), transferDataConfig.organizationProvider(), + transferDataConfig.fhirContext()); + } + + @Bean(name = "Send-setTimeoutError") // prefix to force distinct bean names + public SetTimeoutError setTimeoutError() + { + return new SetTimeoutError(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper()); + } + + @Bean + public DeleteDataForGth deleteDataForGth() + { + return new DeleteDataForGth(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper()); + } + + @Bean(name = "Send-checkForError") // prefix to force distinct bean names + public CheckForError checkForError() + { + return new CheckForError(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper()); + } + + @Bean + public DownloadValidationErrorFromGth downloadValidationErrorFromGth() + { + return new DownloadValidationErrorFromGth(transferDataConfig.fhirClientProvider(), + transferDataConfig.taskHelper(), transferDataConfig.readAccessHelper(), + transferDataConfig.endpointProvider(), transferDataConfig.gthIdentifierValue()); + } + + @Bean + public DecryptValidationErrorFromGth decryptValidationErrorFromGth() + { + return new DecryptValidationErrorFromGth(transferDataConfig.fhirClientProvider(), + transferDataConfig.taskHelper(), transferDataConfig.readAccessHelper(), + transferDataConfig.fhirContext()); + } + + @Bean(name = "Send-logSuccess") // prefix to force distinct bean names + public LogSuccess logSuccess() + { + return new LogSuccess(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper()); + } + + @Bean(name = "Send-logValidationError") // prefix to force distinct bean names + public LogValidationError logValidationError() + { + return new LogValidationError(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper(), transferDataConfig.errorOutputParameterGenerator(), + transferDataConfig.errorLogger()); + } + + @Bean(name = "Send-logError") // prefix to force distinct bean names + public LogError logError() + { + return new LogError(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper(), transferDataConfig.errorOutputParameterGenerator(), + transferDataConfig.errorLogger()); + } +} diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/spring/config/TransferDataConfig.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/spring/config/TransferDataConfig.java index ecd2b221..eb14f10a 100644 --- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/spring/config/TransferDataConfig.java +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/spring/config/TransferDataConfig.java @@ -23,30 +23,9 @@ import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.client.fhir.GeccoFhirClient; import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.crypto.CrrKeyProvider; import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.crypto.CrrKeyProviderImpl; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.error.ErrorInputParameterGenerator; import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.error.ErrorOutputParameterGenerator; import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.logging.ErrorLogger; -import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.message.StartReceiveProcess; -import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.message.StartSendProcess; -import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.message.StartTranslateProcess; -import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.CheckConsent; -import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.DecryptData; -import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.DownloadDataFromDic; -import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.DownloadDataFromTransferHub; -import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.EncryptData; -import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.ExtractPatientReference; -import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.FindNewData; -import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.HandleNoConsentIdatMerge; -import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.HandleNoConsentUsageAndTransfer; -import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.InsertDataIntoCodex; -import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.ReadData; -import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.ReplacePseudonym; -import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.ResolvePseudonym; -import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.SaveLastExportTo; -import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.StartTimer; -import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.StopTimer; -import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.StoreDataForCrr; -import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.StoreDataForTransferHub; -import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.ValidateData; import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.validation.BundleValidatorFactory; @Configuration @@ -179,7 +158,7 @@ public class TransferDataConfig @ProcessDocumentation(description = "DSF organization identifier of the GECCO Transfer Hub", processNames = "wwwnetzwerk-universitaetsmedizinde_dataSend") @Value("${de.netzwerk.universitaetsmedizin.codex.gth.identifier.value:hs-heilbronn.de}") - private String geccoTransferHubIdentifierValue; + private String gthIdentifierValue; @ProcessDocumentation(description = "DSF organization identifier of the central research repository", processNames = "wwwnetzwerk-universitaetsmedizinde_dataTranslate") @Value("${de.netzwerk.universitaetsmedizin.codex.crr.identifier.value:num-codex.de}") @@ -294,6 +273,61 @@ public class TransferDataConfig @Value("${org.highmed.dsf.bpe.fhir.server.organization.identifier.value}") private String localIdentifierValue; + public List idatMergeGrantedOids() + { + return idatMergeGrantedOids; + } + + public List mdatTransferGrantedOids() + { + return mdatTransferGrantedOids; + } + + public String gthIdentifierValue() + { + return gthIdentifierValue; + } + + public String crrIdentifierValue() + { + return crrIdentifierValue; + } + + public FhirWebserviceClientProvider fhirClientProvider() + { + return fhirClientProvider; + } + + public TaskHelper taskHelper() + { + return taskHelper; + } + + public ReadAccessHelper readAccessHelper() + { + return readAccessHelper; + } + + public FhirContext fhirContext() + { + return fhirContext; + } + + public BundleValidatorFactory bundleValidatorFactory() + { + return bundleValidatorFactory; + } + + public EndpointProvider endpointProvider() + { + return endpointProvider; + } + + public OrganizationProvider organizationProvider() + { + return organizationProvider; + } + @Bean public CrrKeyProvider crrKeyProvider() { @@ -359,86 +393,10 @@ public ConsentClientFactory consentClientFactory() return new ConsentClientFactory(); } - // numCodexDataTrigger - - @Bean - public StartTimer startTimer() - { - return new StartTimer(fhirClientProvider, taskHelper, readAccessHelper); - } - - @Bean - public FindNewData findNewData() - { - return new FindNewData(fhirClientProvider, taskHelper, readAccessHelper, organizationProvider, endpointProvider, - geccoClientFactory()); - } - - @Bean - public StartSendProcess startSendProcess() - { - return new StartSendProcess(fhirClientProvider, taskHelper, readAccessHelper, organizationProvider, - fhirContext); - } - @Bean - public StopTimer stopTimer() + public ErrorInputParameterGenerator errorInputParameterGenerator() { - return new StopTimer(fhirClientProvider, taskHelper, readAccessHelper); - } - - @Bean - public SaveLastExportTo saveLastExportTo() - { - return new SaveLastExportTo(fhirClientProvider, taskHelper, readAccessHelper); - } - - // numCodexDataSend - - @Bean - public ExtractPatientReference extractPseudonym() - { - return new ExtractPatientReference(fhirClientProvider, taskHelper, readAccessHelper); - } - - @Bean - public ResolvePseudonym resolvePseudonym() - { - return new ResolvePseudonym(fhirClientProvider, taskHelper, readAccessHelper, geccoClientFactory(), - fttpClientFactory()); - } - - @Bean - public CheckConsent checkConsent() - { - return new CheckConsent(fhirClientProvider, taskHelper, readAccessHelper, consentClientFactory(), - idatMergeGrantedOids, mdatTransferGrantedOids); - } - - @Bean - public HandleNoConsentUsageAndTransfer handleNoConsentUsageAndTransfer() - { - return new HandleNoConsentUsageAndTransfer(fhirClientProvider, taskHelper, readAccessHelper); - } - - @Bean - public HandleNoConsentIdatMerge handleNoConsentIdatMerge() - { - return new HandleNoConsentIdatMerge(fhirClientProvider, taskHelper, readAccessHelper); - } - - @Bean - public ReadData readData() - { - return new ReadData(fhirClientProvider, taskHelper, readAccessHelper, fhirContext, geccoClientFactory(), - fhirStoreBaseUrl); - } - - @Bean - public ValidateData validateData() - { - return new ValidateData(fhirClientProvider, taskHelper, readAccessHelper, bundleValidatorFactory, - errorOutputParameterGenerator(), errorLogger()); + return new ErrorInputParameterGenerator(); } @Bean @@ -452,73 +410,4 @@ public ErrorLogger errorLogger() { return new ErrorLogger(); } - - @Bean - public EncryptData encryptData() - { - return new EncryptData(fhirClientProvider, taskHelper, readAccessHelper, fhirContext, crrKeyProvider()); - } - - @Bean - public StoreDataForTransferHub storeDataForTransferHub() - { - return new StoreDataForTransferHub(fhirClientProvider, taskHelper, readAccessHelper, endpointProvider, - geccoTransferHubIdentifierValue); - } - - @Bean - public StartTranslateProcess startTranslateProcess() - { - return new StartTranslateProcess(fhirClientProvider, taskHelper, readAccessHelper, organizationProvider, - fhirContext); - } - - // numCodexDataTranslate - - @Bean - public DownloadDataFromDic downloadDataFromDiz() - { - return new DownloadDataFromDic(fhirClientProvider, taskHelper, readAccessHelper); - } - - @Bean - public ReplacePseudonym replacePseudonym() - { - return new ReplacePseudonym(fhirClientProvider, taskHelper, readAccessHelper, fttpClientFactory()); - } - - @Bean - public StoreDataForCrr storeDataForCodex() - { - return new StoreDataForCrr(fhirClientProvider, taskHelper, readAccessHelper, endpointProvider, - crrIdentifierValue); - } - - @Bean - public StartReceiveProcess startReceiveProcess() - { - return new StartReceiveProcess(fhirClientProvider, taskHelper, readAccessHelper, organizationProvider, - fhirContext); - } - - // InsertDataIntoCodex - - @Bean - public DownloadDataFromTransferHub downloadDataFromTransferHub() - { - return new DownloadDataFromTransferHub(fhirClientProvider, taskHelper, readAccessHelper); - } - - @Bean - public DecryptData decryptData() - { - return new DecryptData(fhirClientProvider, taskHelper, readAccessHelper, fhirContext, crrKeyProvider()); - } - - @Bean - public InsertDataIntoCodex insertDataIntoCodex() - { - return new InsertDataIntoCodex(fhirClientProvider, taskHelper, readAccessHelper, fhirContext, - geccoClientFactory()); - } } diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/spring/config/TranslateConfig.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/spring/config/TranslateConfig.java new file mode 100644 index 00000000..21c92b64 --- /dev/null +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/spring/config/TranslateConfig.java @@ -0,0 +1,149 @@ +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.spring.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.message.ContinueSendProcess; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.message.ContinueSendProcessWithError; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.message.ContinueSendProcessWithValidationError; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.message.StartReceiveProcess; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.translate.CheckForError; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.translate.DeleteDataForCrr; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.translate.DeleteValidationErrorForDic; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.translate.DownloadDataFromDic; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.translate.DownloadValidationErrorFromCrr; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.translate.LogError; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.translate.LogSuccess; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.translate.LogValidationError; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.translate.ReplacePseudonym; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.translate.SetTimeoutError; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.translate.StoreDataForCrr; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.translate.StoreValidationErrorForDic; + +@Configuration +public class TranslateConfig +{ + @Autowired + private TransferDataConfig transferDataConfig; + + @Bean + public DownloadDataFromDic downloadDataFromDiz() + { + return new DownloadDataFromDic(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper(), transferDataConfig.endpointProvider()); + } + + @Bean + public ReplacePseudonym replacePseudonym() + { + return new ReplacePseudonym(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper(), transferDataConfig.fttpClientFactory()); + } + + @Bean + public StoreDataForCrr storeDataForCodex() + { + return new StoreDataForCrr(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper(), transferDataConfig.endpointProvider(), + transferDataConfig.crrIdentifierValue()); + } + + @Bean + public StartReceiveProcess startReceiveProcess() + { + return new StartReceiveProcess(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper(), transferDataConfig.organizationProvider(), + transferDataConfig.fhirContext()); + } + + @Bean(name = "Translate-setTimeoutError") // prefix to force distinct bean names + public SetTimeoutError setTimeoutError() + { + return new SetTimeoutError(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper()); + } + + @Bean + public DeleteDataForCrr deleteDataForCrr() + { + return new DeleteDataForCrr(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper()); + } + + @Bean(name = "Translate-checkForError") // prefix to force distinct bean names + public CheckForError checkForError() + { + return new CheckForError(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper()); + } + + @Bean + public ContinueSendProcess continueSendProcess() + { + return new ContinueSendProcess(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper(), transferDataConfig.organizationProvider(), + transferDataConfig.fhirContext()); + } + + @Bean(name = "Translate-logSuccess") // prefix to force distinct bean names + public LogSuccess logSuccess() + { + return new LogSuccess(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper()); + } + + @Bean + public DownloadValidationErrorFromCrr downloadValidationErrorFromCrr() + { + return new DownloadValidationErrorFromCrr(transferDataConfig.fhirClientProvider(), + transferDataConfig.taskHelper(), transferDataConfig.readAccessHelper()); + } + + @Bean + public StoreValidationErrorForDic storeValidationErrorForDic() + { + return new StoreValidationErrorForDic(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper(), transferDataConfig.endpointProvider()); + } + + @Bean + public ContinueSendProcessWithValidationError continueSendProcessWithValidationError() + { + return new ContinueSendProcessWithValidationError(transferDataConfig.fhirClientProvider(), + transferDataConfig.taskHelper(), transferDataConfig.readAccessHelper(), + transferDataConfig.organizationProvider(), transferDataConfig.fhirContext()); + } + + @Bean(name = "Translate-logValidationError") // prefix to force distinct bean names + public LogValidationError logValidationError() + { + return new LogValidationError(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper(), transferDataConfig.errorOutputParameterGenerator(), + transferDataConfig.errorLogger()); + } + + @Bean + public DeleteValidationErrorForDic deleteValidationErrorForDic() + { + return new DeleteValidationErrorForDic(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper()); + } + + @Bean + public ContinueSendProcessWithError continueSendProcessWithError() + { + return new ContinueSendProcessWithError(transferDataConfig.fhirClientProvider(), + transferDataConfig.taskHelper(), transferDataConfig.readAccessHelper(), + transferDataConfig.organizationProvider(), transferDataConfig.fhirContext(), + transferDataConfig.errorInputParameterGenerator()); + } + + @Bean(name = "Translate-logError") // prefix to force distinct bean names + public LogError logError() + { + return new LogError(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper(), transferDataConfig.errorOutputParameterGenerator(), + transferDataConfig.errorLogger()); + } +} diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/spring/config/TriggerConfig.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/spring/config/TriggerConfig.java new file mode 100644 index 00000000..6caf5839 --- /dev/null +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/spring/config/TriggerConfig.java @@ -0,0 +1,55 @@ +package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.spring.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.message.StartSendProcess; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.trigger.FindNewData; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.trigger.SaveLastExportTo; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.trigger.StartTimer; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.trigger.StopTimer; + +@Configuration +public class TriggerConfig +{ + @Autowired + private TransferDataConfig transferDataConfig; + + @Bean + public StartTimer startTimer() + { + return new StartTimer(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper()); + } + + @Bean + public FindNewData findNewData() + { + return new FindNewData(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper(), transferDataConfig.organizationProvider(), + transferDataConfig.endpointProvider(), transferDataConfig.geccoClientFactory()); + } + + @Bean + public StartSendProcess startSendProcess() + { + return new StartSendProcess(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper(), transferDataConfig.organizationProvider(), + transferDataConfig.fhirContext()); + } + + @Bean + public StopTimer stopTimer() + { + return new StopTimer(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper()); + } + + @Bean + public SaveLastExportTo saveLastExportTo() + { + return new SaveLastExportTo(transferDataConfig.fhirClientProvider(), transferDataConfig.taskHelper(), + transferDataConfig.readAccessHelper()); + } +} diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/spring/config/ValidationConfig.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/spring/config/ValidationConfig.java index 2a8dff7a..d4c8df7e 100644 --- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/spring/config/ValidationConfig.java +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/spring/config/ValidationConfig.java @@ -65,6 +65,11 @@ public class ValidationConfig { private static final Logger logger = LoggerFactory.getLogger(ValidationConfig.class); + public static enum TerminologyServerConnectionTestStatus + { + OK, NOT_OK, DISABLED + } + @ProcessDocumentation(description = "Enables/disables local FHIR validation, set to `false` to skip validation", processNames = "wwwnetzwerk-universitaetsmedizinde_dataSend") @Value("${de.netzwerk.universitaetsmedizin.codex.gecco.validation:true}") private boolean validationEnabled; @@ -129,7 +134,7 @@ public class ValidationConfig @Value("${de.netzwerk.universitaetsmedizin.codex.gecco.validation.package.client.timeout.read:300000}") private int packageClientReadTimeout; - @ProcessDocumentation(description = "To enable verbose logging of requests and replies to the FHIR implementation guide package server set to `true`", processNames = "wwwnetzwerk-universitaetsmedizinde_dataSend") + @ProcessDocumentation(description = "To enable verbose logging of requests and replies to the FHIR implementation guide package server, set to `true`", processNames = "wwwnetzwerk-universitaetsmedizinde_dataSend") @Value("${de.netzwerk.universitaetsmedizin.codex.gecco.validation.package.client.verbose:false}") private boolean packageClientVerbose; @@ -189,7 +194,7 @@ public class ValidationConfig @Value("${de.netzwerk.universitaetsmedizin.codex.gecco.validation.valueset.expansion.client.timeout.read:300000}") private int valueSetExpansionClientReadTimeout; - @ProcessDocumentation(description = "To enable verbose logging of requests and replies to the terminology server set to `true`", processNames = "wwwnetzwerk-universitaetsmedizinde_dataSend") + @ProcessDocumentation(description = "To enable verbose logging of requests and replies to the terminology server, set to `true`", processNames = "wwwnetzwerk-universitaetsmedizinde_dataSend") @Value("${de.netzwerk.universitaetsmedizin.codex.gecco.validation.valueset.expansion.client.verbose:false}") private boolean valueSetExpansionClientVerbose; @@ -451,25 +456,29 @@ public ObjectMapper validationObjectMapper() return ObjectMapperFactory.createObjectMapper(fhirContext); } - public boolean testConnectionToTerminologyServer() + public TerminologyServerConnectionTestStatus testConnectionToTerminologyServer() { logger.info( - "Testing connection to terminology server with {trustStorePath: {}, certificatePath: {}, privateKeyPath: {}, privateKeyPassword: {}," - + " basicAuthUsername {}, basicAuthPassword {}, serverBase: {}, proxyUrl {}, proxyUsername, proxyPassword {}}", - valueSetExpansionClientTrustCertificates, valueSetExpansionClientCertificate, - valueSetExpansionClientCertificatePrivateKey, + "{}esting connection to terminology server with {trustStorePath: {}, certificatePath: {}, privateKeyPath: {}, privateKeyPassword: {}," + + " basicAuthUsername {}, basicAuthPassword {}, serverBase: {}, proxyUrl {}, proxyUsername {}, proxyPassword {}}{}", + validationEnabled ? "T" : "Not t", valueSetExpansionClientTrustCertificates, + valueSetExpansionClientCertificate, valueSetExpansionClientCertificatePrivateKey, valueSetExpansionClientCertificatePrivateKeyPassword != null ? "***" : "null", valueSetExpansionClientBasicAuthUsername, valueSetExpansionClientBasicAuthPassword != null ? "***" : "null", valueSetExpansionServerBaseUrl, valueSetExpansionClientProxySchemeHostPort, valueSetExpansionClientProxyUsername, - valueSetExpansionClientProxyPassword != null ? "***" : "null"); + valueSetExpansionClientProxyPassword != null ? "***" : "null", + validationEnabled ? "" : ", validation disabled"); + + if (!validationEnabled) + return TerminologyServerConnectionTestStatus.DISABLED; try { CapabilityStatement metadata = valueSetExpansionClient().getMetadata(); logger.info("Connection test OK: {} - {}", metadata.getSoftware().getName(), metadata.getSoftware().getVersion()); - return true; + return TerminologyServerConnectionTestStatus.OK; } catch (Exception e) { @@ -481,7 +490,7 @@ public boolean testConnectionToTerminologyServer() else logger.error("Connection test failed: {}", e.getMessage()); - return false; + return TerminologyServerConnectionTestStatus.NOT_OK; } } diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/validation/ValidationMain.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/validation/ValidationMain.java index ec110767..46a79481 100644 --- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/validation/ValidationMain.java +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/validation/ValidationMain.java @@ -28,6 +28,7 @@ import ca.uhn.fhir.parser.IParser; import ca.uhn.fhir.validation.ValidationResult; import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.spring.config.ValidationConfig; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.spring.config.ValidationConfig.TerminologyServerConnectionTestStatus; public class ValidationMain implements InitializingBean { @@ -118,9 +119,9 @@ public static void main(String[] args) ValidationConfig.class)) { ValidationConfig config = springContext.getBean(ValidationConfig.class); - boolean testOk = config.testConnectionToTerminologyServer(); + TerminologyServerConnectionTestStatus status = config.testConnectionToTerminologyServer(); - if (testOk) + if (TerminologyServerConnectionTestStatus.OK.equals(status)) { ValidationMain main = springContext.getBean(ValidationMain.class); main.validate(args); diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/validation/ValidationPackageClientJersey.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/validation/ValidationPackageClientJersey.java index fc0f53c6..8fc37f9e 100644 --- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/validation/ValidationPackageClientJersey.java +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/validation/ValidationPackageClientJersey.java @@ -23,8 +23,12 @@ public class ValidationPackageClientJersey implements ValidationPackageClient { - private static final java.util.logging.Logger requestDebugLogger = java.util.logging.Logger - .getLogger(ValueSetExpansionClientJersey.class.getName()); + private static final java.util.logging.Logger requestDebugLogger; + static + { + requestDebugLogger = java.util.logging.Logger.getLogger(ValidationPackageClientJersey.class.getName()); + requestDebugLogger.setLevel(Level.INFO); + } private final Client client; private final String baseUrl; @@ -72,7 +76,7 @@ else if (trustStore != null && keyStore != null && keyStorePassword != null) if (logRequests) { - builder = builder.register(new LoggingFeature(requestDebugLogger, Level.FINE, Verbosity.PAYLOAD_ANY, + builder = builder.register(new LoggingFeature(requestDebugLogger, Level.INFO, Verbosity.PAYLOAD_ANY, LoggingFeature.DEFAULT_MAX_ENTITY_SIZE)); } diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/validation/ValueSetExpansionClientJersey.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/validation/ValueSetExpansionClientJersey.java index ca76021c..0454ab60 100644 --- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/validation/ValueSetExpansionClientJersey.java +++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/validation/ValueSetExpansionClientJersey.java @@ -43,8 +43,12 @@ public class ValueSetExpansionClientJersey implements ValueSetExpansionClient { private static final Logger logger = LoggerFactory.getLogger(ValueSetExpansionClientJersey.class); - private static final java.util.logging.Logger requestDebugLogger = java.util.logging.Logger - .getLogger(ValueSetExpansionClientJersey.class.getName()); + private static final java.util.logging.Logger requestDebugLogger; + static + { + requestDebugLogger = java.util.logging.Logger.getLogger(ValueSetExpansionClientJersey.class.getName()); + requestDebugLogger.setLevel(Level.INFO); + } private final Client client; private final String baseUrl; @@ -108,7 +112,7 @@ else if (trustStore != null && keyStore != null && keyStorePassword != null) if (logRequests) { - builder = builder.register(new LoggingFeature(requestDebugLogger, Level.FINE, Verbosity.PAYLOAD_ANY, + builder = builder.register(new LoggingFeature(requestDebugLogger, Level.INFO, Verbosity.PAYLOAD_ANY, LoggingFeature.DEFAULT_MAX_ENTITY_SIZE)); } diff --git a/codex-process-data-transfer/src/main/resources/bpe/receive.bpmn b/codex-process-data-transfer/src/main/resources/bpe/receive.bpmn index ef21a6f8..b416c9d8 100644 --- a/codex-process-data-transfer/src/main/resources/bpe/receive.bpmn +++ b/codex-process-data-transfer/src/main/resources/bpe/receive.bpmn @@ -1,36 +1,250 @@ - + Flow_1gyqorb - - + + Flow_1gyqorb Flow_064nbas - - + + Flow_064nbas Flow_0si3bwl - - Flow_1w6vljw - - - + Flow_0si3bwl - Flow_1w6vljw + Flow_09lbnic + + + Flow_0cysiak + + + + Flow_03ztcka + + + + + Flow_1jsw4ms + Flow_0jhj8th + + + Flow_0qgdm67 + Flow_0k9x0eh + + + Flow_0cysiak + Flow_03ztcka + Flow_193yd93 + Flow_0lzdm4b + Flow_0wsem2y + Flow_0gjzmhl + + + + + + + Flow_11fvfcn + Flow_1g2ia7m + + + Flow_1g2ia7m + Flow_0qzurps + + + ${continueStatus == 'SUCCESS'} + + + + Flow_18ceeqv + + + + Flow_1kkiaj0 + Flow_0ok68b5 + + PT5M + + + + Flow_0ok68b5 + Flow_18ceeqv + + + Flow_193yd93 + + + + Flow_0lzdm4b + + + + Flow_0wsem2y + + + + + + + Flow_09lbnic + Flow_02q1fg2 + Flow_1pjawha + + + ${continueStatus == 'VALIDATION_ERROR'} + + + + + + http://www.netzwerk-universitaetsmedizin.de/bpe/Process/dataTranslate/#{version} + continueDataTranslateWithValidationError + http://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-continue-data-translate-with-validation-error|#{version} + + + Flow_0qzurps + Flow_1kkiaj0 + + + + + + Flow_02q1fg2 + Flow_11fvfcn + + + + http://www.netzwerk-universitaetsmedizin.de/bpe/Process/dataTranslate/#{version} + continueDataTranslate + http://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-continue-data-translate|#{version} + + + Flow_1pjawha + Flow_0qgdm67 + + + + + Flow_0k9x0eh + + + + + + http://www.netzwerk-universitaetsmedizin.de/bpe/Process/dataTranslate/#{version} + continueDataTranslateWithError + http://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-continue-data-translate-with-error|#{version} + + + Flow_0gjzmhl + Flow_1jsw4ms + + + + + Flow_0jhj8th + + + + Error message & error metadata + + + + Error message & error metadata +Reference to Binary (encrypted validation error) +Codex PSN + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -44,24 +258,114 @@ + + + + + + + + + + + + + + + + - + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/codex-process-data-transfer/src/main/resources/bpe/send.bpmn b/codex-process-data-transfer/src/main/resources/bpe/send.bpmn index 46782498..23cf83ba 100644 --- a/codex-process-data-transfer/src/main/resources/bpe/send.bpmn +++ b/codex-process-data-transfer/src/main/resources/bpe/send.bpmn @@ -1,43 +1,32 @@ - + Flow_1km61ly - - + + Flow_06456ku Flow_0g5a4jz - + Flow_0wpfzi1 Flow_0yamo5r - - - - - http://www.netzwerk-universitaetsmedizin.de/bpe/Process/dataTranslate/#{version} - startDataTranslate - http://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-start-data-translate|#{version} - - - Flow_109e2pt - - - + + Flow_0yamo5r Flow_0zrvqk8 - + Flow_0zrvqk8 Flow_0smf5sr - - + + Flow_0smf5sr Flow_109e2pt @@ -50,22 +39,18 @@ ${usageAndTransferGranted} - - Flow_00kpx7f - - + ${!usageAndTransferGranted} - - + Flow_0tsm3rc - Flow_00kpx7f + Flow_0nrf7fq - + Flow_1km61ly Flow_06456ku - + Flow_05s6sr1 Flow_12xkou2 @@ -75,17 +60,13 @@ Flow_0wugx7a - + ${patientReference.hasIdentifier() && !patientReference.hasAbsoluteReference()} - - Flow_10krxjo - - - + Flow_0pt6h5d - Flow_10krxjo + Flow_04t997c Flow_0wugx7a @@ -95,168 +76,579 @@ ${!patientReference.hasIdentifier() && patientReference.hasAbsoluteReference()} - + ${idatMergeGranted} - + ${!idatMergeGranted} - - - Flow_018z9ct - + + + + + http://www.netzwerk-universitaetsmedizin.de/bpe/Process/dataTranslate/#{version} + startDataTranslate + http://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-start-data-translate|#{version} + + + Flow_109e2pt + Flow_0y7kv08 + + + + Flow_01cz1ir + + + + Flow_1mff8mx + + + + Flow_0sy09vc + + + + Flow_040kkv8 + + + + Flow_18cfw7e + + + + Flow_0yow5g2 + + + + Flow_1ojlya5 + + + + Flow_115gsvw + Flow_0ogw7no + + + Flow_0ogw7no + Flow_1yj09fp + Flow_0s9c6mf + Flow_0ervxi8 + + + Flow_1yj09fp + Flow_0ixpqv3 + + + Flow_0s9c6mf + Flow_1j2hn6l + + + Flow_16ouahu + Flow_188eh1h + + + Flow_1784u2y + + + + ${continueStatus == 'SUCCESS'} + + + ${continueStatus == 'VALIDATION_ERROR'} + + + Flow_1784u2y + Flow_0ervxi8 + Flow_01cz1ir + Flow_1mff8mx + Flow_0sy09vc + Flow_040kkv8 + Flow_0nrf7fq + Flow_18cfw7e + Flow_04t997c + Flow_0yow5g2 + Flow_1ojlya5 + Flow_0wqrp5a + Flow_16ouahu + + + + + Flow_188eh1h + + + + Flow_0ixpqv3 + + + + ${continueStatus == 'ERROR'} + + + + + + + + + + + + + Flow_1j2hn6l + Flow_1fe76g6 + + + + Flow_0wqrp5a + - - Flow_018z9ct + + + Flow_1fe76g6 + Flow_1yqcwpb + + + Flow_1yqcwpb - + + + + + Flow_1tal48r + Flow_009empz + Flow_0soepqw + Flow_0tjvgz8 + Flow_075p3fz + + + Flow_0y7kv08 + Flow_1pyjkzx + Flow_0lcotqz + Flow_0egy89t + Flow_1dsdmf9 + + + Flow_1dsdmf9 + Flow_0yofyrq + + PT10M + + + + Flow_0yofyrq + Flow_1tal48r + + + Flow_1pyjkzx + Flow_009empz + + + + Flow_0lcotqz + Flow_0tjvgz8 + + + + Flow_0egy89t + Flow_0soepqw + + + + Flow_075p3fz + Flow_115gsvw + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - + + + + + - - + + - - + + - + - - - - - - + + - + - - - - + + + + - - - - - - + + - - - + + + + + - - + + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - - + + - - - - - + + + + + + + + - + - + - - + + - + - - + + - - + + + + + - - + + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + diff --git a/codex-process-data-transfer/src/main/resources/bpe/translate.bpmn b/codex-process-data-transfer/src/main/resources/bpe/translate.bpmn index bc5ec78c..992e3142 100644 --- a/codex-process-data-transfer/src/main/resources/bpe/translate.bpmn +++ b/codex-process-data-transfer/src/main/resources/bpe/translate.bpmn @@ -1,27 +1,27 @@ - + Flow_185r1m5 - + Flow_185r1m5 Flow_1e9g35h - + Flow_1e9g35h Flow_0onpu3n - + Flow_0onpu3n Flow_1c2ibtj - + http://www.netzwerk-universitaetsmedizin.de/bpe/Process/dataReceive/#{version} @@ -30,50 +30,532 @@ Flow_1c2ibtj - + Flow_0jz0ii6 + + + + Flow_1n9z3h0 + + + + Flow_19uw2w0 + + + + Flow_1dscaiy + + + + + Flow_1pcy90f + Flow_01ory47 + + + Flow_0vp9yol + Flow_04mbhgy + Flow_05y4kuz + Flow_1o3h7ee + + + Flow_06jkx6x + + + + Flow_1otluz4 + + + + Flow_1o3h7ee + Flow_198ccaq + + + Flow_198ccaq + Flow_10abffn + + + Flow_1otluz4 + Flow_06jkx6x + Flow_05y4kuz + Flow_1dscaiy + Flow_19uw2w0 + Flow_1n9z3h0 + Flow_1uonb5c + + + ${continueStatus == 'SUCCESS'} + + + ${continueStatus == 'ERROR'} + + + + + + + + + http://www.netzwerk-universitaetsmedizin.de/bpe/Process/dataSend/#{version} + continueDataSendWithValidationError + http://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-continue-data-send-with-validation-error|#{version} + + + Flow_10abffn + Flow_0veo5jn + + + + + Flow_0fgnfzu + Flow_0maa1om + + PT5M + + + + + ${continueStatus == 'VALIDATION_ERROR'} + + + Flow_1cw2fc1 + Flow_14s05ya + + + + Flow_0maa1om + Flow_05390w0 + + + Flow_10keuoy + Flow_0vp9yol + + + + + + Flow_05390w0 + + Flow_0veo5jn + Flow_0fgnfzu + + + + + http://www.netzwerk-universitaetsmedizin.de/bpe/Process/dataSend/#{version} + continueDataSend + http://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-continue-data-send|#{version} + + + Flow_04mbhgy + Flow_1pcy90f + + + + + Flow_01ory47 + + + + + + http://www.netzwerk-universitaetsmedizin.de/bpe/Process/dataSend/#{version} + continueDataSendWithError + http://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-continue-data-send-with-error|#{version} + + + Flow_1uonb5c + Flow_1cw2fc1 + + + + + Flow_14s05ya + + + + + + + Flow_0jfknjf + Flow_10keuoy + + + Flow_0164ju7 + Flow_0ud2mov + + + Flow_0ud2mov + Flow_1qdh3uy + Flow_14jfl63 + Flow_101difh + Flow_0jfknjf + + + Flow_0jz0ii6 + Flow_0mnu8ck + Flow_1ojwldr + Flow_0uqvklv + Flow_1haez7h + + + Flow_0mnu8ck + Flow_101difh + + + + Flow_1ojwldr + Flow_14jfl63 + + + + Flow_0uqvklv + Flow_1qdh3uy + + + + Flow_1haez7h + Flow_0164ju7 + + PT5M + + + + + + + + + + + + + + + Error message & error metadata +Reference to Binary (encrypted validation error) +DIZ PSN + + + + Error message & error metadata + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/codex-process-data-transfer/src/main/resources/bpe/trigger.bpmn b/codex-process-data-transfer/src/main/resources/bpe/trigger.bpmn index 21aea313..35f83dbf 100644 --- a/codex-process-data-transfer/src/main/resources/bpe/trigger.bpmn +++ b/codex-process-data-transfer/src/main/resources/bpe/trigger.bpmn @@ -1,7 +1,7 @@ - + - + Flow_0jy9ipp Flow_0xlfzol @@ -74,7 +74,7 @@ Flow_1x5v76c - + Flow_0m0cias Flow_1vxlaau @@ -96,12 +96,12 @@ ${!stopTimer} - + Flow_09o8bb5 Flow_1bbw6lm - + Flow_0stek1z Flow_0hm58q0 diff --git a/codex-process-data-transfer/src/main/resources/fhir/ActivityDefinition/num-codex-data-receive.xml b/codex-process-data-transfer/src/main/resources/fhir/ActivityDefinition/num-codex-data-receive.xml index 8b79ade7..3ef3adc9 100644 --- a/codex-process-data-transfer/src/main/resources/fhir/ActivityDefinition/num-codex-data-receive.xml +++ b/codex-process-data-transfer/src/main/resources/fhir/ActivityDefinition/num-codex-data-receive.xml @@ -43,7 +43,7 @@ value="http://www.netzwerk-universitaetsmedizin.de/bpe/Process/dataReceive" /> - + <subtitle value="NUM-CODEX Central Research Repository Data Receive Process" /> <!-- status managed by bpe --> diff --git a/codex-process-data-transfer/src/main/resources/fhir/ActivityDefinition/num-codex-data-send.xml b/codex-process-data-transfer/src/main/resources/fhir/ActivityDefinition/num-codex-data-send.xml index 45eae27b..0353f3f1 100644 --- a/codex-process-data-transfer/src/main/resources/fhir/ActivityDefinition/num-codex-data-send.xml +++ b/codex-process-data-transfer/src/main/resources/fhir/ActivityDefinition/num-codex-data-send.xml @@ -5,14 +5,12 @@ <code value="ALL" /> </tag> </meta> - <extension - url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization"> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization"> <extension url="message-name"> <valueString value="startDataSend" /> </extension> <extension url="task-profile"> - <valueCanonical - value="http://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-start-data-send|#{version}" /> + <valueCanonical value="http://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-start-data-send|#{version}" /> </extension> <extension url="requester"> <valueCoding> @@ -55,11 +53,130 @@ </valueCoding> </extension> </extension> - <url - value="http://www.netzwerk-universitaetsmedizin.de/bpe/Process/dataSend" /> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization"> + <extension url="message-name"> + <valueString value="continueDataSend" /> + </extension> + <extension url="task-profile"> + <valueCanonical value="http://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-continue-data-send|#{version}" /> + </extension> + <extension url="requester"> + <valueCoding> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization-organization"> + <valueIdentifier> + <system value="http://highmed.org/sid/organization-identifier" /> + <value value="#{de.netzwerk_universitaetsmedizin.codex.gth.identifier.value:hs-heilbronn.de}" /> + </valueIdentifier> + </extension> + <system value="http://highmed.org/fhir/CodeSystem/process-authorization" /> + <code value="REMOTE_ORGANIZATION" /> + </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="netzwerk-universitaetsmedizin.de" /> + </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="continueDataSendWithValidationError" /> + </extension> + <extension url="task-profile"> + <valueCanonical value="http://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-continue-data-send-with-validation-error|#{version}" /> + </extension> + <extension url="requester"> + <valueCoding> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization-organization"> + <valueIdentifier> + <system value="http://highmed.org/sid/organization-identifier" /> + <value value="#{de.netzwerk_universitaetsmedizin.codex.gth.identifier.value:hs-heilbronn.de}" /> + </valueIdentifier> + </extension> + <system value="http://highmed.org/fhir/CodeSystem/process-authorization" /> + <code value="REMOTE_ORGANIZATION" /> + </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="netzwerk-universitaetsmedizin.de" /> + </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="continueDataSendWithError" /> + </extension> + <extension url="task-profile"> + <valueCanonical value="http://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-continue-data-send-with-error|#{version}" /> + </extension> + <extension url="requester"> + <valueCoding> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization-organization"> + <valueIdentifier> + <system value="http://highmed.org/sid/organization-identifier" /> + <value value="#{de.netzwerk_universitaetsmedizin.codex.gth.identifier.value:hs-heilbronn.de}" /> + </valueIdentifier> + </extension> + <system value="http://highmed.org/fhir/CodeSystem/process-authorization" /> + <code value="REMOTE_ORGANIZATION" /> + </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="netzwerk-universitaetsmedizin.de" /> + </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://www.netzwerk-universitaetsmedizin.de/bpe/Process/dataSend" /> <!-- version managed by bpe --> <version value="#{version}" /> - <name value="dataSend" /> + <name value="DataSend" /> <title value="Data Send Process" /> <subtitle value="Data Send to GECCO Transfer Hub Process" /> <!-- status managed by bpe --> @@ -75,7 +192,6 @@ <value value="forschungsnetzwerk-unimedizin@charite.de" /> </telecom> </contact> - <description - value="Process to check consent and read, validate, encrypt and send data to the GECCO transfer hub" /> + <description value="Process to check consent and read, validate, encrypt and send data to the GECCO transfer hub" /> <kind value="Task" /> </ActivityDefinition> \ No newline at end of file diff --git a/codex-process-data-transfer/src/main/resources/fhir/ActivityDefinition/num-codex-data-translate.xml b/codex-process-data-transfer/src/main/resources/fhir/ActivityDefinition/num-codex-data-translate.xml index 4514b91b..a8a696c4 100644 --- a/codex-process-data-transfer/src/main/resources/fhir/ActivityDefinition/num-codex-data-translate.xml +++ b/codex-process-data-transfer/src/main/resources/fhir/ActivityDefinition/num-codex-data-translate.xml @@ -5,14 +5,12 @@ <code value="ALL" /> </tag> </meta> - <extension - url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization"> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization"> <extension url="message-name"> <valueString value="startDataTranslate" /> </extension> <extension url="task-profile"> - <valueCanonical - value="http://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-start-data-translate|#{version}" /> + <valueCanonical value="http://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-start-data-translate|#{version}" /> </extension> <extension url="requester"> <valueCoding> @@ -47,11 +45,106 @@ </valueCoding> </extension> </extension> - <url - value="http://www.netzwerk-universitaetsmedizin.de/bpe/Process/dataTranslate" /> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization"> + <extension url="message-name"> + <valueString value="continueDataTranslate" /> + </extension> + <extension url="task-profile"> + <valueCanonical value="http://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-continue-data-translate|#{version}" /> + </extension> + <extension url="requester"> + <valueCoding> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization-organization"> + <valueIdentifier> + <system value="http://highmed.org/sid/organization-identifier" /> + <value value="#{de.netzwerk_universitaetsmedizin.codex.crr.identifier.value:num-codex.de}" /> + </valueIdentifier> + </extension> + <system value="http://highmed.org/fhir/CodeSystem/process-authorization" /> + <code value="REMOTE_ORGANIZATION" /> + </valueCoding> + </extension> + <extension url="recipient"> + <valueCoding> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization-organization"> + <valueIdentifier> + <system value="http://highmed.org/sid/organization-identifier" /> + <value value="#{de.netzwerk_universitaetsmedizin.codex.gth.identifier.value:hs-heilbronn.de}" /> + </valueIdentifier> + </extension> + <system value="http://highmed.org/fhir/CodeSystem/process-authorization" /> + <code value="LOCAL_ORGANIZATION" /> + </valueCoding> + </extension> + </extension> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization"> + <extension url="message-name"> + <valueString value="continueDataTranslateWithValidationError" /> + </extension> + <extension url="task-profile"> + <valueCanonical value="http://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-continue-data-translate-with-validation-error|#{version}" /> + </extension> + <extension url="requester"> + <valueCoding> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization-organization"> + <valueIdentifier> + <system value="http://highmed.org/sid/organization-identifier" /> + <value value="#{de.netzwerk_universitaetsmedizin.codex.crr.identifier.value:num-codex.de}" /> + </valueIdentifier> + </extension> + <system value="http://highmed.org/fhir/CodeSystem/process-authorization" /> + <code value="REMOTE_ORGANIZATION" /> + </valueCoding> + </extension> + <extension url="recipient"> + <valueCoding> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization-organization"> + <valueIdentifier> + <system value="http://highmed.org/sid/organization-identifier" /> + <value value="#{de.netzwerk_universitaetsmedizin.codex.gth.identifier.value:hs-heilbronn.de}" /> + </valueIdentifier> + </extension> + <system value="http://highmed.org/fhir/CodeSystem/process-authorization" /> + <code value="LOCAL_ORGANIZATION" /> + </valueCoding> + </extension> + </extension> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization"> + <extension url="message-name"> + <valueString value="continueDataTranslateWithError" /> + </extension> + <extension url="task-profile"> + <valueCanonical value="http://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-continue-data-translate-with-error|#{version}" /> + </extension> + <extension url="requester"> + <valueCoding> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization-organization"> + <valueIdentifier> + <system value="http://highmed.org/sid/organization-identifier" /> + <value value="#{de.netzwerk_universitaetsmedizin.codex.crr.identifier.value:num-codex.de}" /> + </valueIdentifier> + </extension> + <system value="http://highmed.org/fhir/CodeSystem/process-authorization" /> + <code value="REMOTE_ORGANIZATION" /> + </valueCoding> + </extension> + <extension url="recipient"> + <valueCoding> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization-organization"> + <valueIdentifier> + <system value="http://highmed.org/sid/organization-identifier" /> + <value value="#{de.netzwerk_universitaetsmedizin.codex.gth.identifier.value:hs-heilbronn.de}" /> + </valueIdentifier> + </extension> + <system value="http://highmed.org/fhir/CodeSystem/process-authorization" /> + <code value="LOCAL_ORGANIZATION" /> + </valueCoding> + </extension> + </extension> + <url value="http://www.netzwerk-universitaetsmedizin.de/bpe/Process/dataTranslate" /> <!-- version managed by bpe --> <version value="#{version}" /> - <name value="dataTranslate" /> + <name value="DataTranslate" /> <title value="Data Translate Process" /> <subtitle value="GECCO Transfer Hub Data Translate Process" /> <!-- status managed by bpe --> @@ -67,7 +160,6 @@ <value value="forschungsnetzwerk-unimedizin@charite.de" /> </telecom> </contact> - <description - value="Process to translate DIC to CRR pseudonys at the GECCO Transfer Hub using the TTP." /> + <description value="Process to translate DIC to CRR pseudonys at the GECCO Transfer Hub using the TTP." /> <kind value="Task" /> </ActivityDefinition> \ No newline at end of file diff --git a/codex-process-data-transfer/src/main/resources/fhir/ActivityDefinition/num-codex-data-trigger.xml b/codex-process-data-transfer/src/main/resources/fhir/ActivityDefinition/num-codex-data-trigger.xml index 1a74a366..315c811d 100644 --- a/codex-process-data-transfer/src/main/resources/fhir/ActivityDefinition/num-codex-data-trigger.xml +++ b/codex-process-data-transfer/src/main/resources/fhir/ActivityDefinition/num-codex-data-trigger.xml @@ -109,7 +109,7 @@ value="http://www.netzwerk-universitaetsmedizin.de/bpe/Process/dataTrigger" /> <!-- version managed by bpe --> <version value="#{version}" /> - <name value="dataTrigger" /> + <name value="DataTrigger" /> <title value="Data Trigger Process" /> <subtitle value="Start/Stop Data Trigger Process" /> <!-- status managed by bpe --> diff --git a/codex-process-data-transfer/src/main/resources/fhir/CodeSystem/num-codex-data-transfer-error-source.xml b/codex-process-data-transfer/src/main/resources/fhir/CodeSystem/num-codex-data-transfer-error-source.xml index f63dbd87..e9897436 100644 --- a/codex-process-data-transfer/src/main/resources/fhir/CodeSystem/num-codex-data-transfer-error-source.xml +++ b/codex-process-data-transfer/src/main/resources/fhir/CodeSystem/num-codex-data-transfer-error-source.xml @@ -31,11 +31,6 @@ <display value="GTH" /> <definition value="Error during process execution at the GECCO Transfer Hub" /> </concept> - <concept> - <code value="fTTP" /> - <display value="fTTP" /> - <definition value="Error during process execution at the federated Trusted Third Party" /> - </concept> <concept> <code value="CRR" /> <display value="CRR" /> diff --git a/codex-process-data-transfer/src/main/resources/fhir/CodeSystem/num-codex-data-transfer-error.xml b/codex-process-data-transfer/src/main/resources/fhir/CodeSystem/num-codex-data-transfer-error.xml index 0fce6339..4d2c517f 100644 --- a/codex-process-data-transfer/src/main/resources/fhir/CodeSystem/num-codex-data-transfer-error.xml +++ b/codex-process-data-transfer/src/main/resources/fhir/CodeSystem/num-codex-data-transfer-error.xml @@ -21,10 +21,60 @@ <hierarchyMeaning value="grouped-by" /> <versionNeeded value="false" /> <content value="complete" /> + <concept> + <code value="patient-not-found" /> + <display value="Patient Not Found" /> + <definition value="The referenced Patient could not be found in the local FHIR repository" /> + </concept> + <concept> + <code value="bad-patient-reference" /> + <display value="Bad Patient Reference" /> + <definition value="The given Patient reference does not point to a resource at the local FHIR repository" /> + </concept> <concept> <code value="validation-failed" /> <display value="Validation Failed" /> <definition value="Error or fatal error during validaton of FHIR resources" /> </concept> + <concept> + <code value="download-data-from-dic-failed" /> + <display value="Download Data From DIC Failed" /> + <definition value="Error while downloading encrypted GECCO data from DIC" /> + </concept> + <concept> + <code value="fttp-not-reachable" /> + <display value="Unable to Connect to The fTTP" /> + <definition value="No connection could be established with the fTTP" /> + </concept> + <concept> + <code value="no-dic-pseudonym-for-bloomfilter" /> + <display value="No DIC Pseudonym For Bloomfilter" /> + <definition value="The fTTP did not return a DIC pseudonym for the given Bloomfilter" /> + </concept> + <concept> + <code value="no-crr-pseudonym-for-dic-pseudonym" /> + <display value="No CRR Pseudonym For DIC pseudonym" /> + <definition value="The fTTP did not return a CRR pseudonym for the given DIC pseudonym" /> + </concept> + <concept> + <code value="download-data-from-gth-failed" /> + <display value="Download Data From GTH Failed" /> + <definition value="Error while downloading encrypted GECCO data from GTH" /> + </concept> + <concept> + <code value="insert-into-crr-fhir-respository-failed" /> + <display value="Insert Into CRR FHIR Repository Failed" /> + <definition value="Error while inserting data into CRR FHIR repository, not a validation error" /> + </concept> + <concept> + <code value="timeout-waiting-for-response-from-crr" /> + <display value="Timeout Waiting For Response From CRR" /> + <definition value="Timeout while waiting for a response (process continue) task from CRR" /> + </concept> + <concept> + <code value="timeout-waiting-for-response-from-gth" /> + <display value="Timeout Waiting For Response From GTH" /> + <definition value="Timeout while waiting for a response (process continue) task from GTH" /> + </concept> <!-- TODO add additional error codes --> </CodeSystem> \ No newline at end of file diff --git a/codex-process-data-transfer/src/main/resources/fhir/CodeSystem/num-codex-data-transfer.xml b/codex-process-data-transfer/src/main/resources/fhir/CodeSystem/num-codex-data-transfer.xml index db9c6a38..11d52504 100644 --- a/codex-process-data-transfer/src/main/resources/fhir/CodeSystem/num-codex-data-transfer.xml +++ b/codex-process-data-transfer/src/main/resources/fhir/CodeSystem/num-codex-data-transfer.xml @@ -34,7 +34,7 @@ <concept> <code value="data-reference" /> <display value="Data Reference" /> - <definition value="Reference to an encrypted GECCO Data-Set" /> + <definition value="Reference to an encrypted GECCO dataset or result bundle" /> </concept> <concept> <code value="export-from" /> diff --git a/codex-process-data-transfer/src/main/resources/fhir/StructureDefinition/num-codex-extension-error-metadata.xml b/codex-process-data-transfer/src/main/resources/fhir/StructureDefinition/num-codex-extension-error-metadata.xml index f4e1f9a4..d85ec35a 100644 --- a/codex-process-data-transfer/src/main/resources/fhir/StructureDefinition/num-codex-extension-error-metadata.xml +++ b/codex-process-data-transfer/src/main/resources/fhir/StructureDefinition/num-codex-extension-error-metadata.xml @@ -17,6 +17,10 @@ <fhirVersion value="4.0.1" /> <kind value="complex-type" /> <abstract value="false" /> + <context> + <type value="element" /> + <expression value="Task.input" /> + </context> <context> <type value="element" /> <expression value="Task.output" /> diff --git a/codex-process-data-transfer/src/main/resources/fhir/StructureDefinition/num-codex-task-continue-data-send-with-error.xml b/codex-process-data-transfer/src/main/resources/fhir/StructureDefinition/num-codex-task-continue-data-send-with-error.xml new file mode 100644 index 00000000..1c667e11 --- /dev/null +++ b/codex-process-data-transfer/src/main/resources/fhir/StructureDefinition/num-codex-task-continue-data-send-with-error.xml @@ -0,0 +1,109 @@ +<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://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-continue-data-send-with-error" /> + <!-- version managed by bpe --> + <version value="#{version}" /> + <name value="TaskContinueDataSendWithError" /> + <!-- 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://www.netzwerk-universitaetsmedizin.de/bpe/Process/dataSend/#{version}" /> + </element> + <element id="Task.input"> + <path value="Task.input" /> + <min value="3" /> + <max value="3" /> + </element> + <element id="Task.input:message-name"> + <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="continueDataSendWithError" /> + </element> + <element id="Task.input:business-key"> + <path value="Task.input" /> + <sliceName value="business-key" /> + <min value="1" /> + </element> + <element id="Task.input:correlation-key"> + <path value="Task.input" /> + <sliceName value="correlation-key" /> + <max value="0" /> + </element> + <element id="Task.input:input-error"> + <path value="Task.input" /> + <sliceName value="input-error" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:input-error.extension"> + <path value="Task.input.extension" /> + <slicing> + <discriminator> + <type value="value" /> + <path value="url" /> + </discriminator> + <rules value="open" /> + </slicing> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:input-error.extension:error-metadata"> + <path value="Task.input.extension" /> + <sliceName value="error-metadata" /> + <min value="1" /> + <max value="1" /> + <type> + <code value="Extension" /> + <profile value="https://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/error-metadata" /> + </type> + <isModifier value="false" /> + </element> + <element id="Task.input:input-error.type"> + <path value="Task.input.type" /> + <binding> + <strength value="required" /> + <valueSet value="http://highmed.org/fhir/ValueSet/bpmn-message" /> + </binding> + </element> + <element id="Task.input:input-error.type.coding"> + <path value="Task.input.type.coding" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input: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:input-error.type.coding.code"> + <path value="Task.input.type.coding.code" /> + <min value="1" /> + <fixedCode value="error" /> + </element> + <element id="Task.input: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/codex-process-data-transfer/src/main/resources/fhir/StructureDefinition/num-codex-task-continue-data-send-with-validation-error.xml b/codex-process-data-transfer/src/main/resources/fhir/StructureDefinition/num-codex-task-continue-data-send-with-validation-error.xml new file mode 100644 index 00000000..b63daf74 --- /dev/null +++ b/codex-process-data-transfer/src/main/resources/fhir/StructureDefinition/num-codex-task-continue-data-send-with-validation-error.xml @@ -0,0 +1,95 @@ +<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://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-continue-data-send-with-validation-error" /> + <!-- version managed by bpe --> + <version value="#{version}" /> + <name value="TaskContinueDataSendWithValidationError" /> + <!-- 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://www.netzwerk-universitaetsmedizin.de/bpe/Process/dataSend/#{version}" /> + </element> + <element id="Task.input"> + <path value="Task.input" /> + <min value="3" /> + <max value="3" /> + </element> + <element id="Task.input:message-name"> + <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="continueDataSendWithValidationError" /> + </element> + <element id="Task.input:business-key"> + <path value="Task.input" /> + <sliceName value="business-key" /> + <min value="1" /> + </element> + <element id="Task.input:correlation-key"> + <path value="Task.input" /> + <sliceName value="correlation-key" /> + <max value="0" /> + </element> + <element id="Task.input:data"> + <path value="Task.input" /> + <sliceName value="data" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:data.type"> + <path value="Task.input.type" /> + <binding> + <strength value="required" /> + <valueSet value="http://www.netzwerk-universitaetsmedizin.de/fhir/ValueSet/data-transfer" /> + </binding> + </element> + <element id="Task.input:data.type.coding"> + <path value="Task.input.type.coding" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:data.type.coding.system"> + <path value="Task.input.type.coding.system" /> + <min value="1" /> + <fixedUri value="http://www.netzwerk-universitaetsmedizin.de/fhir/CodeSystem/data-transfer" /> + </element> + <element id="Task.input:data.type.coding.code"> + <path value="Task.input.type.coding.code" /> + <min value="1" /> + <fixedCode value="data-reference" /> + </element> + <element id="Task.input:data.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:data.value[x].reference"> + <path value="Task.input.value[x].reference" /> + <min value="1" /> + </element> + <element id="Task.input:data.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/codex-process-data-transfer/src/main/resources/fhir/StructureDefinition/num-codex-task-continue-data-send.xml b/codex-process-data-transfer/src/main/resources/fhir/StructureDefinition/num-codex-task-continue-data-send.xml new file mode 100644 index 00000000..c7e48ba4 --- /dev/null +++ b/codex-process-data-transfer/src/main/resources/fhir/StructureDefinition/num-codex-task-continue-data-send.xml @@ -0,0 +1,52 @@ +<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://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-continue-data-send" /> + <!-- version managed by bpe --> + <version value="#{version}" /> + <name value="TaskContinueDataSend" /> + <!-- 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://www.netzwerk-universitaetsmedizin.de/bpe/Process/dataSend/#{version}" /> + </element> + <element id="Task.input"> + <path value="Task.input" /> + <min value="2" /> + <max value="2" /> + </element> + <element id="Task.input:message-name"> + <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="continueDataSend" /> + </element> + <element id="Task.input:business-key"> + <path value="Task.input" /> + <sliceName value="business-key" /> + <min value="1" /> + </element> + <element id="Task.input:correlation-key"> + <path value="Task.input" /> + <sliceName value="correlation-key" /> + <max value="0" /> + </element> + </differential> +</StructureDefinition> \ No newline at end of file diff --git a/codex-process-data-transfer/src/main/resources/fhir/StructureDefinition/num-codex-task-continue-data-translate-with-error.xml b/codex-process-data-transfer/src/main/resources/fhir/StructureDefinition/num-codex-task-continue-data-translate-with-error.xml new file mode 100644 index 00000000..58ed0dee --- /dev/null +++ b/codex-process-data-transfer/src/main/resources/fhir/StructureDefinition/num-codex-task-continue-data-translate-with-error.xml @@ -0,0 +1,109 @@ +<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://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-continue-data-translate-with-error" /> + <!-- version managed by bpe --> + <version value="#{version}" /> + <name value="TaskContinueDataTranslateWithError" /> + <!-- 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://www.netzwerk-universitaetsmedizin.de/bpe/Process/dataTranslate/#{version}" /> + </element> + <element id="Task.input"> + <path value="Task.input" /> + <min value="3" /> + <max value="3" /> + </element> + <element id="Task.input:message-name"> + <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="continueDataTranslateWithError" /> + </element> + <element id="Task.input:business-key"> + <path value="Task.input" /> + <sliceName value="business-key" /> + <min value="1" /> + </element> + <element id="Task.input:correlation-key"> + <path value="Task.input" /> + <sliceName value="correlation-key" /> + <max value="0" /> + </element> + <element id="Task.input:input-error"> + <path value="Task.input" /> + <sliceName value="input-error" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:input-error.extension"> + <path value="Task.input.extension" /> + <slicing> + <discriminator> + <type value="value" /> + <path value="url" /> + </discriminator> + <rules value="open" /> + </slicing> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:input-error.extension:error-metadata"> + <path value="Task.input.extension" /> + <sliceName value="error-metadata" /> + <min value="1" /> + <max value="1" /> + <type> + <code value="Extension" /> + <profile value="https://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/error-metadata" /> + </type> + <isModifier value="false" /> + </element> + <element id="Task.input:input-error.type"> + <path value="Task.input.type" /> + <binding> + <strength value="required" /> + <valueSet value="http://highmed.org/fhir/ValueSet/bpmn-message" /> + </binding> + </element> + <element id="Task.input:input-error.type.coding"> + <path value="Task.input.type.coding" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input: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:input-error.type.coding.code"> + <path value="Task.input.type.coding.code" /> + <min value="1" /> + <fixedCode value="error" /> + </element> + <element id="Task.input: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/codex-process-data-transfer/src/main/resources/fhir/StructureDefinition/num-codex-task-continue-data-translate-with-validation-error.xml b/codex-process-data-transfer/src/main/resources/fhir/StructureDefinition/num-codex-task-continue-data-translate-with-validation-error.xml new file mode 100644 index 00000000..15a7f1c2 --- /dev/null +++ b/codex-process-data-transfer/src/main/resources/fhir/StructureDefinition/num-codex-task-continue-data-translate-with-validation-error.xml @@ -0,0 +1,95 @@ +<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://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-continue-data-translate-with-validation-error" /> + <!-- version managed by bpe --> + <version value="#{version}" /> + <name value="TaskContinueDataTranslateWithValidationError" /> + <!-- 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://www.netzwerk-universitaetsmedizin.de/bpe/Process/dataTranslate/#{version}" /> + </element> + <element id="Task.input"> + <path value="Task.input" /> + <min value="3" /> + <max value="3" /> + </element> + <element id="Task.input:message-name"> + <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="continueDataTranslateWithValidationError" /> + </element> + <element id="Task.input:business-key"> + <path value="Task.input" /> + <sliceName value="business-key" /> + <min value="1" /> + </element> + <element id="Task.input:correlation-key"> + <path value="Task.input" /> + <sliceName value="correlation-key" /> + <max value="0" /> + </element> + <element id="Task.input:data"> + <path value="Task.input" /> + <sliceName value="data" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:data.type"> + <path value="Task.input.type" /> + <binding> + <strength value="required" /> + <valueSet value="http://www.netzwerk-universitaetsmedizin.de/fhir/ValueSet/data-transfer" /> + </binding> + </element> + <element id="Task.input:data.type.coding"> + <path value="Task.input.type.coding" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:data.type.coding.system"> + <path value="Task.input.type.coding.system" /> + <min value="1" /> + <fixedUri value="http://www.netzwerk-universitaetsmedizin.de/fhir/CodeSystem/data-transfer" /> + </element> + <element id="Task.input:data.type.coding.code"> + <path value="Task.input.type.coding.code" /> + <min value="1" /> + <fixedCode value="data-reference" /> + </element> + <element id="Task.input:data.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:data.value[x].reference"> + <path value="Task.input.value[x].reference" /> + <min value="1" /> + </element> + <element id="Task.input:data.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/codex-process-data-transfer/src/main/resources/fhir/StructureDefinition/num-codex-task-continue-data-translate.xml b/codex-process-data-transfer/src/main/resources/fhir/StructureDefinition/num-codex-task-continue-data-translate.xml new file mode 100644 index 00000000..21aca11a --- /dev/null +++ b/codex-process-data-transfer/src/main/resources/fhir/StructureDefinition/num-codex-task-continue-data-translate.xml @@ -0,0 +1,52 @@ +<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://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-continue-data-translate" /> + <!-- version managed by bpe --> + <version value="#{version}" /> + <name value="TaskContinueDataTranslate" /> + <!-- 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://www.netzwerk-universitaetsmedizin.de/bpe/Process/dataTranslate/#{version}" /> + </element> + <element id="Task.input"> + <path value="Task.input" /> + <min value="2" /> + <max value="2" /> + </element> + <element id="Task.input:message-name"> + <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="continueDataTranslate" /> + </element> + <element id="Task.input:business-key"> + <path value="Task.input" /> + <sliceName value="business-key" /> + <min value="1" /> + </element> + <element id="Task.input:correlation-key"> + <path value="Task.input" /> + <sliceName value="correlation-key" /> + <max value="0" /> + </element> + </differential> +</StructureDefinition> \ No newline at end of file diff --git a/codex-process-data-transfer/src/test/java/de/netzwerk_universitaetsmedizin/codex/processes/fhir/profile/TaskProfileTest.java b/codex-process-data-transfer/src/test/java/de/netzwerk_universitaetsmedizin/codex/processes/fhir/profile/TaskProfileTest.java index 93e957ca..0c5ff4df 100644 --- a/codex-process-data-transfer/src/test/java/de/netzwerk_universitaetsmedizin/codex/processes/fhir/profile/TaskProfileTest.java +++ b/codex-process-data-transfer/src/test/java/de/netzwerk_universitaetsmedizin/codex/processes/fhir/profile/TaskProfileTest.java @@ -1,6 +1,8 @@ package de.netzwerk_universitaetsmedizin.codex.processes.fhir.profile; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_DOWNLOAD_DATA_FROM_DIC_FAILED; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_DOWNLOAD_DATA_FROM_GTH_FAILED; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER_VALUE_DATA_REFERENCE; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER_VALUE_EXPORT_FROM; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER_VALUE_EXPORT_TO; @@ -8,6 +10,18 @@ import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER_VALUE_PSEUDONYM; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.NAMING_SYSTEM_NUM_CODEX_CRR_PSEUDONYM; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.NAMING_SYSTEM_NUM_CODEX_DIC_PSEUDONYM; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_SEND; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_SEND_MESSAGE_NAME; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_SEND_WITH_ERROR; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_SEND_WITH_ERROR_MESSAGE_NAME; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_SEND_WITH_VALIDATION_ERROR; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_SEND_WITH_VALIDATION_ERROR_MESSAGE_NAME; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_TRANSLATE; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_TRANSLATE_MESSAGE_NAME; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_TRANSLATE_WITH_ERROR; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_TRANSLATE_WITH_ERROR_MESSAGE_NAME; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_TRANSLATE_WITH_VALIDATION_ERROR; +import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_TRANSLATE_WITH_VALIDATION_ERROR_MESSAGE_NAME; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.PROFILE_NUM_CODEX_TASK_DATA_RECEIVE_PROCESS_URI_AND_LATEST_VERSION; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.PROFILE_NUM_CODEX_TASK_DATA_SEND_PROCESS_URI_AND_LATEST_VERSION; import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.PROFILE_NUM_CODEX_TASK_DATA_TRANSLATE_PROCESS_URI_AND_LATEST_VERSION; @@ -47,6 +61,7 @@ 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.TaskStatus; import org.junit.ClassRule; @@ -57,6 +72,7 @@ import ca.uhn.fhir.model.api.TemporalPrecisionEnum; import ca.uhn.fhir.validation.ResultSeverityEnum; import ca.uhn.fhir.validation.ValidationResult; +import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.error.ErrorInputParameterGenerator; import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.error.ErrorOutputParameterGenerator; public class TaskProfileTest @@ -66,9 +82,13 @@ public class TaskProfileTest @ClassRule public static final ValidationSupportRule validationRule = new ValidationSupportRule(VERSION, DATE, Arrays.asList("highmed-task-base-0.5.0.xml", "num-codex-extension-error-metadata.xml", - "num-codex-task-start-data-receive.xml", "num-codex-task-start-data-send.xml", - "num-codex-task-start-data-translate.xml", "num-codex-task-start-data-trigger.xml", - "num-codex-task-stop-data-trigger.xml"), + "num-codex-task-start-data-trigger.xml", "num-codex-task-stop-data-trigger.xml", + "num-codex-task-start-data-send.xml", "num-codex-task-continue-data-send.xml", + "num-codex-task-continue-data-send-with-validation-error.xml", + "num-codex-task-continue-data-send-with-error.xml", "num-codex-task-start-data-translate.xml", + "num-codex-task-continue-data-translate.xml", + "num-codex-task-continue-data-translate-with-validation-error.xml", + "num-codex-task-continue-data-translate-with-error.xml", "num-codex-task-start-data-receive.xml"), Arrays.asList("highmed-read-access-tag-0.5.0.xml", "highmed-bpmn-message-0.5.0.xml", "num-codex-data-transfer.xml", "num-codex-data-transfer-error-source.xml", "num-codex-data-transfer-error.xml"), @@ -396,4 +416,223 @@ private Task createValidTaskStartDataReceive() return task; } + + @Test + public void testTaskContinueDataSend() throws Exception + { + Task task = createValidTaskContinueDataSend(); + logTask(task); + + 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 createValidTaskContinueDataSend() + { + Task task = new Task(); + task.getMeta().addProfile(PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_SEND); + task.setInstantiatesUri(PROFILE_NUM_CODEX_TASK_DATA_SEND_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("Test_GTH"); + task.getRestriction().addRecipient().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue("Test_DIC"); + task.addInput().setValue(new StringType(PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_SEND_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 testTaskContinueDataSendWithValidationError() throws Exception + { + Task task = createValidTaskContinueDataSendWithValidationError(); + logTask(task); + + 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 createValidTaskContinueDataSendWithValidationError() + { + Task task = new Task(); + task.getMeta().addProfile(PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_SEND_WITH_VALIDATION_ERROR); + task.setInstantiatesUri(PROFILE_NUM_CODEX_TASK_DATA_SEND_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("Test_GTH"); + task.getRestriction().addRecipient().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue("Test_DIC"); + task.addInput() + .setValue(new StringType(PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_SEND_WITH_VALIDATION_ERROR_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 Reference(new IdType("https://gth", "Binary", UUID.randomUUID().toString(), "1"))) + .getType().addCoding().setSystem(CODESYSTEM_NUM_CODEX_DATA_TRANSFER) + .setCode(CODESYSTEM_NUM_CODEX_DATA_TRANSFER_VALUE_DATA_REFERENCE); + + return task; + } + + @Test + public void testTaskContinueDataSendWithError() throws Exception + { + Task task = createValidTaskContinueDataSendWithError(); + logTask(task); + + 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 createValidTaskContinueDataSendWithError() + { + Task task = new Task(); + task.getMeta().addProfile(PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_SEND_WITH_ERROR); + task.setInstantiatesUri(PROFILE_NUM_CODEX_TASK_DATA_SEND_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("Test_GTH"); + task.getRestriction().addRecipient().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue("Test_DIC"); + task.addInput().setValue(new StringType(PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_SEND_WITH_ERROR_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 = new ErrorInputParameterGenerator().createGthError( + CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_DOWNLOAD_DATA_FROM_DIC_FAILED, "Test Error Message"); + task.addInput(error); + + return task; + } + + @Test + public void testTaskContinueDataTranslate() throws Exception + { + Task task = createValidTaskContinueDataTranslate(); + logTask(task); + + 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 createValidTaskContinueDataTranslate() + { + Task task = new Task(); + task.getMeta().addProfile(PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_TRANSLATE); + task.setInstantiatesUri(PROFILE_NUM_CODEX_TASK_DATA_TRANSLATE_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("Test_CRR"); + task.getRestriction().addRecipient().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue("Test_GTH"); + task.addInput().setValue(new StringType(PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_TRANSLATE_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 testTaskContinueDataTranslateWithValidationError() throws Exception + { + Task task = createValidTaskContinueDataTranslateWithValidationError(); + logTask(task); + + 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 createValidTaskContinueDataTranslateWithValidationError() + { + Task task = new Task(); + task.getMeta().addProfile(PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_TRANSLATE_WITH_VALIDATION_ERROR); + task.setInstantiatesUri(PROFILE_NUM_CODEX_TASK_DATA_TRANSLATE_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("Test_CRR"); + task.getRestriction().addRecipient().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue("Test_GTH"); + task.addInput() + .setValue(new StringType( + PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_TRANSLATE_WITH_VALIDATION_ERROR_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 Reference(new IdType("https://crr", "Binary", UUID.randomUUID().toString(), "1"))) + .getType().addCoding().setSystem(CODESYSTEM_NUM_CODEX_DATA_TRANSFER) + .setCode(CODESYSTEM_NUM_CODEX_DATA_TRANSFER_VALUE_DATA_REFERENCE); + + return task; + } + + @Test + public void testTaskContinueDataTranslateWithError() throws Exception + { + Task task = createValidTaskContinueDataTranslateWithError(); + logTask(task); + + 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 createValidTaskContinueDataTranslateWithError() + { + Task task = new Task(); + task.getMeta().addProfile(PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_TRANSLATE_WITH_ERROR); + task.setInstantiatesUri(PROFILE_NUM_CODEX_TASK_DATA_TRANSLATE_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("Test_CRR"); + task.getRestriction().addRecipient().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue("Test_GTH"); + task.addInput().setValue(new StringType(PROFILE_NUM_CODEX_TASK_CONTINUE_DATA_TRANSLATE_WITH_ERROR_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 = new ErrorInputParameterGenerator().createCrrError( + CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_DOWNLOAD_DATA_FROM_GTH_FAILED, "Test Error Message"); + task.addInput(error); + + return task; + } }