From a7a9c6a874173cf43793c13204703a4f94242c9a Mon Sep 17 00:00:00 2001 From: Prateek Keerthi Date: Wed, 22 May 2024 18:39:59 -0400 Subject: [PATCH 1/2] MAT-7223 and MAT-7224 updating logic to display and add svs versions when apply ic cliked --- .../gov/cms/madie/terminology/dto/Code.java | 2 +- .../service/FhirTerminologyService.java | 102 +++++++++++------- .../terminology/service/VsacService.java | 2 +- .../VsacFhirTerminologyControllerMvcTest.java | 3 +- .../VsacFhirTerminologyControllerTest.java | 32 ++++-- .../service/FhirTerminologyServiceTest.java | 27 ++++- .../terminology/service/VsacServiceTest.java | 10 +- 7 files changed, 120 insertions(+), 58 deletions(-) diff --git a/src/main/java/gov/cms/madie/terminology/dto/Code.java b/src/main/java/gov/cms/madie/terminology/dto/Code.java index f681ef8..72f29f0 100644 --- a/src/main/java/gov/cms/madie/terminology/dto/Code.java +++ b/src/main/java/gov/cms/madie/terminology/dto/Code.java @@ -8,7 +8,7 @@ public class Code { private String name; private String display; - private String version; // 'fhir' in the code-system-entry.json + private String fhirVersion; // 'fhir' in the code-system-entry.json private String svsVersion; // 'vsac' in the code-system-entry.json private String codeSystem; private String codeSystemOid; diff --git a/src/main/java/gov/cms/madie/terminology/service/FhirTerminologyService.java b/src/main/java/gov/cms/madie/terminology/service/FhirTerminologyService.java index 9064b04..09e589f 100644 --- a/src/main/java/gov/cms/madie/terminology/service/FhirTerminologyService.java +++ b/src/main/java/gov/cms/madie/terminology/service/FhirTerminologyService.java @@ -128,8 +128,8 @@ public List searchValueSets(String apiKey, Map { Resource resource = entry.getResource(); - ValueSet vs = (ValueSet) resource; - if (resource instanceof ValueSet) { + ValueSet vs = (ValueSet) resource; + if (resource instanceof ValueSet) { String oid = ""; for (Identifier identifier : ((ValueSet) resource).getIdentifier()) { if (identifier.getValue() != null && !identifier.getValue().isEmpty()) { @@ -139,17 +139,32 @@ public List searchValueSets(String apiKey, Map x.getSystem()).collect(Collectors.joining(","))) - .effectiveDate(String.valueOf(vs.getExtensionByUrl("http://hl7.org/fhir/StructureDefinition/valueset-effectiveDate").getValue())) - .lastReviewDate(String.valueOf(vs.getExtensionByUrl("http://hl7.org/fhir/StructureDefinition/resource-lastReviewDate").getValue())) - .lastUpdated(vs.getMeta().getLastUpdated().toString()) + .composedOf( + vs.getCompose().getInclude().stream() + .map(x -> x.getSystem()) + .collect(Collectors.joining(","))) + .effectiveDate( + String.valueOf( + vs.getExtensionByUrl( + "http://hl7.org/fhir/StructureDefinition/valueset-effectiveDate") + .getValue())) + .lastReviewDate( + String.valueOf( + vs.getExtensionByUrl( + "http://hl7.org/fhir/StructureDefinition/resource-lastReviewDate") + .getValue())) + .lastUpdated(vs.getMeta().getLastUpdated().toString()) .url(vs.getUrl()) .version(vs.getVersion()) .status(vs.getStatus()) - .publisher(vs.getPublisher()) - .purpose(vs.getPurpose()) + .publisher(vs.getPublisher()) + .purpose(vs.getPurpose()) .steward(vs.getPublisher()) .oid(oid) .build(); @@ -224,21 +239,18 @@ public Code retrieveCode(String codeName, String codeSystemName, String version, if (codeSystem == null) { return null; } - String codeJson = fhirTerminologyServiceWebClient.getCodeResource(codeName, codeSystem, apiKey); - Parameters parameters = fhirContext.newJsonParser().parseResource(Parameters.class, codeJson); - Code code = - Code.builder() - .name(codeName) - .codeSystem(codeSystemName) - .version(version) - .display(parameters.getParameter("display").getValue().toString()) - .codeSystemOid(parameters.getParameter("Oid").getValue().toString()) - .build(); - // FHIR terminology API doesn't support code status yet. workaround is to get it from SVS. - // TODO: remove once it is supported by fhir terminology service - CodeStatus status = vsacService.getCodeStatus(code, apiKey); - code.setStatus(status); - return code; + + List codeSystemEntries = mappingService.getCodeSystemEntries(); + Optional> mappedVersion = + mapVersion(version, codeSystem.getOid(), codeSystemEntries, "fhirVersion"); + + if (mappedVersion.isPresent()) { + String vsacVersion = mappedVersion.get().getKey(); + String fhirVersion = mappedVersion.get().getValue(); + + return retrieveCodes(codeName, codeSystemName, vsacVersion, fhirVersion, codeSystem, apiKey); + } + return null; } private void recursiveRetrieveCodeSystems( @@ -329,22 +341,34 @@ public List retrieveCodesAndCodeSystems(List> codeList String oid = code.get("oid") != null ? code.get("oid").replaceAll("'|'", "") : null; Optional> mappedVersion = - mapToFhirVersion(code.get("version"), oid, codeSystemEntries); + mapVersion(code.get("version"), oid, codeSystemEntries, "svsVersion"); if (mappedVersion.isPresent()) { String vsacVersion = mappedVersion.get().getKey(); String fhirVersion = mappedVersion.get().getValue(); + if (StringUtils.isEmpty(codeName) + || StringUtils.isEmpty(codeSystemName) + || StringUtils.isEmpty(fhirVersion)) { + return null; + } + + CodeSystem codeSystem = + codeSystemRepository.findByOidAndVersion(oid, fhirVersion).orElse(null); + if (codeSystem == null) { + return null; + } + return retrieveCodes( - codeName, codeSystemName, vsacVersion, fhirVersion, oid, apiKey); + codeName, codeSystemName, vsacVersion, fhirVersion, codeSystem, apiKey); } return null; }) .collect(Collectors.toList()); } - private Optional> mapToFhirVersion( - String version, String oid, List codeSystemEntries) { + private Optional> mapVersion( + String version, String oid, List codeSystemEntries, String versionType) { if (oid == null) { return Optional.empty(); } @@ -365,7 +389,14 @@ private Optional> mapToFhirVersion( codeSystemEntries.stream() .filter(codeSystemEntry -> StringUtils.equals(codeSystemEntry.getOid(), oid)) .flatMap(codeSystemEntry -> codeSystemEntry.getVersions().stream()) - .filter(codeSystemVersion -> StringUtils.equals(codeSystemVersion.getVsac(), version)) + // depending on the version type suitable mapping is done + .filter( + codeSystemVersion -> + StringUtils.equals( + versionType == "svsVersion" + ? codeSystemVersion.getVsac() + : codeSystemVersion.getFhir(), + version)) .map( codeSystemVersion -> Map.entry(codeSystemVersion.getVsac(), codeSystemVersion.getFhir())) @@ -380,17 +411,8 @@ private Code retrieveCodes( String codeSystemName, String vsacVersion, String fhirVersion, - String oid, + CodeSystem codeSystem, String apiKey) { - if (StringUtils.isEmpty(codeName) - || StringUtils.isEmpty(codeSystemName) - || StringUtils.isEmpty(fhirVersion)) { - return null; - } - CodeSystem codeSystem = codeSystemRepository.findByOidAndVersion(oid, fhirVersion).orElse(null); - if (codeSystem == null) { - return null; - } String codeJson = fhirTerminologyServiceWebClient.getCodeResource(codeName, codeSystem, apiKey); Parameters parameters = fhirContext.newJsonParser().parseResource(Parameters.class, codeJson); @@ -398,7 +420,7 @@ private Code retrieveCodes( Code.builder() .name(codeName) .codeSystem(codeSystemName) - .version(fhirVersion) + .fhirVersion(fhirVersion) .svsVersion(vsacVersion) .display(parameters.getParameter("display").getValue().toString()) .codeSystemOid(parameters.getParameter("Oid").getValue().toString()) diff --git a/src/main/java/gov/cms/madie/terminology/service/VsacService.java b/src/main/java/gov/cms/madie/terminology/service/VsacService.java index a214d54..fd65295 100644 --- a/src/main/java/gov/cms/madie/terminology/service/VsacService.java +++ b/src/main/java/gov/cms/madie/terminology/service/VsacService.java @@ -194,7 +194,7 @@ private String getSvsCodeSystemVersion(Code code) { // get corresponding SVS version for given FHIR version CodeSystemEntry.Version version = systemEntry.getVersions().stream() - .filter(v -> Objects.equals(v.getFhir(), code.getVersion())) + .filter(v -> Objects.equals(v.getFhir(), code.getFhirVersion())) .findFirst() .orElse(null); if (version == null || version.getVsac() == null) { diff --git a/src/test/java/gov/cms/madie/terminology/controller/VsacFhirTerminologyControllerMvcTest.java b/src/test/java/gov/cms/madie/terminology/controller/VsacFhirTerminologyControllerMvcTest.java index beed32c..0140b78 100644 --- a/src/test/java/gov/cms/madie/terminology/controller/VsacFhirTerminologyControllerMvcTest.java +++ b/src/test/java/gov/cms/madie/terminology/controller/VsacFhirTerminologyControllerMvcTest.java @@ -244,7 +244,8 @@ public void testGetCodeSuccessfully() throws Exception { Code.builder() .name(codeName) .codeSystem(codeSystem) - .version(version) + .fhirVersion(version) + .svsVersion(version) .display("Bicarbonate [Moles/volume] in Serum") .codeSystemOid("2.16.840.1.113883.6.1") .build(); diff --git a/src/test/java/gov/cms/madie/terminology/controller/VsacFhirTerminologyControllerTest.java b/src/test/java/gov/cms/madie/terminology/controller/VsacFhirTerminologyControllerTest.java index a576d46..a75f2e7 100644 --- a/src/test/java/gov/cms/madie/terminology/controller/VsacFhirTerminologyControllerTest.java +++ b/src/test/java/gov/cms/madie/terminology/controller/VsacFhirTerminologyControllerTest.java @@ -193,7 +193,8 @@ void testGetCode() { Code.builder() .name(codeName) .codeSystem(codeSystem) - .version(version) + .svsVersion(version) + .fhirVersion(version) .display("Bicarbonate [Moles/volume] in Serum") .codeSystemOid("2.16.840.1.113883.6.1") .build(); @@ -238,7 +239,8 @@ void testGetCodesList() { Code.builder() .name("1963-8") .codeSystem("LOINC") - .version("2.72") + .svsVersion("2.72") + .fhirVersion("2.72") .display("Bicarbonate [Moles/volume] in Serum") .codeSystemOid("2.16.840.1.113883.6.1") .status(CodeStatus.valueOf("ACTIVE")) @@ -258,10 +260,26 @@ void testGetCodesList() { @Test void testSearchValueSets() { List mockValueSets = new ArrayList<>(); - ValueSetForSearch v1 = ValueSetForSearch.builder().title("title 1").name("title1").url("url").oid("oid") - .steward("steward").version("version").codeSystem("cs").build(); - ValueSetForSearch v2 = ValueSetForSearch.builder().title("title 2").name("title2").url("url").oid("oid") - .steward("steward").version("version").codeSystem("cs").build(); + ValueSetForSearch v1 = + ValueSetForSearch.builder() + .title("title 1") + .name("title1") + .url("url") + .oid("oid") + .steward("steward") + .version("version") + .codeSystem("cs") + .build(); + ValueSetForSearch v2 = + ValueSetForSearch.builder() + .title("title 2") + .name("title2") + .url("url") + .oid("oid") + .steward("steward") + .version("version") + .codeSystem("cs") + .build(); mockValueSets.add(v1); mockValueSets.add(v2); Principal principal = mock(Principal.class); @@ -272,7 +290,7 @@ void testSearchValueSets() { queryParams.put("param1", "value1"); queryParams.put("param2", "value2"); ResponseEntity> response = - vsacFhirTerminologyController.searchValueSets(principal, queryParams); + vsacFhirTerminologyController.searchValueSets(principal, queryParams); assertEquals(response.getStatusCode(), HttpStatus.OK); } } diff --git a/src/test/java/gov/cms/madie/terminology/service/FhirTerminologyServiceTest.java b/src/test/java/gov/cms/madie/terminology/service/FhirTerminologyServiceTest.java index e483f25..8d695b8 100644 --- a/src/test/java/gov/cms/madie/terminology/service/FhirTerminologyServiceTest.java +++ b/src/test/java/gov/cms/madie/terminology/service/FhirTerminologyServiceTest.java @@ -435,8 +435,29 @@ void testRetrieveCodeSuccessfully() { + " \"valueString\": \"2.16.840.1.113883.6.1\"\n" + " } ]\n" + "}"; + codeSystemEntries = new ArrayList<>(); + CodeSystemEntry.Version versions = new CodeSystemEntry.Version(); + versions.setVsac("2.40"); + versions.setFhir("2.40"); + var codeSystemEntry = + CodeSystemEntry.builder() + .name("1963-8") + .oid("urn:oid:2.16.840.1.113883.6.1") + .url("http://loinc.org") + .versions(List.of(versions)) + .build(); + codeSystemEntries.add(codeSystemEntry); - var codeSystem = gov.cms.madie.terminology.models.CodeSystem.builder().build(); + var codeSystem = + gov.cms.madie.terminology.models.CodeSystem.builder() + .fullUrl("http://loinc.org") + .title("LOINC") + .name("LOINC") + .version("2.40") + .versionId("2084800774") + .oid("urn:oid:2.16.840.1.113883.6.1") + .build(); + when(mappingService.getCodeSystemEntries()).thenReturn(codeSystemEntries); when(codeSystemRepository.findByNameAndVersion(anyString(), anyString())) .thenReturn(Optional.of(codeSystem)); when(fhirTerminologyServiceWebClient.getCodeResource(codeName, codeSystem, TEST_API_KEY)) @@ -448,7 +469,7 @@ void testRetrieveCodeSuccessfully() { assertThat(code.getName(), is(equalTo(codeName))); assertThat(code.getDisplay(), is(equalTo("Bicarbonate [Moles/volume] in Serum"))); assertThat(code.getCodeSystem(), is(equalTo(codeSystemName))); - assertThat(code.getVersion(), is(equalTo(version))); + assertThat(code.getFhirVersion(), is(equalTo(version))); assertThat(code.getStatus(), is(equalTo(CodeStatus.ACTIVE))); } @@ -514,7 +535,7 @@ void testRetrieveCodesListSuccessfully() { assertThat(code.get(0).getName(), is(equalTo("1963-8"))); assertThat(code.get(0).getDisplay(), is(equalTo("Bicarbonate [Moles/volume] in Serum"))); assertThat(code.get(0).getCodeSystem(), is(equalTo("LOINC"))); - assertThat(code.get(0).getVersion(), is(equalTo("2.40"))); + assertThat(code.get(0).getFhirVersion(), is(equalTo("2.40"))); assertThat(code.get(0).getStatus(), is(equalTo(CodeStatus.ACTIVE))); } } diff --git a/src/test/java/gov/cms/madie/terminology/service/VsacServiceTest.java b/src/test/java/gov/cms/madie/terminology/service/VsacServiceTest.java index 2ed9d5d..b0148d9 100644 --- a/src/test/java/gov/cms/madie/terminology/service/VsacServiceTest.java +++ b/src/test/java/gov/cms/madie/terminology/service/VsacServiceTest.java @@ -459,7 +459,7 @@ void testGetCodeStatusIfCodeSystemMappingAbsent() { when(mappingService.getCodeSystemEntryByOid(anyString())).thenReturn(null); assertThat( vsacService.getCodeStatus( - Code.builder().codeSystemOid("oid").version("version").build(), TEST_API_KEY), + Code.builder().codeSystemOid("oid").fhirVersion("version").build(), TEST_API_KEY), is(equalTo(CodeStatus.NA))); } @@ -469,7 +469,7 @@ void testGetCodeStatusIfCodeSystemNotInSvs() { when(mappingService.getCodeSystemEntryByOid(anyString())).thenReturn(cse); assertThat( vsacService.getCodeStatus( - Code.builder().codeSystemOid("oid").version("version").build(), TEST_API_KEY), + Code.builder().codeSystemOid("oid").fhirVersion("version").build(), TEST_API_KEY), is(equalTo(CodeStatus.NA))); } @@ -510,7 +510,7 @@ void testGetCodeStatusActive() { Code.builder() .name("1222766008") .codeSystem("ABC") - .version("abc.info/20230901") + .fhirVersion("abc.info/20230901") .display("American Joint Committee on Cancer stage IIA") .codeSystemOid("1.2.3.4.96") .build(); @@ -543,7 +543,7 @@ void testGetCodeStatusInactive() { Code.builder() .name("1222766008") .codeSystem("ABC") - .version("abc.info/20230901") + .fhirVersion("abc.info/20230901") .display("American Joint Committee on Cancer stage IIA") .codeSystemOid("1.2.3.4.96") .build(); @@ -576,7 +576,7 @@ void testGetCodeStatusIfCodeNotFoundInSvs() { Code.builder() .name("1222766008") .codeSystem("ABC") - .version("abc.info/20230901") + .fhirVersion("abc.info/20230901") .display("American Joint Committee on Cancer stage IIA") .codeSystemOid("1.2.3.4.96") .build(); From da119648f84f956e7c2b8def5aeca5fb0ef0dcfe Mon Sep 17 00:00:00 2001 From: Prateek Keerthi Date: Wed, 22 May 2024 18:41:56 -0400 Subject: [PATCH 2/2] MAT-7223 and MAT-7224 updating logic to display and add svs versions when apply is cliked --- .../cms/madie/terminology/service/FhirTerminologyService.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/gov/cms/madie/terminology/service/FhirTerminologyService.java b/src/main/java/gov/cms/madie/terminology/service/FhirTerminologyService.java index 09e589f..46f4b37 100644 --- a/src/main/java/gov/cms/madie/terminology/service/FhirTerminologyService.java +++ b/src/main/java/gov/cms/madie/terminology/service/FhirTerminologyService.java @@ -234,6 +234,7 @@ public Code retrieveCode(String codeName, String codeSystemName, String version, || StringUtils.isEmpty(version)) { return null; } + CodeSystem codeSystem = codeSystemRepository.findByNameAndVersion(codeSystemName, version).orElse(null); if (codeSystem == null) {