Skip to content
This repository was archived by the owner on Oct 6, 2025. It is now read-only.

Commit 770dc1e

Browse files
committed
Merge remote-tracking branch 'origin/release/0.3.4' into main
2 parents 379785a + 083c136 commit 770dc1e

34 files changed

Lines changed: 133 additions & 63 deletions

codex-process-data-transfer/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<parent>
99
<groupId>de.netzwerk-universitaetsmedizin.codex</groupId>
1010
<artifactId>codex-processes-ap1</artifactId>
11-
<version>0.3.3</version>
11+
<version>0.3.4</version>
1212
</parent>
1313

1414
<properties>

codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/DataTransferProcessPluginDefinition.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
public class DataTransferProcessPluginDefinition implements ProcessPluginDefinition
2222
{
23-
public static final String VERSION = "0.3.3";
23+
public static final String VERSION = "0.3.4";
2424

2525
@Override
2626
public String getName()

codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/client/FttpClientImpl.java

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,6 @@ public class FttpClientImpl implements FttpClient, InitializingBean
4545
private final String fttpTarget;
4646
private final String fttpApiKey;
4747

48-
private final String proxySchemeHostPort;
49-
private final String proxyUsername;
50-
private final String proxyPassword;
51-
5248
private final boolean hapiClientVerbose;
5349

5450
public FttpClientImpl(KeyStore trustStore, KeyStore keyStore, char[] keyStorePassword, int connectTimeout,
@@ -67,9 +63,7 @@ public FttpClientImpl(KeyStore trustStore, KeyStore keyStore, char[] keyStorePas
6763
this.fttpStudy = fttpStudy;
6864
this.fttpTarget = fttpTarget;
6965

70-
this.proxySchemeHostPort = proxySchemeHostPort;
71-
this.proxyUsername = proxyUsername;
72-
this.proxyPassword = proxyPassword;
66+
configureProxy(clientFactory, proxySchemeHostPort, proxyUsername, proxyPassword);
7367

7468
this.hapiClientVerbose = hapiClientVerbose;
7569
}
@@ -85,7 +79,6 @@ protected ApacheRestfulClientFactoryWithTlsConfig createClientFactory(KeyStore t
8579
ApacheRestfulClientFactoryWithTlsConfig hapiClientFactory = new ApacheRestfulClientFactoryWithTlsConfig(
8680
fhirContext, trustStore, keyStore, keyStorePassword);
8781
hapiClientFactory.setServerValidationMode(ServerValidationModeEnum.NEVER);
88-
configureProxy(hapiClientFactory);
8982

9083
hapiClientFactory.setConnectTimeout(connectTimeout);
9184
hapiClientFactory.setSocketTimeout(socketTimeout);
@@ -95,7 +88,8 @@ protected ApacheRestfulClientFactoryWithTlsConfig createClientFactory(KeyStore t
9588
return hapiClientFactory;
9689
}
9790

98-
private void configureProxy(ApacheRestfulClientFactoryWithTlsConfig clientFactory)
91+
private void configureProxy(IRestfulClientFactory clientFactory, String proxySchemeHostPort, String proxyUsername,
92+
String proxyPassword)
9993
{
10094
if (StringUtils.isNotBlank(proxySchemeHostPort))
10195
{

codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/client/HapiFhirClientFactory.java

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@
44

55
import org.hl7.fhir.instance.model.api.IBaseBundle;
66
import org.hl7.fhir.instance.model.api.IBaseResource;
7+
import org.hl7.fhir.r4.model.CapabilityStatement;
78
import org.slf4j.Logger;
89
import org.slf4j.LoggerFactory;
10+
import org.springframework.context.event.ContextRefreshedEvent;
11+
import org.springframework.context.event.EventListener;
912

1013
import ca.uhn.fhir.context.FhirContext;
1114
import ca.uhn.fhir.interceptor.api.IInterceptorService;
@@ -50,6 +53,7 @@ public class HapiFhirClientFactory
5053
private final String bearerToken;
5154

5255
private final boolean hapiClientVerbose;
56+
private final boolean useChainedParameterNotLogicalReference;
5357

5458
private final ApacheRestfulClientFactory clientFactory;
5559

@@ -70,10 +74,14 @@ public class HapiFhirClientFactory
7074
* >= -1, -1: system default, 0: infinity, >0: timeout in ms
7175
* @param connectionRequestTimeout
7276
* >= -1, -1: system default, 0: infinity, >0: timeout in ms
77+
* @param hapiClientVerbose
78+
* <code>true</code> for verbose logging
79+
* @param useChainedParameterNotLogicalReference
80+
* <code>true</code> to enable modifying the search parameters during data storage
7381
*/
7482
public HapiFhirClientFactory(FhirContext fhirContext, String serverBase, String basicAuthUsername,
7583
String basicAuthPassword, String bearerToken, int connectTimeout, int socketTimeout,
76-
int connectionRequestTimeout, boolean hapiClientVerbose)
84+
int connectionRequestTimeout, boolean hapiClientVerbose, boolean useChainedParameterNotLogicalReference)
7785
{
7886
if (fhirContext != null)
7987
this.fhirContext = fhirContext;
@@ -86,6 +94,7 @@ public HapiFhirClientFactory(FhirContext fhirContext, String serverBase, String
8694
this.bearerToken = bearerToken;
8795

8896
this.hapiClientVerbose = hapiClientVerbose;
97+
this.useChainedParameterNotLogicalReference = useChainedParameterNotLogicalReference;
8998

9099
if (isConfigured())
91100
{
@@ -99,6 +108,33 @@ public HapiFhirClientFactory(FhirContext fhirContext, String serverBase, String
99108
clientFactory = null;
100109
}
101110

111+
@EventListener({ ContextRefreshedEvent.class })
112+
public void onContextRefreshedEvent(ContextRefreshedEvent event)
113+
{
114+
if (isConfigured())
115+
{
116+
try
117+
{
118+
logger.info(
119+
"Testing connection to GECCO FHIR server with {basicAuthUsername: {}, basicAuthPassword: {}, bearerToken: {}, serverBase: {}}",
120+
basicAuthUsername, basicAuthPassword != null ? "***" : "null",
121+
bearerToken != null ? "***" : "null", serverBase);
122+
123+
CapabilityStatement statement = getFhirStoreClient().capabilities().ofType(CapabilityStatement.class)
124+
.execute();
125+
126+
logger.info("Connection test OK {} - {}", statement.getSoftware().getName(),
127+
statement.getSoftware().getVersion());
128+
}
129+
catch (Exception e)
130+
{
131+
logger.error("Error while testing connection to GECCO FHIR server", e);
132+
}
133+
}
134+
else
135+
logger.warn("GECCO FHIR server Client stub implementation, no connection test performed");
136+
}
137+
102138
protected boolean isConfigured()
103139
{
104140
return serverBase != null && !serverBase.isEmpty();
@@ -474,4 +510,9 @@ private void configureLoggingInterceptor(IGenericClient client)
474510
client.registerInterceptor(loggingInterceptor);
475511
}
476512
}
513+
514+
public boolean shouldUseChainedParameterNotLogicalReference()
515+
{
516+
return useChainedParameterNotLogicalReference;
517+
}
477518
}

codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/client/fhir/FhirBridgeClient.java

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@ public class FhirBridgeClient extends AbstractComplexFhirClient
3030
private static final Logger logger = LoggerFactory.getLogger(FhirBridgeClient.class);
3131
private static final OutcomeLogger outcomeLogger = new OutcomeLogger(logger);
3232

33-
public static final String RFC_4122_SYSTEM = "urn:ietf:rfc:4122";
34-
3533
/**
3634
* @param fhirContext
3735
* not <code>null</code>
@@ -209,32 +207,35 @@ private void createOrUpdateEntry(int index, BundleEntryComponent entry, Patient
209207

210208
private Optional<Resource> findResourceInLocalFhirStore(String url, Class<? extends Resource> resourceType)
211209
{
210+
if (clientFactory.shouldUseChainedParameterNotLogicalReference())
211+
url = url.replace("patient:identifier", "patient.identifier");
212+
212213
try
213214
{
214-
Bundle patientBundle = clientFactory.getFhirStoreClient().search().byUrl(url).sort()
215+
Bundle resultBundle = clientFactory.getFhirStoreClient().search().byUrl(url).sort()
215216
.descending("_lastUpdated").count(1).returnBundle(Bundle.class).execute();
216217

217218
if (logger.isDebugEnabled())
218219
logger.debug("{} search-bundle result: {}", resourceType.getAnnotation(ResourceDef.class).name(),
219-
fhirContext.newJsonParser().encodeResourceToString(patientBundle));
220+
fhirContext.newJsonParser().encodeResourceToString(resultBundle));
220221

221-
if (patientBundle.getTotal() > 0)
222+
if (resultBundle.getTotal() > 0)
222223
{
223-
if (patientBundle.getTotal() > 1)
224+
if (resultBundle.getTotal() > 1)
224225
logger.warn("FHIR store has more than one Resource with url {}, using last updated", url);
225226

226-
if (patientBundle.getEntryFirstRep().hasResource()
227-
&& resourceType.isInstance(patientBundle.getEntryFirstRep().getResource()))
228-
return Optional.of((Patient) patientBundle.getEntryFirstRep().getResource());
227+
if (resultBundle.getEntryFirstRep().hasResource()
228+
&& resourceType.isInstance(resultBundle.getEntryFirstRep().getResource()))
229+
return Optional.of(resultBundle.getEntryFirstRep().getResource());
229230
else
230231
{
231232
logger.warn("Error while search for Resource with url {}, bundle has no {} resource", url,
232233
resourceType.getAnnotation(ResourceDef.class).name());
233234

234-
if (patientBundle.getEntryFirstRep().getResponse().hasOutcome()
235-
&& patientBundle.getEntryFirstRep().getResponse().getOutcome() instanceof OperationOutcome)
235+
if (resultBundle.getEntryFirstRep().getResponse().hasOutcome()
236+
&& resultBundle.getEntryFirstRep().getResponse().getOutcome() instanceof OperationOutcome)
236237
outcomeLogger.logOutcome(
237-
(OperationOutcome) patientBundle.getEntryFirstRep().getResponse().getOutcome());
238+
(OperationOutcome) resultBundle.getEntryFirstRep().getResponse().getOutcome());
238239

239240
return Optional.empty();
240241
}

codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/ReadData.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ public class ReadData extends AbstractServiceDelegate
5858
{
5959
private static final String NUM_CODEX_STRUCTURE_DEFINITION_PREFIX = "https://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition";
6060
private static final String MII_LAB_STRUCTURED_DEFINITION = "https://www.medizininformatik-initiative.de/fhir/core/modul-labor/StructureDefinition/ObservationLab";
61+
private static final String NUM_CODEX_DO_NOT_RESUSCITAT_ORDER = "https://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/do-not-resuscitate-order";
6162

6263
private static final Logger logger = LoggerFactory.getLogger(ReadData.class);
6364

@@ -249,6 +250,35 @@ else if (resource instanceof Condition)
249250
+ c.getRecordedDateElement().getValueAsString() + "&patient:identifier="
250251
+ ConstantsDataTransfer.NAMING_SYSTEM_NUM_CODEX_DIC_PSEUDONYM + "|" + pseudonym;
251252
}
253+
else if (resource instanceof Consent)
254+
{
255+
Consent c = (Consent) resource;
256+
String profileUrl = getProfileUrl(resource, v -> v.startsWith(NUM_CODEX_STRUCTURE_DEFINITION_PREFIX));
257+
258+
if (NUM_CODEX_DO_NOT_RESUSCITAT_ORDER.equals(profileUrl))
259+
{
260+
boolean scopePresent = c.getScope().getCoding().stream().filter(co -> co.hasSystem())
261+
.filter(co -> "http://terminology.hl7.org/CodeSystem/consentscope".equals(co.getSystem()))
262+
.filter(co -> co.hasCode()).filter(co -> "adr".equals(co.getCode())).findAny().isPresent();
263+
boolean categoryPresent = c.getCategory().stream().flatMap(coc -> coc.getCoding().stream())
264+
.filter(co -> co.hasSystem())
265+
.filter(co -> "http://terminology.hl7.org/CodeSystem/consentcategorycodes"
266+
.equals(co.getSystem()))
267+
.filter(co -> co.hasCode()).filter(co -> "dnr".equals(co.getCode())).findAny().isPresent();
268+
269+
if (scopePresent && categoryPresent)
270+
return "Consent?_profile=" + profileUrl
271+
+ "&scope=http://terminology.hl7.org/CodeSystem/consentscope|adr"
272+
+ "&category=http://terminology.hl7.org/CodeSystem/consentcategorycodes|dnr"
273+
+ "&patient:identifier=" + ConstantsDataTransfer.NAMING_SYSTEM_NUM_CODEX_DIC_PSEUDONYM + "|"
274+
+ pseudonym;
275+
else
276+
throw new RuntimeException("Resource of type Consent with profile " + profileUrl
277+
+ " is missing scope: http://terminology.hl7.org/CodeSystem/consentscope|adr and/or category: http://terminology.hl7.org/CodeSystem/consentcategorycodes|dnr");
278+
}
279+
else
280+
throw new RuntimeException("Resource of type Consent with profile " + profileUrl + " not supported");
281+
}
252282
else if (resource instanceof DiagnosticReport)
253283
{
254284
DiagnosticReport dr = (DiagnosticReport) resource;

codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/spring/config/TransferDataConfig.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ public class TransferDataConfig
9393
@Value("${de.netzwerk_universitaetsmedizin.codex.fhir.client:de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.client.fhir.FhirBridgeClient}")
9494
private String fhirStoreClientClass;
9595

96+
@Value("${de.netzwerk_universitaetsmedizin.codex.fhir.useChainedParameterNotLogicalReference:true}")
97+
private boolean fhirStoreUseChainedParameterNotLogicalReference;
98+
9699
@Value("${de.netzwerk_universitaetsmedizin.codex.fhir.searchBundleOverride:#{null}}")
97100
private String fhirStoreSearchBundleOverride;
98101

@@ -176,7 +179,8 @@ public HapiFhirClientFactory hapiFhirClientFactory()
176179
{
177180
return new HapiFhirClientFactory(fhirContext, fhirStoreBaseUrl, fhirStoreUsername, fhirStorePassword,
178181
fhirStoreBearerToken, fhirStoreConnectTimeout, fhirStoreSocketTimeout,
179-
fhirStoreConnectionRequestTimeout, fhirStoreHapiClientVerbose);
182+
fhirStoreConnectionRequestTimeout, fhirStoreHapiClientVerbose,
183+
fhirStoreUseChainedParameterNotLogicalReference);
180184
}
181185

182186
@Bean

codex-process-data-transfer/src/main/resources/bpe/receive.bpmn

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_18azqkl" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.2.0">
3-
<bpmn:process id="dataReceive" isExecutable="true" camunda:versionTag="0.3.3">
3+
<bpmn:process id="dataReceive" isExecutable="true" camunda:versionTag="0.3.4">
44
<bpmn:startEvent id="DataReceiveMessageStartEvent" name="start data receive process">
55
<bpmn:outgoing>Flow_1gyqorb</bpmn:outgoing>
66
<bpmn:messageEventDefinition id="MessageEventDefinition_1qwi1k6" messageRef="Message_157qpi8" />

codex-process-data-transfer/src/main/resources/bpe/send.bpmn

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_008keuw" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.8.1">
3-
<bpmn:process id="dataSend" isExecutable="true" camunda:versionTag="0.3.3">
3+
<bpmn:process id="dataSend" isExecutable="true" camunda:versionTag="0.3.4">
44
<bpmn:startEvent id="DataSendMessageStartEvent" name="start data send process">
55
<bpmn:outgoing>Flow_1km61ly</bpmn:outgoing>
66
<bpmn:messageEventDefinition id="MessageEventDefinition_07sumgd" messageRef="Message_0mcjkpi" />
@@ -21,7 +21,7 @@
2121
<bpmn:extensionElements>
2222
<camunda:inputOutput>
2323
<camunda:inputParameter name="processDefinitionKey">dataTranslate</camunda:inputParameter>
24-
<camunda:inputParameter name="versionTag">0.3.3</camunda:inputParameter>
24+
<camunda:inputParameter name="versionTag">0.3.4</camunda:inputParameter>
2525
<camunda:inputParameter name="messageName">startDataTranslate</camunda:inputParameter>
2626
<camunda:inputParameter name="profile">http://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-start-data-translate</camunda:inputParameter>
2727
</camunda:inputOutput>

codex-process-data-transfer/src/main/resources/bpe/translate.bpmn

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_1davgtw" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.2.0">
3-
<bpmn:process id="dataTranslate" isExecutable="true" camunda:versionTag="0.3.3">
3+
<bpmn:process id="dataTranslate" isExecutable="true" camunda:versionTag="0.3.4">
44
<bpmn:startEvent id="DataTranslateMessageStartEvent" name="start data translate process">
55
<bpmn:outgoing>Flow_185r1m5</bpmn:outgoing>
66
<bpmn:messageEventDefinition id="MessageEventDefinition_0nqjzhp" messageRef="Message_1nly3ld" />
@@ -25,7 +25,7 @@
2525
<bpmn:extensionElements>
2626
<camunda:inputOutput>
2727
<camunda:inputParameter name="processDefinitionKey">dataReceive</camunda:inputParameter>
28-
<camunda:inputParameter name="versionTag">0.3.3</camunda:inputParameter>
28+
<camunda:inputParameter name="versionTag">0.3.4</camunda:inputParameter>
2929
<camunda:inputParameter name="messageName">startDataReceive</camunda:inputParameter>
3030
<camunda:inputParameter name="profile">http://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/task-start-data-receive</camunda:inputParameter>
3131
</camunda:inputOutput>

0 commit comments

Comments
 (0)