-
Notifications
You must be signed in to change notification settings - Fork 49
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add common getExpansion() function (#763)
* Add common getExpansion() function * Mock out server calls * Specify charset * Add TerminologyServerClient Bean to config * Refactor - make client non VSAC specific & add statuc variables * getExpansion changes * Refactor - take credentials from properties, cleanup, add IT * Fix issue with authoritative source url and system-version parameter Update test file to reflect actual value set * Remove addition of ValueSet level system-version param & update test to reflect. Privatise getters/setters. --------- Co-authored-by: Adam Stevenson <stevenson_adam@yahoo.com>
- Loading branch information
Showing
10 changed files
with
508 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
79 changes: 79 additions & 0 deletions
79
plugin/cr/src/main/java/org/opencds/cqf/ruler/cr/TerminologyServerClient.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
package org.opencds.cqf.ruler.cr; | ||
|
||
import ca.uhn.fhir.context.FhirContext; | ||
import ca.uhn.fhir.rest.client.api.IGenericClient; | ||
import ca.uhn.fhir.rest.client.interceptor.AdditionalRequestHeadersInterceptor; | ||
import org.apache.commons.lang3.StringUtils; | ||
import org.hl7.fhir.r4.model.Parameters; | ||
import org.hl7.fhir.r4.model.ValueSet; | ||
import org.jetbrains.annotations.NotNull; | ||
import org.opencds.cqf.cql.evaluator.fhir.util.Canonicals; | ||
|
||
import java.nio.charset.StandardCharsets; | ||
import java.util.Base64; | ||
|
||
public class TerminologyServerClient { | ||
|
||
private final FhirContext ctx; | ||
|
||
private String username; | ||
|
||
private String getUsername() { | ||
return username; | ||
} | ||
|
||
private void setUsername(String username) { | ||
this.username = username; | ||
} | ||
|
||
private String apiKey; | ||
|
||
private String getApiKey() { | ||
return apiKey; | ||
} | ||
|
||
private void setApiKey(String apiKey) { | ||
this.apiKey = apiKey; | ||
} | ||
public TerminologyServerClient() { | ||
ctx = FhirContext.forR4(); | ||
} | ||
|
||
public TerminologyServerClient(String username, String apiKey) { | ||
this(); | ||
setUsername(username); | ||
setApiKey(apiKey); | ||
} | ||
|
||
public ValueSet expand(ValueSet valueSet, String authoritativeSource, Parameters expansionParameters) { | ||
IGenericClient fhirClient = ctx.newRestfulGenericClient(getAuthoritativeSourceBase(authoritativeSource)); | ||
fhirClient.registerInterceptor(getAuthInterceptor(getUsername(), getApiKey())); | ||
|
||
// Invoke by Value Set ID | ||
return fhirClient | ||
.operation() | ||
.onInstance(valueSet.getId()) | ||
.named("$expand") | ||
.withParameters(expansionParameters) | ||
.returnResourceType(ValueSet.class) | ||
.execute(); | ||
} | ||
|
||
private AdditionalRequestHeadersInterceptor getAuthInterceptor(String username, String apiKey) { | ||
String authString = StringUtils.join("Basic ", Base64.getEncoder() | ||
.encodeToString(StringUtils.join(username, ":", apiKey).getBytes(StandardCharsets.UTF_8))); | ||
AdditionalRequestHeadersInterceptor authInterceptor = new AdditionalRequestHeadersInterceptor(); | ||
authInterceptor.addHeaderValue("Authorization", authString); | ||
return authInterceptor; | ||
} | ||
|
||
// Strips resource and id from the authoritative source URL, these are not needed as the client constructs the URL. | ||
// Converts http URLs to https | ||
private String getAuthoritativeSourceBase(String authoritativeSource) { | ||
authoritativeSource = authoritativeSource.substring(0, authoritativeSource.indexOf(Canonicals.getResourceType(authoritativeSource))); | ||
if (authoritativeSource.startsWith("http://")) { | ||
authoritativeSource = authoritativeSource.replaceFirst("http://", "https://"); | ||
} | ||
return authoritativeSource; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,3 +2,5 @@ hapi: | |
fhir: | ||
rulercr: | ||
enabled: true | ||
vsac-username: | ||
vsac-api-key: |
51 changes: 51 additions & 0 deletions
51
plugin/cr/src/test/java/org/opencds/cqf/ruler/cr/KnowledgeArtifactProcessorIT.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package org.opencds.cqf.ruler.cr; | ||
|
||
import ca.uhn.fhir.context.FhirContext; | ||
import ca.uhn.fhir.parser.IParser; | ||
import org.hl7.fhir.r4.model.Parameters; | ||
import org.hl7.fhir.r4.model.ValueSet; | ||
import org.junit.jupiter.api.Disabled; | ||
import org.junit.jupiter.api.Test; | ||
import org.opencds.cqf.ruler.test.RestIntegrationTest; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.boot.test.context.SpringBootTest; | ||
import org.springframework.context.annotation.Lazy; | ||
|
||
import java.io.IOException; | ||
|
||
import static org.junit.jupiter.api.Assertions.*; | ||
|
||
@Lazy | ||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, | ||
classes = {KnowledgeArtifactProcessorIT.class, CrConfig.class}, | ||
properties = {"hapi.fhir.fhir_version=r4", "hapi.fhir.security.basic_auth.enabled=false"}) | ||
public class KnowledgeArtifactProcessorIT extends RestIntegrationTest { | ||
|
||
@Autowired | ||
KnowledgeArtifactProcessor processor; | ||
|
||
@Autowired | ||
TerminologyServerClient client; | ||
|
||
@Disabled | ||
@Test | ||
void testGetExpansionVSAC() throws IOException { | ||
// given | ||
FhirContext ctx = FhirContext.forR4(); | ||
|
||
String input = new String(this.getClass().getResourceAsStream("r4/valueset/valueset-2.16.840.1.113762.1.4.1116.89.json").readAllBytes()); | ||
IParser parser = ctx.newJsonParser(); | ||
ValueSet valueSet = parser.parseResource(ValueSet.class, input); | ||
String codeSystemVersion = valueSet.getCompose().getInclude().get(0).getVersion(); | ||
|
||
Parameters expansionParameters = new Parameters(); | ||
|
||
// when | ||
processor.expandValueSet(valueSet, expansionParameters); | ||
|
||
// then | ||
assertNotNull(valueSet.getExpansion()); | ||
assertEquals(16, valueSet.getExpansion().getTotal()); | ||
} | ||
|
||
} |
75 changes: 75 additions & 0 deletions
75
plugin/cr/src/test/java/org/opencds/cqf/ruler/cr/KnowledgeArtifactProcessorTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
package org.opencds.cqf.ruler.cr; | ||
|
||
import ca.uhn.fhir.context.FhirContext; | ||
import ca.uhn.fhir.parser.IParser; | ||
import org.hl7.fhir.r4.model.Parameters; | ||
import org.hl7.fhir.r4.model.ValueSet; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.extension.ExtendWith; | ||
import org.mockito.InjectMocks; | ||
import org.mockito.Mock; | ||
import org.mockito.Mockito; | ||
import org.mockito.junit.jupiter.MockitoExtension; | ||
|
||
import java.io.IOException; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
import static org.junit.jupiter.api.Assertions.assertNotNull; | ||
import static org.junit.jupiter.api.Assertions.assertTrue; | ||
|
||
@ExtendWith(MockitoExtension.class) | ||
public class KnowledgeArtifactProcessorTest { | ||
|
||
@InjectMocks | ||
KnowledgeArtifactProcessor processor; | ||
|
||
@Mock | ||
TerminologyServerClient client; | ||
|
||
@Test | ||
void testGetExpansionVSAC() throws IOException { | ||
// given | ||
FhirContext ctx = FhirContext.forR4(); | ||
|
||
String input = new String(this.getClass().getResourceAsStream("r4/valueset/valueset-2.16.840.1.113762.1.4.1116.89.json").readAllBytes()); | ||
IParser parser = ctx.newJsonParser(); | ||
ValueSet valueSet = parser.parseResource(ValueSet.class, input); | ||
|
||
Parameters expansionParameters = new Parameters(); | ||
expansionParameters.addParameter("system-version", "http://snomed.info/sct|http://snomed.info/sct/731000124108/version/20230901"); | ||
|
||
// when | ||
String expandedValueSetString = new String(this.getClass().getResourceAsStream("r4/test/valueset-expanded.json").readAllBytes()); | ||
ValueSet expandedValueSet = parser.parseResource(ValueSet.class, expandedValueSetString); | ||
Mockito.when(client.expand(Mockito.eq(valueSet), Mockito.eq(valueSet.getUrl()), Mockito.eq(expansionParameters))).thenReturn(expandedValueSet); | ||
|
||
processor.expandValueSet(valueSet, expansionParameters); | ||
|
||
// then | ||
assertNotNull(valueSet.getExpansion()); | ||
assertEquals(16, valueSet.getExpansion().getTotal()); | ||
} | ||
|
||
@Test | ||
void testGetExpansionNaive() throws IOException { | ||
FhirContext ctx = FhirContext.forR4(); | ||
|
||
String input = new String(this.getClass().getResourceAsStream("r4/valueset/valueset-vsm-authored.json").readAllBytes()); | ||
IParser parser = ctx.newJsonParser(); | ||
ValueSet valueSet = parser.parseResource(ValueSet.class, input); | ||
Parameters expansionParameters = new Parameters(); | ||
expansionParameters.addParameter("system-version", "http://snomed.info/sct|http://snomed.info/sct/731000124108/version/20230901"); | ||
|
||
// when | ||
processor.expandValueSet(valueSet, expansionParameters); | ||
|
||
// then | ||
assertNotNull(valueSet.getExpansion()); | ||
assertNotNull(valueSet.getExpansion().getParameter().get(0)); | ||
assertEquals("naive", valueSet.getExpansion().getParameter().get(0).getName()); | ||
assertTrue(valueSet.getExpansion().getParameter().get(0).getValueBooleanType().booleanValue()); | ||
assertEquals(1, valueSet.getExpansion().getContains().size()); | ||
assertEquals("ANC.A.DE13", valueSet.getExpansion().getContains().get(0).getCode()); | ||
assertEquals("Co-habitants", valueSet.getExpansion().getContains().get(0).getDisplay()); | ||
} | ||
} |
Oops, something went wrong.