Skip to content

Commit ba0589c

Browse files
authored
Moved terminology config out of being R4 specific. It now applies to all versions (hapifhir#822)
1 parent 5ee2e47 commit ba0589c

File tree

3 files changed

+89
-66
lines changed

3 files changed

+89
-66
lines changed
Lines changed: 1 addition & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,9 @@
11
package ca.uhn.fhir.jpa.starter.common;
22

3-
import ca.uhn.fhir.context.FhirContext;
4-
import ca.uhn.fhir.context.support.ConceptValidationOptions;
5-
import ca.uhn.fhir.context.support.IValidationSupport;
6-
import ca.uhn.fhir.context.support.ValidationSupportContext;
73
import ca.uhn.fhir.jpa.config.r4.JpaR4Config;
8-
import ca.uhn.fhir.jpa.starter.AppProperties;
94
import ca.uhn.fhir.jpa.starter.annotations.OnR4Condition;
10-
import ca.uhn.fhir.jpa.starter.common.validation.OnRemoteTerminologyPresent;
115
import ca.uhn.fhir.jpa.starter.cr.StarterCrR4Config;
126
import ca.uhn.fhir.jpa.starter.ips.StarterIpsConfig;
13-
import org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport;
14-
import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain;
15-
import org.springframework.context.annotation.Bean;
167
import org.springframework.context.annotation.Conditional;
178
import org.springframework.context.annotation.Configuration;
189
import org.springframework.context.annotation.Import;
@@ -26,53 +17,4 @@
2617
ElasticsearchConfig.class,
2718
StarterIpsConfig.class
2819
})
29-
public class FhirServerConfigR4 {
30-
31-
@Bean(name = "myHybridRemoteValidationSupportChain")
32-
@Conditional({OnR4Condition.class, OnRemoteTerminologyPresent.class})
33-
public IValidationSupport addRemoteValidation(
34-
ValidationSupportChain theValidationSupport, FhirContext theFhirContext, AppProperties theAppProperties) {
35-
var values = theAppProperties.getRemoteTerminologyServicesMap().values();
36-
37-
// If the remote terminology service is "*" and is the only one then forward all requests to the remote
38-
// terminology service
39-
if (values.size() == 1 && "*".equalsIgnoreCase(values.iterator().next().getSystem())) {
40-
var remoteSystem = values.iterator().next();
41-
theValidationSupport.addValidationSupport(
42-
0, new RemoteTerminologyServiceValidationSupport(theFhirContext, remoteSystem.getUrl()));
43-
return theValidationSupport;
44-
45-
// If there are multiple remote terminology services, then add each one to the validation chain
46-
} else {
47-
values.forEach((remoteSystem) -> theValidationSupport.addValidationSupport(
48-
0, new RemoteTerminologyServiceValidationSupport(theFhirContext, remoteSystem.getUrl()) {
49-
@Override
50-
public boolean isCodeSystemSupported(
51-
ValidationSupportContext theValidationSupportContext, String theSystem) {
52-
return remoteSystem.getSystem().equalsIgnoreCase(theSystem);
53-
}
54-
55-
@Override
56-
public CodeValidationResult validateCode(
57-
ValidationSupportContext theValidationSupportContext,
58-
ConceptValidationOptions theOptions,
59-
String theCodeSystem,
60-
String theCode,
61-
String theDisplay,
62-
String theValueSetUrl) {
63-
if (remoteSystem.getSystem().equalsIgnoreCase(theCodeSystem)) {
64-
return super.validateCode(
65-
theValidationSupportContext,
66-
theOptions,
67-
theCodeSystem,
68-
theCode,
69-
theDisplay,
70-
theValueSetUrl);
71-
}
72-
return null;
73-
}
74-
}));
75-
}
76-
return theValidationSupport;
77-
}
78-
}
20+
public class FhirServerConfigR4 {}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package ca.uhn.fhir.jpa.starter.terminology;
2+
3+
import ca.uhn.fhir.context.FhirContext;
4+
import ca.uhn.fhir.context.support.ConceptValidationOptions;
5+
import ca.uhn.fhir.context.support.IValidationSupport;
6+
import ca.uhn.fhir.context.support.ValidationSupportContext;
7+
import ca.uhn.fhir.jpa.starter.AppProperties;
8+
import ca.uhn.fhir.jpa.starter.common.StarterJpaConfig;
9+
import ca.uhn.fhir.jpa.starter.common.validation.OnRemoteTerminologyPresent;
10+
import org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport;
11+
import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain;
12+
import org.springframework.context.annotation.Bean;
13+
import org.springframework.context.annotation.Conditional;
14+
import org.springframework.context.annotation.Configuration;
15+
import org.springframework.context.annotation.Import;
16+
17+
@Configuration
18+
@Conditional(OnRemoteTerminologyPresent.class)
19+
@Import(StarterJpaConfig.class)
20+
public class TerminologyConfig {
21+
22+
@Bean(name = "myHybridRemoteValidationSupportChain")
23+
public IValidationSupport addRemoteValidation(
24+
ValidationSupportChain theValidationSupport, FhirContext theFhirContext, AppProperties theAppProperties) {
25+
var values = theAppProperties.getRemoteTerminologyServicesMap().values();
26+
27+
// If the remote terminology service is "*" and is the only one then forward all requests to the remote
28+
// terminology service
29+
if (values.size() == 1 && "*".equalsIgnoreCase(values.iterator().next().getSystem())) {
30+
var remoteSystem = values.iterator().next();
31+
theValidationSupport.addValidationSupport(
32+
0, new RemoteTerminologyServiceValidationSupport(theFhirContext, remoteSystem.getUrl()));
33+
return theValidationSupport;
34+
35+
// If there are multiple remote terminology services, then add each one to the validation chain
36+
} else {
37+
values.forEach((remoteSystem) -> theValidationSupport.addValidationSupport(
38+
0, new RemoteTerminologyServiceValidationSupport(theFhirContext, remoteSystem.getUrl()) {
39+
@Override
40+
public boolean isCodeSystemSupported(
41+
ValidationSupportContext theValidationSupportContext, String theSystem) {
42+
return remoteSystem.getSystem().equalsIgnoreCase(theSystem);
43+
}
44+
45+
@Override
46+
public CodeValidationResult validateCode(
47+
ValidationSupportContext theValidationSupportContext,
48+
ConceptValidationOptions theOptions,
49+
String theCodeSystem,
50+
String theCode,
51+
String theDisplay,
52+
String theValueSetUrl) {
53+
if (remoteSystem.getSystem().equalsIgnoreCase(theCodeSystem)) {
54+
return super.validateCode(
55+
theValidationSupportContext,
56+
theOptions,
57+
theCodeSystem,
58+
theCode,
59+
theDisplay,
60+
theValueSetUrl);
61+
}
62+
return null;
63+
}
64+
}));
65+
}
66+
return theValidationSupport;
67+
}
68+
}

src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,7 @@
1111
import jakarta.websocket.Session;
1212
import jakarta.websocket.WebSocketContainer;
1313
import org.hl7.fhir.instance.model.api.IIdType;
14-
import org.hl7.fhir.r5.model.Bundle;
15-
import org.hl7.fhir.r5.model.Enumerations;
16-
import org.hl7.fhir.r5.model.Observation;
17-
import org.hl7.fhir.r5.model.Patient;
18-
import org.hl7.fhir.r5.model.Subscription;
19-
import org.hl7.fhir.r5.model.SubscriptionTopic;
14+
import org.hl7.fhir.r5.model.*;
2015
import org.junit.jupiter.api.BeforeEach;
2116
import org.junit.jupiter.api.Test;
2217
import org.junit.jupiter.api.extension.ExtendWith;
@@ -36,7 +31,9 @@
3631
"spring.datasource.url=jdbc:h2:mem:dbr5",
3732
"hapi.fhir.fhir_version=r5",
3833
"hapi.fhir.cr_enabled=false",
39-
"hapi.fhir.subscription.websocket_enabled=true"
34+
"hapi.fhir.subscription.websocket_enabled=true",
35+
"hapi.fhir.remote_terminology_service.snomed.system=http://snomed.info/sct",
36+
"hapi.fhir.remote_terminology_service.snomed.url=https://tx.fhir.org/r5"
4037
})
4138
public class ExampleServerR5IT {
4239

@@ -156,6 +153,22 @@ void testWebsocketSubscription() throws Exception {
156153
ourClient.delete().resourceById(mySubscriptionId).execute();
157154
}
158155

156+
157+
@Test
158+
void testValidateRemoteTerminology() {
159+
160+
String testCodeSystem = "http://foo/cs";
161+
String testValueSet = "http://foo/vs";
162+
ourClient.create().resource(new CodeSystem().setUrl(testCodeSystem).addConcept(new CodeSystem.ConceptDefinitionComponent().setCode("yes")).addConcept(new CodeSystem.ConceptDefinitionComponent().setCode("no"))).execute();
163+
ourClient.create().resource(new ValueSet().setUrl(testValueSet).setCompose(new ValueSet.ValueSetComposeComponent().addInclude(new ValueSet.ConceptSetComponent().setSystem(testValueSet)))).execute();
164+
165+
Parameters remoteResult = ourClient.operation().onType(ValueSet.class).named("$validate-code").withParameter(Parameters.class, "code", new StringType("22298006")).andParameter("system", new UriType("http://snomed.info/sct")).execute();
166+
assertEquals(true, ((BooleanType) remoteResult.getParameterValue("result")).getValue());
167+
assertEquals("Myocardial infarction", ((StringType) remoteResult.getParameterValue("display")).getValue());
168+
169+
Parameters localResult = ourClient.operation().onType(CodeSystem.class).named("$validate-code").withParameter(Parameters.class, "url", new UrlType(testCodeSystem)).andParameter("coding", new Coding(testCodeSystem, "yes", null)).execute();
170+
}
171+
159172
@BeforeEach
160173
void beforeEach() {
161174

0 commit comments

Comments
 (0)