From 1a7adc2494d32b31980d84c73db1f98189fb19c7 Mon Sep 17 00:00:00 2001 From: mcmcphillips Date: Tue, 30 Apr 2024 10:24:39 -0700 Subject: [PATCH 1/5] MAT-7038: Modify cs retrieve to return displayValues for vsac version --- .../madie/terminology/models/CodeSystem.java | 1 + .../service/FhirTerminologyService.java | 46 ++++++++++++++++++- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/main/java/gov/cms/madie/terminology/models/CodeSystem.java b/src/main/java/gov/cms/madie/terminology/models/CodeSystem.java index 58e19fb..6a7016e 100644 --- a/src/main/java/gov/cms/madie/terminology/models/CodeSystem.java +++ b/src/main/java/gov/cms/madie/terminology/models/CodeSystem.java @@ -22,6 +22,7 @@ public class CodeSystem { private String title; private String name; private String version; + private String displayVersion; // match version HL7V3.0_2019-12 against fhir private String versionId; private String oid; // identifier[0].value oid of identifier List private Instant lastUpdated; // when queried 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 689bf74..736132c 100644 --- a/src/main/java/gov/cms/madie/terminology/service/FhirTerminologyService.java +++ b/src/main/java/gov/cms/madie/terminology/service/FhirTerminologyService.java @@ -25,8 +25,10 @@ import java.time.Instant; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Optional; +import java.util.concurrent.atomic.AtomicBoolean; @Service @Slf4j @@ -122,7 +124,49 @@ private List getValueSetConcepts( } public List getAllCodeSystems() { - return codeSystemRepository.findAll(); + // remove items that are marked as not present in vsac to cut expense + List codeSystemEntries = mappingService.getCodeSystemEntries().stream().filter(codeSystemEntry -> !codeSystemEntry.getOid().contains("NOT.IN.VSAC")).toList(); + List codeSystems = codeSystemRepository.findAll(); + List transformedResults = new ArrayList<>(Collections.emptyList()); + codeSystems.forEach(codeSystem -> { + // if the oid shows up at all + int index = -1; + for (int i = 0; i < codeSystems.size(); i++) { + if (codeSystems.get(i).getOid().equals(codeSystem.getOid())) { + index = i; + break; + } + } + if(index != -1) { + CodeSystemEntry matchingEntry = null; + for (CodeSystemEntry entry : codeSystemEntries) { + if (entry.getOid().equals(codeSystem.getOid())) { + matchingEntry = entry; + break; + } + } + if (matchingEntry != null) { + AtomicBoolean usableVersionFound = new AtomicBoolean(false); + matchingEntry.getVersions().forEach(version -> { + // we use fhir csv to interact with api. goal here is to look for fhir version, then give users a display version + // that looks like vsac because that's what they understand. + if (version.getFhir().equals(codeSystem.getVersion()) && version.getVsac() != null) { + codeSystem.setDisplayVersion(version.getVsac()); + transformedResults.add(codeSystem); + usableVersionFound.set(true); + } + }); + if (usableVersionFound.get()){ + log.info("CodeSystem title {} , version: {} was not found in mapping document", codeSystem.getTitle(), codeSystem.getVersion()); + } + } + } + else { + // it was not found, we log that it's not located within vsac. + log.info("CodeSystem title {} , version: {} was not found in mapping document", codeSystem.getTitle(), codeSystem.getName()); + } + }); + return transformedResults; } public List retrieveAllCodeSystems(UmlsUser umlsUser) { From 4c8b4a4047b33fe922450a7e0179d759f4fda133 Mon Sep 17 00:00:00 2001 From: mcmcphillips Date: Thu, 9 May 2024 09:57:46 -0700 Subject: [PATCH 2/5] MAT-7038: fix test --- .../service/FhirTerminologyServiceTest.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) 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 eb8224c..0f94767 100644 --- a/src/test/java/gov/cms/madie/terminology/service/FhirTerminologyServiceTest.java +++ b/src/test/java/gov/cms/madie/terminology/service/FhirTerminologyServiceTest.java @@ -35,6 +35,7 @@ import java.io.File; import java.io.IOException; +import java.lang.reflect.Array; import java.nio.charset.Charset; import java.time.Instant; import java.util.*; @@ -334,9 +335,20 @@ void testRetrieveAllCodeSystemsWithInsert() { void testGetAllCodeSystems() { var c1 = new gov.cms.madie.terminology.models.CodeSystem(); c1.setTitle("t1"); + c1.setOid("fakeoid1"); + c1.setVersion("1.0"); var c2 = new gov.cms.madie.terminology.models.CodeSystem(); c2.setTitle("t2"); + c2.setOid("fakeoid2"); + c2.setVersion("2.0"); + CodeSystemEntry.Version cv1 = new CodeSystemEntry.Version().toBuilder().fhir("1.0").vsac("exists").build(); + CodeSystemEntry.Version cv2 = new CodeSystemEntry.Version().toBuilder().fhir("2.0").vsac("exists").build(); + var ce1 = new CodeSystemEntry().toBuilder().versions(java.util.Collections.singletonList(cv1)).oid("fakeoid1").build(); + var ce2 = new CodeSystemEntry().toBuilder().versions(java.util.Collections.singletonList(cv2)).oid("fakeoid2").build(); + + List codeSystemEntries = Arrays.asList(ce1, ce2); List codeSystems = Arrays.asList(c1, c2); + when(mappingService.getCodeSystemEntries()).thenAnswer(invocation -> codeSystemEntries); when(codeSystemRepository.findAll()).thenAnswer(invocation -> codeSystems); List result = fhirTerminologyService.getAllCodeSystems(); From 5cf0b1cf2292ef87673f6157d52cffb596358c88 Mon Sep 17 00:00:00 2001 From: Joseph Kotanchik Date: Thu, 9 May 2024 15:34:46 -0400 Subject: [PATCH 3/5] MAT-7038: Rename property to indicate its usage with QDM measures. --- src/main/java/gov/cms/madie/terminology/models/CodeSystem.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/gov/cms/madie/terminology/models/CodeSystem.java b/src/main/java/gov/cms/madie/terminology/models/CodeSystem.java index 6a7016e..afa023f 100644 --- a/src/main/java/gov/cms/madie/terminology/models/CodeSystem.java +++ b/src/main/java/gov/cms/madie/terminology/models/CodeSystem.java @@ -22,7 +22,7 @@ public class CodeSystem { private String title; private String name; private String version; - private String displayVersion; // match version HL7V3.0_2019-12 against fhir + private String qdmDisplayVersion; // match version HL7V3.0_2019-12 against fhir private String versionId; private String oid; // identifier[0].value oid of identifier List private Instant lastUpdated; // when queried From 9231056fa4a5abf693ab447f7967409928a6f7fc Mon Sep 17 00:00:00 2001 From: Joseph Kotanchik Date: Thu, 9 May 2024 15:38:40 -0400 Subject: [PATCH 4/5] MAT-7038: Rework to ensure FHIR only Code Systems are not dropped during processing. Replace index based search with lambda findFirst. Simplify log conditional, and set logs at debug level. --- .../service/FhirTerminologyService.java | 79 +++++++++---------- .../service/FhirTerminologyServiceTest.java | 39 ++++++--- 2 files changed, 64 insertions(+), 54 deletions(-) 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 736132c..362f88c 100644 --- a/src/main/java/gov/cms/madie/terminology/service/FhirTerminologyService.java +++ b/src/main/java/gov/cms/madie/terminology/service/FhirTerminologyService.java @@ -25,10 +25,8 @@ import java.time.Instant; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Optional; -import java.util.concurrent.atomic.AtomicBoolean; @Service @Slf4j @@ -125,48 +123,45 @@ private List getValueSetConcepts( public List getAllCodeSystems() { // remove items that are marked as not present in vsac to cut expense - List codeSystemEntries = mappingService.getCodeSystemEntries().stream().filter(codeSystemEntry -> !codeSystemEntry.getOid().contains("NOT.IN.VSAC")).toList(); + List codeSystemMappingEntries = + mappingService.getCodeSystemEntries().stream() + .filter(codeSystemEntry -> !codeSystemEntry.getOid().contains("NOT.IN.VSAC")) + .toList(); List codeSystems = codeSystemRepository.findAll(); - List transformedResults = new ArrayList<>(Collections.emptyList()); - codeSystems.forEach(codeSystem -> { - // if the oid shows up at all - int index = -1; - for (int i = 0; i < codeSystems.size(); i++) { - if (codeSystems.get(i).getOid().equals(codeSystem.getOid())) { - index = i; - break; - } - } - if(index != -1) { - CodeSystemEntry matchingEntry = null; - for (CodeSystemEntry entry : codeSystemEntries) { - if (entry.getOid().equals(codeSystem.getOid())) { - matchingEntry = entry; - break; - } - } - if (matchingEntry != null) { - AtomicBoolean usableVersionFound = new AtomicBoolean(false); - matchingEntry.getVersions().forEach(version -> { - // we use fhir csv to interact with api. goal here is to look for fhir version, then give users a display version - // that looks like vsac because that's what they understand. - if (version.getFhir().equals(codeSystem.getVersion()) && version.getVsac() != null) { - codeSystem.setDisplayVersion(version.getVsac()); - transformedResults.add(codeSystem); - usableVersionFound.set(true); - } - }); - if (usableVersionFound.get()){ - log.info("CodeSystem title {} , version: {} was not found in mapping document", codeSystem.getTitle(), codeSystem.getVersion()); + codeSystems.forEach( + codeSystem -> { + Optional matchingEntry = + codeSystemMappingEntries.stream() + .filter(entry -> entry.getOid().equals(codeSystem.getOid())) + .findFirst(); + if (matchingEntry.isPresent()) { + matchingEntry + .get() + .getVersions() + .forEach( + version -> { + // We use fhir url to interact with VSAC FHIR Term Service. + // Goal here is to look for fhir version, then give users + // viewing QDM measures a display version that looks like + // svs vsac because that's what they expect. + if (version.getFhir().equals(codeSystem.getVersion()) + && version.getVsac() != null) { + codeSystem.setQdmDisplayVersion(version.getVsac()); + log.debug( + "CodeSystem title {} , version: {} was found in mapping document", + codeSystem.getTitle(), + codeSystem.getVersion()); + } + }); + } else { + // it was not found, we log that it's not located within vsac. + log.debug( + "CodeSystem title {} , version: {} was NOT found in mapping document", + codeSystem.getTitle(), + codeSystem.getName()); } - } - } - else { - // it was not found, we log that it's not located within vsac. - log.info("CodeSystem title {} , version: {} was not found in mapping document", codeSystem.getTitle(), codeSystem.getName()); - } - }); - return transformedResults; + }); + return codeSystems; } public List retrieveAllCodeSystems(UmlsUser umlsUser) { 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 0f94767..727071e 100644 --- a/src/test/java/gov/cms/madie/terminology/service/FhirTerminologyServiceTest.java +++ b/src/test/java/gov/cms/madie/terminology/service/FhirTerminologyServiceTest.java @@ -1,7 +1,6 @@ package gov.cms.madie.terminology.service; import ca.uhn.fhir.context.FhirContext; -import com.okta.commons.lang.Collections; import gov.cms.madie.models.mapping.CodeSystemEntry; import gov.cms.madie.models.measure.ManifestExpansion; import gov.cms.madie.terminology.dto.Code; @@ -27,6 +26,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.times; @@ -35,12 +35,10 @@ import java.io.File; import java.io.IOException; -import java.lang.reflect.Array; import java.nio.charset.Charset; import java.time.Instant; import java.util.*; -import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.when; @@ -144,7 +142,7 @@ public void setUp() throws IOException { .name("Icd10CM") .oid("urn:oid:2.16.840.1.113883.6.90") .url("http://hl7.org/fhir/sid/icd-10-cm") - .versions(Collections.toList(version)) + .versions(List.of(version)) .build(); codeSystemEntries.add(codeSystemEntry); } @@ -341,22 +339,39 @@ void testGetAllCodeSystems() { c2.setTitle("t2"); c2.setOid("fakeoid2"); c2.setVersion("2.0"); - CodeSystemEntry.Version cv1 = new CodeSystemEntry.Version().toBuilder().fhir("1.0").vsac("exists").build(); - CodeSystemEntry.Version cv2 = new CodeSystemEntry.Version().toBuilder().fhir("2.0").vsac("exists").build(); - var ce1 = new CodeSystemEntry().toBuilder().versions(java.util.Collections.singletonList(cv1)).oid("fakeoid1").build(); - var ce2 = new CodeSystemEntry().toBuilder().versions(java.util.Collections.singletonList(cv2)).oid("fakeoid2").build(); - - List codeSystemEntries = Arrays.asList(ce1, ce2); - List codeSystems = Arrays.asList(c1, c2); + var c3 = new gov.cms.madie.terminology.models.CodeSystem(); + c3.setTitle("t3"); + c3.setOid("fakeoid3"); + c3.setVersion("2024"); + + CodeSystemEntry.Version cv1 = + new CodeSystemEntry.Version().toBuilder().fhir("1.0").vsac("1").build(); + CodeSystemEntry.Version cv2 = + new CodeSystemEntry.Version().toBuilder().fhir("2.0").vsac("2").build(); + CodeSystemEntry.Version cv3 = new CodeSystemEntry.Version().toBuilder().fhir("latest").build(); + var ce1 = new CodeSystemEntry().toBuilder().versions(List.of(cv1)).oid("fakeoid1").build(); + var ce2 = new CodeSystemEntry().toBuilder().versions(List.of(cv2)).oid("fakeoid2").build(); + var ce3 = new CodeSystemEntry().toBuilder().versions(List.of(cv3)).oid("NOT.IN.VSAC").build(); + + List codeSystemEntries = Arrays.asList(ce1, ce2, ce3); + List codeSystems = Arrays.asList(c1, c2, c3); when(mappingService.getCodeSystemEntries()).thenAnswer(invocation -> codeSystemEntries); when(codeSystemRepository.findAll()).thenAnswer(invocation -> codeSystems); List result = fhirTerminologyService.getAllCodeSystems(); verify(codeSystemRepository).findAll(); - assertEquals(2, result.size()); + assertEquals(3, result.size()); assertEquals("t1", result.get(0).getTitle()); + assertEquals("1", result.get(0).getQdmDisplayVersion()); + assertEquals("t2", result.get(1).getTitle()); + assertEquals("2", result.get(1).getQdmDisplayVersion()); + + // Verify FHIR only Code Systems appear in the result set + assertEquals("t3", result.get(2).getTitle()); + assertEquals("2024", result.get(2).getVersion()); + assertNull(result.get(2).getQdmDisplayVersion()); } @Test From 9b3b20534497bcf2390b4fff32296880f1192801 Mon Sep 17 00:00:00 2001 From: Joseph Kotanchik Date: Thu, 9 May 2024 15:38:51 -0400 Subject: [PATCH 5/5] MAT-7038: formatter --- .../gov/cms/madie/terminology/task/UpdateCodeSystemTaskTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/java/gov/cms/madie/terminology/task/UpdateCodeSystemTaskTest.java b/src/test/java/gov/cms/madie/terminology/task/UpdateCodeSystemTaskTest.java index e1ef2ae..5ab28dc 100644 --- a/src/test/java/gov/cms/madie/terminology/task/UpdateCodeSystemTaskTest.java +++ b/src/test/java/gov/cms/madie/terminology/task/UpdateCodeSystemTaskTest.java @@ -17,6 +17,7 @@ public class UpdateCodeSystemTaskTest { @Mock private FhirTerminologyService fhirTerminologyService; @InjectMocks UpdateCodeSystemTask updateCodeSystemTask; + @Test void updateCodeSystemTaskTest() { UmlsUser umlsUser = new UmlsUser();