diff --git a/pom.xml b/pom.xml index 4ea262e..ef6ffa0 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ de.medizininformatik-initiative mii-process-data-transfer - 1.0.3.0 + 1.0.3.1 UTF-8 diff --git a/src/main/java/de/medizininformatik_initiative/process/data_transfer/DataTransferProcessPluginDefinition.java b/src/main/java/de/medizininformatik_initiative/process/data_transfer/DataTransferProcessPluginDefinition.java index e19cb60..c272501 100644 --- a/src/main/java/de/medizininformatik_initiative/process/data_transfer/DataTransferProcessPluginDefinition.java +++ b/src/main/java/de/medizininformatik_initiative/process/data_transfer/DataTransferProcessPluginDefinition.java @@ -11,8 +11,8 @@ public class DataTransferProcessPluginDefinition implements ProcessPluginDefinition { - public static final String VERSION = "1.0.3.0"; - public static final LocalDate RELEASE_DATE = LocalDate.of(2024, 11, 8); + public static final String VERSION = "1.0.3.1"; + public static final LocalDate RELEASE_DATE = LocalDate.of(2025, 2, 18); @Override public String getName() diff --git a/src/main/java/de/medizininformatik_initiative/process/data_transfer/service/InsertData.java b/src/main/java/de/medizininformatik_initiative/process/data_transfer/service/InsertData.java index fa61eb8..2d64eea 100644 --- a/src/main/java/de/medizininformatik_initiative/process/data_transfer/service/InsertData.java +++ b/src/main/java/de/medizininformatik_initiative/process/data_transfer/service/InsertData.java @@ -1,16 +1,15 @@ package de.medizininformatik_initiative.process.data_transfer.service; -import static java.util.stream.Collectors.toList; - +import java.util.ArrayList; import java.util.List; import java.util.Objects; import org.camunda.bpm.engine.delegate.BpmnError; import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.hl7.fhir.instance.model.api.IBaseBundle; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.DocumentReference; import org.hl7.fhir.r4.model.IdType; -import org.hl7.fhir.r4.model.Organization; import org.hl7.fhir.r4.model.Reference; import org.hl7.fhir.r4.model.ResourceType; import org.hl7.fhir.r4.model.Task; @@ -110,7 +109,7 @@ private List storeData(FhirClient fhirClient, Bundle bundle, String send List idsOfCreatedResources = stored.getEntry().stream().filter(Bundle.BundleEntryComponent::hasResponse) .map(Bundle.BundleEntryComponent::getResponse).map(Bundle.BundleEntryResponseComponent::getLocation) - .map(IdType::new).map(id -> setIdBase(id, fhirClient)).collect(toList()); + .map(IdType::new).map(this::setIdBase).toList(); idsOfCreatedResources.stream().filter(i -> ResourceType.DocumentReference.name().equals(i.getResourceType())) .forEach(i -> addOutputToStartTask(variables, i)); @@ -123,32 +122,29 @@ private List storeData(FhirClient fhirClient, Bundle bundle, String send private Bundle checkAndAdaptBundleForExistingData(FhirClient fhirClient, Bundle bundle, String sendingOrganization, String projectIdentifier, Task task) { - Bundle searchResult = fhirClient.getGenericFhirClient().search().forResource(DocumentReference.class) - .where(DocumentReference.IDENTIFIER.exactly() - .systemAndCode(ConstantsBase.NAMINGSYSTEM_MII_PROJECT_IDENTIFIER, projectIdentifier)) - .and(DocumentReference.AUTHOR.hasChainedProperty(Organization.IDENTIFIER.exactly() - .systemAndCode(NamingSystems.OrganizationIdentifier.SID, sendingOrganization))) - .returnBundle(Bundle.class).execute(); - - List existingDocumentReferences = searchResult.getEntry().stream() - .filter(Bundle.BundleEntryComponent::hasResource).map(Bundle.BundleEntryComponent::getResource) - .filter(r -> r instanceof DocumentReference).map(r -> (DocumentReference) r).toList(); + List existingDocumentReferences = searchExistingDocumentReferences(fhirClient, + sendingOrganization, projectIdentifier, task.getId()); if (existingDocumentReferences.size() < 1) + { + logger.info( + "DocumentReference for project-identifier '{}' authored by '{}' does not yet exist, creating a new data-set on FHIR server with baseUrl '{}' in Task with id '{}'", + projectIdentifier, sendingOrganization, fhirClient.getFhirBaseUrl(), task.getId()); return bundle; + } if (existingDocumentReferences.size() > 1) logger.warn( "Found more than one DocumentReference for project-identifier '{}' authored by '{}', using the first", projectIdentifier, sendingOrganization); - DocumentReference existingDocumentReference = existingDocumentReferences.get(0); - String existingDocumentReferenceId = existingDocumentReference.getIdElement().getIdPart(); - logger.info( "DocumentReference for project-identifier '{}' authored by '{}' already exists, updating data-set on FHIR server with baseUrl '{}' in Task with id '{}'", projectIdentifier, sendingOrganization, fhirClient.getFhirBaseUrl(), task.getId()); + DocumentReference existingDocumentReference = existingDocumentReferences.get(0); + String existingDocumentReferenceId = existingDocumentReference.getIdElement().getIdPart(); + bundle.getEntry().stream().filter(Bundle.BundleEntryComponent::hasResource) .filter(e -> e.getResource() instanceof DocumentReference) .filter(Bundle.BundleEntryComponent::hasRequest).filter(Bundle.BundleEntryComponent::hasResource) @@ -162,6 +158,46 @@ private Bundle checkAndAdaptBundleForExistingData(FhirClient fhirClient, Bundle return bundle; } + private List searchExistingDocumentReferences(FhirClient fhirClient, String sendingOrganization, + String projectIdentifier, String taskId) + { + // workaround since not all fhir server used in MII support DocumentReference.author:identifier or + // DocumentReference.author:Organization.identifier search parameters. Therefore filtering for author + // after loading all DocumentReferences for given project-identifier + try + { + List entries = new ArrayList<>(); + + Bundle searchResult = fhirClient.getGenericFhirClient().search().forResource(DocumentReference.class) + .where(DocumentReference.IDENTIFIER.exactly() + .systemAndCode(ConstantsBase.NAMINGSYSTEM_MII_PROJECT_IDENTIFIER, projectIdentifier)) + .returnBundle(Bundle.class).execute(); + entries.addAll(searchResult.getEntry()); + + while (searchResult.getLink(IBaseBundle.LINK_NEXT) != null) + { + searchResult = fhirClient.getGenericFhirClient().loadPage().next(searchResult).execute(); + entries.addAll(searchResult.getEntry()); + } + + return entries.stream().filter(Bundle.BundleEntryComponent::hasResource) + .map(Bundle.BundleEntryComponent::getResource).filter(r -> r instanceof DocumentReference) + .map(r -> (DocumentReference) r) + .filter(d -> d.getAuthor().stream().anyMatch(a -> a.hasIdentifier() + && NamingSystems.OrganizationIdentifier.SID.equals(a.getIdentifier().getSystem()) + && sendingOrganization != null && sendingOrganization.equals(a.getIdentifier().getValue()))) + .toList(); + } + catch (Exception exception) + { + logger.warn( + "Error while searching for existing DocumentReferences for project-identifier '{}' authored by '{}' on FHIR server with baseUrl '{}' in Task with id '{}'- {}", + projectIdentifier, sendingOrganization, fhirClient.getFhirBaseUrl(), taskId, + exception.getMessage()); + return List.of(); + } + } + private void sendMail(Task task, List createdIds, String sendingOrganization, String projectIdentifier) { String subject = "New data-set received in process '" + ConstantsDataTransfer.PROCESS_NAME_FULL_DATA_RECEIVE @@ -178,9 +214,9 @@ private void sendMail(Task task, List createdIds, String sendingOrganiza api.getMailService().send(subject, message.toString()); } - private IdType setIdBase(IdType idType, FhirClient fhirClient) + private IdType setIdBase(IdType idType) { - String fhirBaseUrl = fhirClient.getFhirBaseUrl(); + String fhirBaseUrl = fhirClientFactory.getFhirClient().getFhirBaseUrl(); return new IdType(fhirBaseUrl, idType.getResourceType(), idType.getIdPart(), idType.getVersionIdPart()); }