From a04145517cf4c105e9e5c351753e60fdc2003d96 Mon Sep 17 00:00:00 2001 From: Rohit Kandimalla Date: Wed, 12 Apr 2023 12:15:02 -0400 Subject: [PATCH 01/10] Removing unused dependency of madie-server-commons --- pom.xml | 5 ----- .../resources/ValidationController.java | 17 +++++++++++++---- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index c1f3a303..0504dc11 100644 --- a/pom.xml +++ b/pom.xml @@ -112,11 +112,6 @@ madie-rest-commons 0.0.2-SNAPSHOT - - gov.cms.madie - madie-server-commons - 0.0.1 - com.okta.spring okta-spring-boot-starter diff --git a/src/main/java/gov/cms/madie/madiefhirservice/resources/ValidationController.java b/src/main/java/gov/cms/madie/madiefhirservice/resources/ValidationController.java index f0ae84ea..5f2f791d 100644 --- a/src/main/java/gov/cms/madie/madiefhirservice/resources/ValidationController.java +++ b/src/main/java/gov/cms/madie/madiefhirservice/resources/ValidationController.java @@ -44,7 +44,10 @@ public class ValidationController { produces = MediaType.APPLICATION_JSON_VALUE) public HapiOperationOutcome validateBundle(HttpEntity request) { IParser parser = - fhirContext.newJsonParser().setParserErrorHandler(new StrictErrorHandler()).setPrettyPrint(true); + fhirContext + .newJsonParser() + .setParserErrorHandler(new StrictErrorHandler()) + .setPrettyPrint(true); Bundle bundle; @@ -70,11 +73,17 @@ public HapiOperationOutcome validateBundle(HttpEntity request) { ValidationResult result = validator.validateWithResult(bundle); try { - final OperationOutcome combinedOutcome = validationService.combineOutcomes(requiredProfilesOutcome, uniqueIdsOutcome, (OperationOutcome)result.toOperationOutcome()); + final OperationOutcome combinedOutcome = + validationService.combineOutcomes( + requiredProfilesOutcome, + uniqueIdsOutcome, + (OperationOutcome) result.toOperationOutcome()); String outcomeString = parser.encodeResourceToString(combinedOutcome); return HapiOperationOutcome.builder() - .code(requiredProfilesOutcome.hasIssue() || uniqueIdsOutcome.hasIssue() ? - HttpStatus.BAD_REQUEST.value() : HttpStatus.OK.value()) + .code( + requiredProfilesOutcome.hasIssue() || uniqueIdsOutcome.hasIssue() + ? HttpStatus.BAD_REQUEST.value() + : HttpStatus.OK.value()) .successful(validationService.isSuccessful(combinedOutcome)) .outcomeResponse(mapper.readValue(outcomeString, Object.class)) .build(); From b32cd9fc5fa21d638149eff8aa488246409e487b Mon Sep 17 00:00:00 2001 From: Rohit Kandimalla Date: Thu, 13 Apr 2023 11:54:23 -0400 Subject: [PATCH 02/10] Using experimental field from madie measure to generate measure bundle --- .../madiefhirservice/services/MeasureTranslatorService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/gov/cms/madie/madiefhirservice/services/MeasureTranslatorService.java b/src/main/java/gov/cms/madie/madiefhirservice/services/MeasureTranslatorService.java index f1414ac6..d22bbfb6 100644 --- a/src/main/java/gov/cms/madie/madiefhirservice/services/MeasureTranslatorService.java +++ b/src/main/java/gov/cms/madie/madiefhirservice/services/MeasureTranslatorService.java @@ -63,7 +63,7 @@ public org.hl7.fhir.r4.model.Measure createFhirMeasureForMadieMeasure(Measure ma .setName(madieMeasure.getCqlLibraryName()) .setTitle(madieMeasure.getMeasureName()) .setIdentifier(buildMeasureIdentifiers(madieMeasure)) - .setExperimental(true) + .setExperimental(madieMeasure.getMeasureMetaData().isExperimental()) .setUrl(fhirBaseUrl + "/Measure/" + madieMeasure.getCqlLibraryName()) .setVersion(madieMeasure.getVersion().toString()) .setEffectivePeriod( From 976fac9d78f07b5efd9af7ce1e4b6b12a26567ea Mon Sep 17 00:00:00 2001 From: Rohit Kandimalla Date: Thu, 13 Apr 2023 12:09:57 -0400 Subject: [PATCH 03/10] Added test cases --- .../madiefhirservice/services/MeasureTranslatorServiceTest.java | 1 + .../gov/cms/madie/madiefhirservice/utils/MeasureTestHelper.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/gov/cms/madie/madiefhirservice/services/MeasureTranslatorServiceTest.java b/src/test/java/gov/cms/madie/madiefhirservice/services/MeasureTranslatorServiceTest.java index 1db67d83..25ec8b28 100644 --- a/src/test/java/gov/cms/madie/madiefhirservice/services/MeasureTranslatorServiceTest.java +++ b/src/test/java/gov/cms/madie/madiefhirservice/services/MeasureTranslatorServiceTest.java @@ -260,6 +260,7 @@ public void testCreateFhirMeasureForMadieRatioMeasure() { measureTranslatorService.createFhirMeasureForMadieMeasure(madieRatioMeasure); assertThat(measure.getName(), is(equalTo(madieMeasure.getCqlLibraryName()))); + assertFalse(measure.getExperimental()); assertThat(measure.getGuidance(), is(equalTo(madieMeasure.getMeasureMetaData().getSteward()))); assertThat( measure.getRationale(), is(equalTo(madieMeasure.getMeasureMetaData().getRationale()))); diff --git a/src/test/java/gov/cms/madie/madiefhirservice/utils/MeasureTestHelper.java b/src/test/java/gov/cms/madie/madiefhirservice/utils/MeasureTestHelper.java index fa2cf2f4..799f0214 100644 --- a/src/test/java/gov/cms/madie/madiefhirservice/utils/MeasureTestHelper.java +++ b/src/test/java/gov/cms/madie/madiefhirservice/utils/MeasureTestHelper.java @@ -31,7 +31,7 @@ public static Bundle createTestMeasureBundle() { measure .setName("TestCMS0001") .setTitle("TestTitle001") - .setExperimental(true) + .setExperimental(false) .setUrl("/Measure/TestCMS0001") .setPublisher("CMS") .setCopyright("CMS copyright") From 811d6354b7a98dfc62effb407dfb55a8474dc4a5 Mon Sep 17 00:00:00 2001 From: CeciliaLiu8 Date: Fri, 14 Apr 2023 07:03:18 -0500 Subject: [PATCH 04/10] MAT-5470 bundle without NQF --- .../services/MeasureTranslatorService.java | 8 ++++-- .../MeasureTranslatorServiceTest.java | 27 +++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/main/java/gov/cms/madie/madiefhirservice/services/MeasureTranslatorService.java b/src/main/java/gov/cms/madie/madiefhirservice/services/MeasureTranslatorService.java index f1414ac6..ded9bddd 100644 --- a/src/main/java/gov/cms/madie/madiefhirservice/services/MeasureTranslatorService.java +++ b/src/main/java/gov/cms/madie/madiefhirservice/services/MeasureTranslatorService.java @@ -127,7 +127,9 @@ public List buildMeasureIdentifiers(Measure madieMeasure) { ValueConstants.CODE_VERSION_SPECIFIC)); if (madieMeasure.getMeasureMetaData() != null && madieMeasure.getMeasureMetaData().getEndorsements() != null - && !madieMeasure.getMeasureMetaData().getEndorsements().isEmpty()) { + && !madieMeasure.getMeasureMetaData().getEndorsements().isEmpty() + && StringUtils.isNotBlank( + madieMeasure.getMeasureMetaData().getEndorsements().get(0).getEndorser())) { Endorsement endorsement = madieMeasure.getMeasureMetaData().getEndorsements().get(0); identifiers.add( buildIdentifier( @@ -135,7 +137,9 @@ public List buildMeasureIdentifiers(Measure madieMeasure) { UriConstants.MadieMeasure.NQF_ID, endorsement.getEndorsementId(), ValueConstants.CODE_ENDORSER) - .setAssigner(buildDisplayReference("NQF"))); + .setAssigner( + buildDisplayReference( + madieMeasure.getMeasureMetaData().getEndorsements().get(0).getEndorser()))); } if (StringUtils.isNotBlank(madieMeasure.getCmsId())) { identifiers.add( diff --git a/src/test/java/gov/cms/madie/madiefhirservice/services/MeasureTranslatorServiceTest.java b/src/test/java/gov/cms/madie/madiefhirservice/services/MeasureTranslatorServiceTest.java index 1db67d83..5d510135 100644 --- a/src/test/java/gov/cms/madie/madiefhirservice/services/MeasureTranslatorServiceTest.java +++ b/src/test/java/gov/cms/madie/madiefhirservice/services/MeasureTranslatorServiceTest.java @@ -821,6 +821,33 @@ public void testBuildMeasureIdentifiersReturnsIdentifiersWithoutCmsIdWithNqfForM assertThat(output.get(3).getValue(), is(equalTo("NQF1234"))); } + @Test + public void testBuildMeasureIdentifiersReturnsIdentifiersWithoutNqfForMeasure() { + final Measure madieMeasure = + Measure.builder() + .id("MEASURE_ID_1") + .measureSetId("MEASURE_SET_ID_99") + .ecqmTitle("ECQM_TITLE") + .measureMetaData( + MeasureMetaData.builder() + .endorsements( + List.of(Endorsement.builder().endorsementId("").endorser("").build())) + .build()) + .build(); + List output = measureTranslatorService.buildMeasureIdentifiers(madieMeasure); + assertThat(output, is(notNullValue())); + // Short Name + assertThat(output.size(), is(equalTo(3))); + assertThat(output.get(0), is(notNullValue())); + assertThat(output.get(0).getSystem(), is(equalTo(SHORT_NAME))); + // Measure Set ID + assertThat(output.get(1), is(notNullValue())); + assertThat(output.get(1).getValue(), is(equalTo(URN_UUID_PREFIX + "MEASURE_SET_ID_99"))); + // Measure ID + assertThat(output.get(2), is(notNullValue())); + assertThat(output.get(2).getValue(), is(equalTo(URN_UUID_PREFIX + "MEASURE_ID_1"))); + } + @Test public void testBuildGroupsWithNull() { List listOfComponent = From ee825dbaff81de0686fc121a6f0450fa35c08808 Mon Sep 17 00:00:00 2001 From: CeciliaLiu8 Date: Fri, 14 Apr 2023 09:17:57 -0500 Subject: [PATCH 05/10] MAT-5085 resource id required --- .../resources/ValidationController.java | 7 ++- .../services/ResourceValidationService.java | 22 +++++++-- .../ValidationControllerMvcTest.java | 14 +++--- .../resources/ValidationControllerTest.java | 46 +++++++++++++++++-- .../ResourceValidationServiceTest.java | 27 +++++++++-- 5 files changed, 93 insertions(+), 23 deletions(-) diff --git a/src/main/java/gov/cms/madie/madiefhirservice/resources/ValidationController.java b/src/main/java/gov/cms/madie/madiefhirservice/resources/ValidationController.java index 5f2f791d..d7ec7a81 100644 --- a/src/main/java/gov/cms/madie/madiefhirservice/resources/ValidationController.java +++ b/src/main/java/gov/cms/madie/madiefhirservice/resources/ValidationController.java @@ -68,20 +68,19 @@ public HapiOperationOutcome validateBundle(HttpEntity request) { OperationOutcome requiredProfilesOutcome = validationService.validateBundleResourcesProfiles(bundle); - OperationOutcome uniqueIdsOutcome = - validationService.validateBundleResourcesIdUniqueness(bundle); + OperationOutcome validIdsOutcome = validationService.validateBundleResourcesIdValid(bundle); ValidationResult result = validator.validateWithResult(bundle); try { final OperationOutcome combinedOutcome = validationService.combineOutcomes( requiredProfilesOutcome, - uniqueIdsOutcome, + validIdsOutcome, (OperationOutcome) result.toOperationOutcome()); String outcomeString = parser.encodeResourceToString(combinedOutcome); return HapiOperationOutcome.builder() .code( - requiredProfilesOutcome.hasIssue() || uniqueIdsOutcome.hasIssue() + requiredProfilesOutcome.hasIssue() || validIdsOutcome.hasIssue() ? HttpStatus.BAD_REQUEST.value() : HttpStatus.OK.value()) .successful(validationService.isSuccessful(combinedOutcome)) diff --git a/src/main/java/gov/cms/madie/madiefhirservice/services/ResourceValidationService.java b/src/main/java/gov/cms/madie/madiefhirservice/services/ResourceValidationService.java index f771bf9a..f806fd10 100644 --- a/src/main/java/gov/cms/madie/madiefhirservice/services/ResourceValidationService.java +++ b/src/main/java/gov/cms/madie/madiefhirservice/services/ResourceValidationService.java @@ -5,6 +5,8 @@ import ca.uhn.fhir.util.OperationOutcomeUtil; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; + +import org.apache.commons.lang3.StringUtils; import org.hl7.fhir.instance.model.api.IBaseBundle; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.r4.model.OperationOutcome; @@ -59,24 +61,34 @@ public OperationOutcome validateBundleResourcesProfiles(IBaseBundle bundleResour return operationOutcome; } - public OperationOutcome validateBundleResourcesIdUniqueness(IBaseBundle bundleResource) { + public OperationOutcome validateBundleResourcesIdValid(IBaseBundle bundleResource) { List resources = BundleUtil.toListOfResources(fhirContext, bundleResource); Set existingIds = new HashSet<>(); Set duplicateIds = new HashSet<>(); OperationOutcome operationOutcome = new OperationOutcome(); for (IBaseResource resource : resources) { final String resourceId = resource.getIdElement().getIdPart(); - if (existingIds.contains(resourceId) && !duplicateIds.contains(resourceId)) { + if (StringUtils.isBlank(resourceId)) { OperationOutcomeUtil.addIssue( fhirContext, operationOutcome, OperationOutcome.IssueSeverity.ERROR.toCode(), - formatUniqueIdViolationMessage(resourceId), + "All resources must have an Id", null, OperationOutcome.IssueType.INVALID.toCode()); - duplicateIds.add(resourceId); } else { - existingIds.add(resourceId); + if (existingIds.contains(resourceId) && !duplicateIds.contains(resourceId)) { + OperationOutcomeUtil.addIssue( + fhirContext, + operationOutcome, + OperationOutcome.IssueSeverity.ERROR.toCode(), + formatUniqueIdViolationMessage(resourceId), + null, + OperationOutcome.IssueType.INVALID.toCode()); + duplicateIds.add(resourceId); + } else { + existingIds.add(resourceId); + } } } return operationOutcome; diff --git a/src/test/java/gov/cms/madie/madiefhirservice/resources/ValidationControllerMvcTest.java b/src/test/java/gov/cms/madie/madiefhirservice/resources/ValidationControllerMvcTest.java index 3959d1ff..ac6f99d9 100644 --- a/src/test/java/gov/cms/madie/madiefhirservice/resources/ValidationControllerMvcTest.java +++ b/src/test/java/gov/cms/madie/madiefhirservice/resources/ValidationControllerMvcTest.java @@ -78,7 +78,7 @@ void testUnsuccessfulOutcomeReturnedForInvalidEncounter() throws Exception { String tc1Json = getStringFromTestResource("/testCaseBundles/testCaseInvalidEncounter.json"); when(validationService.validateBundleResourcesProfiles(any(IBaseBundle.class))) .thenReturn(new OperationOutcome()); - when(validationService.validateBundleResourcesIdUniqueness(any(IBaseBundle.class))) + when(validationService.validateBundleResourcesIdValid(any(IBaseBundle.class))) .thenReturn(new OperationOutcome()); when(validationService.combineOutcomes(any())).thenReturn(new OperationOutcome()); @@ -103,7 +103,7 @@ void testUnsuccessfulOutcomeReturnedForMissingProfile() throws Exception { operationOutcomeWithIssues.addIssue().setSeverity(OperationOutcome.IssueSeverity.WARNING); when(validationService.validateBundleResourcesProfiles(any(IBaseBundle.class))) .thenReturn(operationOutcomeWithIssues); - when(validationService.validateBundleResourcesIdUniqueness(any(IBaseBundle.class))) + when(validationService.validateBundleResourcesIdValid(any(IBaseBundle.class))) .thenReturn(new OperationOutcome()); when(validationService.combineOutcomes(any())).thenReturn(operationOutcomeWithIssues); when(validationService.isSuccessful(any(OperationOutcome.class))).thenReturn(true); @@ -127,7 +127,7 @@ void testSuccessfulOutcomeReturnedForValidTestCaseJson() throws Exception { String tc1Json = getStringFromTestResource("/testCaseBundles/validTestCase.json"); when(validationService.validateBundleResourcesProfiles(any(IBaseBundle.class))) .thenReturn(new OperationOutcome()); - when(validationService.validateBundleResourcesIdUniqueness(any(IBaseBundle.class))) + when(validationService.validateBundleResourcesIdValid(any(IBaseBundle.class))) .thenReturn(new OperationOutcome()); when(validationService.combineOutcomes(any())).thenReturn(new OperationOutcome()); when(validationService.isSuccessful(any(OperationOutcome.class))).thenReturn(true); @@ -153,10 +153,10 @@ void testUnsuccessfulOutcomeReturnedForMissingProfileValidTestCaseJson() throws profileWarningOutcome.addIssue().setSeverity(OperationOutcome.IssueSeverity.WARNING); when(validationService.validateBundleResourcesProfiles(any(IBaseBundle.class))) .thenReturn(profileWarningOutcome); - OperationOutcome uniqueIdErrorOutcome = new OperationOutcome(); - uniqueIdErrorOutcome.addIssue().setSeverity(OperationOutcome.IssueSeverity.ERROR); - when(validationService.validateBundleResourcesIdUniqueness(any(IBaseBundle.class))) - .thenReturn(uniqueIdErrorOutcome); + OperationOutcome invalidIdErrorOutcome = new OperationOutcome(); + invalidIdErrorOutcome.addIssue().setSeverity(OperationOutcome.IssueSeverity.ERROR); + when(validationService.validateBundleResourcesIdValid(any(IBaseBundle.class))) + .thenReturn(invalidIdErrorOutcome); OperationOutcome combinedOutcome = new OperationOutcome(); combinedOutcome.addIssue().setSeverity(OperationOutcome.IssueSeverity.ERROR); combinedOutcome.addIssue().setSeverity(OperationOutcome.IssueSeverity.WARNING); diff --git a/src/test/java/gov/cms/madie/madiefhirservice/resources/ValidationControllerTest.java b/src/test/java/gov/cms/madie/madiefhirservice/resources/ValidationControllerTest.java index 5b885b3e..08854f0c 100644 --- a/src/test/java/gov/cms/madie/madiefhirservice/resources/ValidationControllerTest.java +++ b/src/test/java/gov/cms/madie/madiefhirservice/resources/ValidationControllerTest.java @@ -159,7 +159,7 @@ void testValidationControllerReturnsExceptionForErrorProcessingOutput() when(validationService.validateBundleResourcesProfiles(any(IBaseBundle.class))) .thenReturn(new OperationOutcome()); - when(validationService.validateBundleResourcesIdUniqueness(any(IBaseBundle.class))) + when(validationService.validateBundleResourcesIdValid(any(IBaseBundle.class))) .thenReturn(new OperationOutcome()); OperationOutcome outcome = new OperationOutcome(); outcome.addIssue().setSeverity(OperationOutcome.IssueSeverity.ERROR); @@ -184,7 +184,7 @@ void testValidationControllerReturnsOutcomeWithIssues() throws JsonProcessingExc when(validationService.validateBundleResourcesProfiles(any(IBaseBundle.class))) .thenReturn(new OperationOutcome()); - when(validationService.validateBundleResourcesIdUniqueness(any(IBaseBundle.class))) + when(validationService.validateBundleResourcesIdValid(any(IBaseBundle.class))) .thenReturn(new OperationOutcome()); when(parser.encodeResourceToString(any(OperationOutcome.class))) @@ -228,7 +228,45 @@ void testValidationControllerReturnsOutcomeWithUniqueIdIssues() throws JsonProce .setDiagnostics( "All resources in bundle must have unique ID regardless of type. Multiple resources detected with ID 1234") .setSeverity(OperationOutcome.IssueSeverity.ERROR); - when(validationService.validateBundleResourcesIdUniqueness(any(IBaseBundle.class))) + when(validationService.validateBundleResourcesIdValid(any(IBaseBundle.class))) + .thenReturn(errorOutcome); + when(parser.encodeResourceToString(any(OperationOutcome.class))) + .thenReturn("{ \"resourceType\": \"OperationOutcome\" }"); + + ValidationResult result = Mockito.mock(ValidationResult.class); + when(result.toOperationOutcome()).thenReturn(new OperationOutcome()); + when(fhirValidator.validateWithResult(any(IBaseResource.class))).thenReturn(result); + + when(validationService.combineOutcomes(any())).thenReturn(errorOutcome); + when(validationService.isSuccessful(any(OperationOutcome.class))).thenReturn(false); + + HapiOperationOutcome output = validationController.validateBundle(entity); + assertThat(output, is(notNullValue())); + assertThat(output.getCode(), is(equalTo(HttpStatus.BAD_REQUEST.value()))); + assertThat(output.getOutcomeResponse() instanceof Map, is(true)); + Map outcomeResponse = (Map) output.getOutcomeResponse(); + Object resourceType = outcomeResponse.get("resourceType"); + assertThat(resourceType, is(equalTo("OperationOutcome"))); + } + + @Test + void testValidationControllerReturnsOutcomeWithInvalidIdIssues() throws JsonProcessingException { + String tc1Json = getStringFromTestResource("/testCaseBundles/testCaseInvalidEncounter.json"); + when(parser.parseResource(any(Class.class), anyString())).thenReturn(new Bundle()); + when(entity.getBody()).thenReturn(tc1Json); + + Map mockOutcome = new HashMap<>(); + mockOutcome.put("resourceType", "OperationOutcome"); + when(mapper.readValue(anyString(), any(Class.class))).thenReturn(mockOutcome); + + when(validationService.validateBundleResourcesProfiles(any(IBaseBundle.class))) + .thenReturn(new OperationOutcome()); + OperationOutcome errorOutcome = new OperationOutcome(); + errorOutcome + .addIssue() + .setDiagnostics("All resources must have an Id") + .setSeverity(OperationOutcome.IssueSeverity.ERROR); + when(validationService.validateBundleResourcesIdValid(any(IBaseBundle.class))) .thenReturn(errorOutcome); when(parser.encodeResourceToString(any(OperationOutcome.class))) .thenReturn("{ \"resourceType\": \"OperationOutcome\" }"); @@ -258,7 +296,7 @@ void testValidationControllerReturnsSuccessfulOutcome() { when(validationService.validateBundleResourcesProfiles(any(IBaseBundle.class))) .thenReturn(new OperationOutcome()); - when(validationService.validateBundleResourcesIdUniqueness(any(IBaseBundle.class))) + when(validationService.validateBundleResourcesIdValid(any(IBaseBundle.class))) .thenReturn(new OperationOutcome()); when(validationService.combineOutcomes(any())).thenReturn(new OperationOutcome()); when(validationService.isSuccessful(any(OperationOutcome.class))).thenReturn(true); diff --git a/src/test/java/gov/cms/madie/madiefhirservice/services/ResourceValidationServiceTest.java b/src/test/java/gov/cms/madie/madiefhirservice/services/ResourceValidationServiceTest.java index 972291a6..fe934005 100644 --- a/src/test/java/gov/cms/madie/madiefhirservice/services/ResourceValidationServiceTest.java +++ b/src/test/java/gov/cms/madie/madiefhirservice/services/ResourceValidationServiceTest.java @@ -25,6 +25,7 @@ import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; @@ -135,7 +136,7 @@ void testValidateBundleResourcesIdUniquenessCatchesDuplicateIds() { .thenReturn(List.of(p, e1, e2)); Bundle bundle = new Bundle(); - OperationOutcome output = validationService.validateBundleResourcesIdUniqueness(bundle); + OperationOutcome output = validationService.validateBundleResourcesIdValid(bundle); assertThat(output, is(notNullValue())); assertThat(output.hasIssue(), is(true)); assertThat(output.getIssueFirstRep().getDiagnostics().contains("1234"), is(true)); @@ -158,7 +159,7 @@ void testValidateBundleResourcesIdUniquenessLooksAcrossResourceTypes() { .thenReturn(List.of(p, e1, p1, e2)); Bundle bundle = new Bundle(); - OperationOutcome output = validationService.validateBundleResourcesIdUniqueness(bundle); + OperationOutcome output = validationService.validateBundleResourcesIdValid(bundle); assertThat(output, is(notNullValue())); assertThat(output.hasIssue(), is(true)); assertThat(output.getIssueFirstRep().getDiagnostics().contains("1234"), is(true)); @@ -180,9 +181,29 @@ void testValidateBundleResourcesIdUniquenessReturnsNoErrorsForAllUniqueIds() { .thenReturn(List.of(p, e1, e2)); Bundle bundle = new Bundle(); - OperationOutcome output = validationService.validateBundleResourcesIdUniqueness(bundle); + OperationOutcome output = validationService.validateBundleResourcesIdValid(bundle); assertThat(output, is(notNullValue())); assertThat(output.hasIssue(), is(false)); } } + + @Test + void testValidateBundleResourcesIdValidReturnsErrorForNoId() { + Patient p = new Patient(); + Encounter e1 = new Encounter(); + e1.setId("2222"); + Encounter e2 = new Encounter(); + e2.setId("3333"); + try (MockedStatic utilities = Mockito.mockStatic(BundleUtil.class)) { + utilities + .when(() -> BundleUtil.toListOfResources(any(FhirContext.class), any(IBaseBundle.class))) + .thenReturn(List.of(p, e1, e2)); + + Bundle bundle = new Bundle(); + OperationOutcome output = validationService.validateBundleResourcesIdValid(bundle); + assertThat(output, is(notNullValue())); + assertThat(output.hasIssue(), is(true)); + assertEquals(output.getIssueFirstRep().getDiagnostics(), "All resources must have an Id"); + } + } } From ad81d92d2b8585027718c999bb15f9cd277cd74e Mon Sep 17 00:00:00 2001 From: CeciliaLiu8 Date: Fri, 14 Apr 2023 09:23:22 -0500 Subject: [PATCH 06/10] use CollectionUtils instead --- .../madiefhirservice/services/MeasureTranslatorService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/gov/cms/madie/madiefhirservice/services/MeasureTranslatorService.java b/src/main/java/gov/cms/madie/madiefhirservice/services/MeasureTranslatorService.java index be5dd659..31f669dc 100644 --- a/src/main/java/gov/cms/madie/madiefhirservice/services/MeasureTranslatorService.java +++ b/src/main/java/gov/cms/madie/madiefhirservice/services/MeasureTranslatorService.java @@ -127,7 +127,7 @@ public List buildMeasureIdentifiers(Measure madieMeasure) { ValueConstants.CODE_VERSION_SPECIFIC)); if (madieMeasure.getMeasureMetaData() != null && madieMeasure.getMeasureMetaData().getEndorsements() != null - && !madieMeasure.getMeasureMetaData().getEndorsements().isEmpty() + && CollectionUtils.isNotEmpty(madieMeasure.getMeasureMetaData().getEndorsements()) && StringUtils.isNotBlank( madieMeasure.getMeasureMetaData().getEndorsements().get(0).getEndorser())) { Endorsement endorsement = madieMeasure.getMeasureMetaData().getEndorsements().get(0); From f913ef1951478f6aef1daaa4aa7f7d73be5f9bea Mon Sep 17 00:00:00 2001 From: Joseph Kotanchik Date: Tue, 18 Apr 2023 14:28:32 -0400 Subject: [PATCH 07/10] Use the FHIRPath escape function on user supplied descriptions to handle any HTML unfriendly characters such as < and & --- src/main/resources/templates/Measure.liquid | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/resources/templates/Measure.liquid b/src/main/resources/templates/Measure.liquid index 3fffd1a7..0f3a79a6 100644 --- a/src/main/resources/templates/Measure.liquid +++ b/src/main/resources/templates/Measure.liquid @@ -173,7 +173,7 @@ {% if Measure.description.exists() %} Description: - {{Measure.description}} + {{Measure.description.escape('html')}} {% endif %} {% if Measure.group.exists() %} @@ -191,7 +191,7 @@ {% for population in group.population %} {{population.code.coding[0].display}}: - {{population.description}} + {{population.description.escape('html')}} {% endfor %} @@ -579,7 +579,7 @@ {{population.code.first().coding.first().display}} {% if population.description %} - {{(population.description)}} + {{(population.description.escape('html'))}} {% endif %} @@ -666,10 +666,10 @@ {{iif(supplementalData.code.text.exists(), supplementalData.code.text, iif(supplementalData.code.coding.first().display.exists(), supplementalData.code.coding.first().display, supplementalData.code.coding.first().code))}} {% else %} {%if supplementalData.description.exists() %} - {{supplementalData.description}} + {{supplementalData.description.escape('html')}} {% else %} {%if supplementalData.criteria.description.exists() %} - {{supplementalData.criteria.description}} + {{supplementalData.criteria.description.escape('html')}} {% else %} {{supplementalData.criteria.expression}} {% endif %} @@ -689,10 +689,10 @@ {{iif(supplementalData.code.text.exists(), supplementalData.code.text, iif(supplementalData.code.coding.first().display.exists(), supplementalData.code.coding.first().display, supplementalData.code.coding.first().code))}} {% else %} {%if supplementalData.description.exists() %} - {{supplementalData.description}} + {{supplementalData.description.escape('html')}} {% else %} {%if supplementalData.criteria.description.exists() %} - {{supplementalData.criteria.description}} + {{supplementalData.criteria.description.escape('html')}} {% else %} {{supplementalData.criteria.expression}} {% endif %} From 94856b011aeab2f76158db46dbe0f15eefabb5e3 Mon Sep 17 00:00:00 2001 From: mcmcphillips Date: Wed, 19 Apr 2023 06:48:30 -0700 Subject: [PATCH 08/10] escape html charactars. charactar & breaks export --- .../madie/madiefhirservice/services/MeasureBundleService.java | 3 +++ src/main/resources/templates/Measure.liquid | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/gov/cms/madie/madiefhirservice/services/MeasureBundleService.java b/src/main/java/gov/cms/madie/madiefhirservice/services/MeasureBundleService.java index 570f9d00..7808aeb1 100644 --- a/src/main/java/gov/cms/madie/madiefhirservice/services/MeasureBundleService.java +++ b/src/main/java/gov/cms/madie/madiefhirservice/services/MeasureBundleService.java @@ -29,6 +29,8 @@ import java.util.Map; import java.util.stream.Collectors; +// import ca.uhn.fhir.context.FhirContext; + @Slf4j @Service @RequiredArgsConstructor @@ -39,6 +41,7 @@ public class MeasureBundleService { private final HapiFhirServer hapiFhirServer; private final ElmTranslatorClient elmTranslatorClient; private final HumanReadableService humanReadableService; + // private final FhirContext fhirContext; /** * Creates measure bundle that contains measure, main library, and included libraries resources diff --git a/src/main/resources/templates/Measure.liquid b/src/main/resources/templates/Measure.liquid index 0f3a79a6..84c59aaf 100644 --- a/src/main/resources/templates/Measure.liquid +++ b/src/main/resources/templates/Measure.liquid @@ -493,7 +493,7 @@ {% for statementExtension in extension.extension.where(url = 'statement') %} -
{{statementExtension.value}}
+
{{statementExtension.value.escape('html')}}
{% endfor %} {% endfor %} @@ -648,7 +648,7 @@ {% for statementExtension in extension.extension.where(url = 'statement') %} -
{{statementExtension.value}}
+
{{statementExtension.value.escape('html')}}
{% endfor %}

{% endfor %} From 666e28ebbc8f51586a44e4d1bd4a7deb753e506e Mon Sep 17 00:00:00 2001 From: mcmcphillips Date: Wed, 19 Apr 2023 07:02:54 -0700 Subject: [PATCH 09/10] Remove dead code --- .../madie/madiefhirservice/services/MeasureBundleService.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/gov/cms/madie/madiefhirservice/services/MeasureBundleService.java b/src/main/java/gov/cms/madie/madiefhirservice/services/MeasureBundleService.java index 7808aeb1..570f9d00 100644 --- a/src/main/java/gov/cms/madie/madiefhirservice/services/MeasureBundleService.java +++ b/src/main/java/gov/cms/madie/madiefhirservice/services/MeasureBundleService.java @@ -29,8 +29,6 @@ import java.util.Map; import java.util.stream.Collectors; -// import ca.uhn.fhir.context.FhirContext; - @Slf4j @Service @RequiredArgsConstructor @@ -41,7 +39,6 @@ public class MeasureBundleService { private final HapiFhirServer hapiFhirServer; private final ElmTranslatorClient elmTranslatorClient; private final HumanReadableService humanReadableService; - // private final FhirContext fhirContext; /** * Creates measure bundle that contains measure, main library, and included libraries resources From f4baf19598839c46638edb62d3d7975aa8fad83b Mon Sep 17 00:00:00 2001 From: Nate Moraca Date: Mon, 24 Apr 2023 12:15:33 -0400 Subject: [PATCH 10/10] replace HAPI FHIR with CQL Library Service for fetching CQL Libraries --- .../CqlLibraryNotFoundException.java | 18 ++ .../exceptions/MissingCqlException.java | 17 ++ .../resources/HapiFhirLibraryController.java | 60 ----- .../services/CqlLibraryService.java | 69 ++++++ .../services/LibraryService.java | 114 +++------- .../services/MeasureBundleService.java | 10 +- src/main/resources/application.yml | 5 + .../HapiFhirLibraryControllerMvcTest.java | 53 ----- .../HapiFhirLibraryControllerTest.java | 70 ------ .../services/LibraryServiceTest.java | 213 +++++------------- .../services/MeasureBundleServiceTest.java | 13 +- 11 files changed, 203 insertions(+), 439 deletions(-) create mode 100644 src/main/java/gov/cms/madie/madiefhirservice/exceptions/CqlLibraryNotFoundException.java create mode 100644 src/main/java/gov/cms/madie/madiefhirservice/exceptions/MissingCqlException.java delete mode 100644 src/main/java/gov/cms/madie/madiefhirservice/resources/HapiFhirLibraryController.java create mode 100644 src/main/java/gov/cms/madie/madiefhirservice/services/CqlLibraryService.java delete mode 100644 src/test/java/gov/cms/madie/madiefhirservice/resources/HapiFhirLibraryControllerMvcTest.java delete mode 100644 src/test/java/gov/cms/madie/madiefhirservice/resources/HapiFhirLibraryControllerTest.java diff --git a/src/main/java/gov/cms/madie/madiefhirservice/exceptions/CqlLibraryNotFoundException.java b/src/main/java/gov/cms/madie/madiefhirservice/exceptions/CqlLibraryNotFoundException.java new file mode 100644 index 00000000..d6d12b96 --- /dev/null +++ b/src/main/java/gov/cms/madie/madiefhirservice/exceptions/CqlLibraryNotFoundException.java @@ -0,0 +1,18 @@ +package gov.cms.madie.madiefhirservice.exceptions; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(value = HttpStatus.NOT_FOUND) +@Slf4j +public class CqlLibraryNotFoundException extends RuntimeException { + + private static final String NOT_FOUND_BY_FIND_DATA = + "Cannot find a CQL Library with name: %s, version: %s"; + + public CqlLibraryNotFoundException(String name, String version) { + super(String.format(NOT_FOUND_BY_FIND_DATA, name, version)); + log.error(getMessage()); + } +} diff --git a/src/main/java/gov/cms/madie/madiefhirservice/exceptions/MissingCqlException.java b/src/main/java/gov/cms/madie/madiefhirservice/exceptions/MissingCqlException.java new file mode 100644 index 00000000..ffc6b5e7 --- /dev/null +++ b/src/main/java/gov/cms/madie/madiefhirservice/exceptions/MissingCqlException.java @@ -0,0 +1,17 @@ +package gov.cms.madie.madiefhirservice.exceptions; + +import gov.cms.madie.models.library.CqlLibrary; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(value = HttpStatus.NOT_FOUND) +@Slf4j +public class MissingCqlException extends RuntimeException { + private static final String NONE_FOUND = "Cannot find CQL for library name: %s, version: %s"; + + public MissingCqlException(CqlLibrary library) { + super(String.format(NONE_FOUND, library.getCqlLibraryName(), library.getVersion())); + log.warn(getMessage()); + } +} diff --git a/src/main/java/gov/cms/madie/madiefhirservice/resources/HapiFhirLibraryController.java b/src/main/java/gov/cms/madie/madiefhirservice/resources/HapiFhirLibraryController.java deleted file mode 100644 index 2dd68580..00000000 --- a/src/main/java/gov/cms/madie/madiefhirservice/resources/HapiFhirLibraryController.java +++ /dev/null @@ -1,60 +0,0 @@ -package gov.cms.madie.madiefhirservice.resources; - -import gov.cms.madie.madiefhirservice.services.LibraryService; -import gov.cms.madie.models.library.CqlLibrary; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.hl7.fhir.r4.model.Library; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -@Slf4j -@RestController -@RequestMapping(path = "/fhir/libraries") -@Tag(name = "HAPI-FHIR-Library-Controller", description = "API for Library resources in HAPI") -@RequiredArgsConstructor -public class HapiFhirLibraryController { - - private final LibraryService libraryService; - - @Operation( - summary = "Get Library's CQL from HAPI FHIR.", - description = - "Fetches Library resource from HAPI FHIR and returns cql string," - + " typically used by CQL-ELM Translator") - @GetMapping("/cql") - public String getLibraryCql(@RequestParam String name, @RequestParam String version) { - return libraryService.getLibraryCql(name, version); - } - - @Operation( - summary = "Get Library's CQL, ELM JSON and ELM XML from HAPI FHIR", - description = - "Fetches Library resource from HAPI FHIR and returns cql string, ELM JSON string," - + " and ELM XML string.") - @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE) - public CqlLibrary getLibraryResourceAsCqlLibrary( - @RequestParam String name, @RequestParam String version) { - return libraryService.getLibraryResourceAsCqlLibrary(name, version); - } - - @Operation( - summary = "Creates new Library Resource in HAPI FHIR. ", - description = - "Creates the new hapi FHIR Library Resource from MADiE Library " - + "if the Library with same name and version does not exists in HAPI FHIR.") - @PostMapping("/create") - public ResponseEntity createLibraryResource(@RequestBody CqlLibrary cqlLibrary) { - Library library = libraryService.createLibraryResourceForCqlLibrary(cqlLibrary); - return ResponseEntity.status(HttpStatus.CREATED).body(library.getUrl()); - } -} diff --git a/src/main/java/gov/cms/madie/madiefhirservice/services/CqlLibraryService.java b/src/main/java/gov/cms/madie/madiefhirservice/services/CqlLibraryService.java new file mode 100644 index 00000000..ab444181 --- /dev/null +++ b/src/main/java/gov/cms/madie/madiefhirservice/services/CqlLibraryService.java @@ -0,0 +1,69 @@ +package gov.cms.madie.madiefhirservice.services; + +import gov.cms.madie.madiefhirservice.exceptions.CqlLibraryNotFoundException; +import gov.cms.madie.models.library.CqlLibrary; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.UriComponentsBuilder; + +import java.net.URI; + +@Service +@Slf4j +@RequiredArgsConstructor +public class CqlLibraryService { + + private final RestTemplate restTemplate; + + @Value("${madie.library.service.baseUrl}") + private String madieLibraryService; + + @Value("${madie.library.service.versioned.uri}") + private String librariesVersionedUri; + + public CqlLibrary getLibrary(String name, String version, String accessToken) { + URI uri = buildMadieLibraryServiceUri(name, version); + log.debug("Getting Madie library: {} ", uri); + + HttpHeaders headers = new HttpHeaders(); + headers.add("Authorization", accessToken); + + ResponseEntity responseEntity = + restTemplate.exchange(uri, HttpMethod.GET, new HttpEntity<>(headers), CqlLibrary.class); + + if (responseEntity.getStatusCode().is2xxSuccessful()) { + if (responseEntity.hasBody()) { + log.debug("Retrieved a valid cqlPayload"); + return responseEntity.getBody(); + } else { + log.error("Cannot find Cql payload in the response"); + return null; + } + } else if (responseEntity.getStatusCode().equals(HttpStatus.NOT_FOUND)) { + throw new CqlLibraryNotFoundException(name, version); + } else if (responseEntity.getStatusCode().equals(HttpStatus.CONFLICT)) { + log.error( + "Multiple libraries found with name: {}, version: {}, but only one was expected", + name, + version); + } + return null; + } + + private URI buildMadieLibraryServiceUri(String name, String version) { + return UriComponentsBuilder.fromHttpUrl(madieLibraryService + librariesVersionedUri) + .queryParam("name", name) + .queryParam("version", version) + .build() + .encode() + .toUri(); + } +} diff --git a/src/main/java/gov/cms/madie/madiefhirservice/services/LibraryService.java b/src/main/java/gov/cms/madie/madiefhirservice/services/LibraryService.java index 352956cc..23005a7d 100644 --- a/src/main/java/gov/cms/madie/madiefhirservice/services/LibraryService.java +++ b/src/main/java/gov/cms/madie/madiefhirservice/services/LibraryService.java @@ -2,89 +2,38 @@ import gov.cms.madie.madiefhirservice.cql.LibraryCqlVisitor; import gov.cms.madie.madiefhirservice.cql.LibraryCqlVisitorFactory; -import gov.cms.madie.madiefhirservice.exceptions.DuplicateLibraryException; -import gov.cms.madie.madiefhirservice.exceptions.HapiLibraryNotFoundException; import gov.cms.madie.madiefhirservice.exceptions.LibraryAttachmentNotFoundException; -import gov.cms.madie.madiefhirservice.hapi.HapiFhirServer; +import gov.cms.madie.madiefhirservice.exceptions.MissingCqlException; +import gov.cms.madie.madiefhirservice.utils.BundleUtil; import gov.cms.madie.models.library.CqlLibrary; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.hl7.fhir.r4.model.Attachment; -import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.Library; import org.hl7.fhir.r4.model.Narrative; import org.hl7.fhir.r4.model.Narrative.NarrativeStatus; import org.springframework.stereotype.Service; -import org.springframework.util.CollectionUtils; -import java.util.List; import java.util.Map; -import java.util.Optional; @Service @Slf4j @RequiredArgsConstructor public class LibraryService { - private final HapiFhirServer hapiFhirServer; + + private final CqlLibraryService cqlLibraryService; private final LibraryTranslatorService libraryTranslatorService; private final LibraryCqlVisitorFactory libCqlVisitorFactory; private final HumanReadableService humanReadableService; - public String getLibraryCql(String name, String version) { - - Bundle bundle = hapiFhirServer.fetchLibraryBundleByNameAndVersion(name, version); - if (bundle.hasEntry()) { - return processBundle(name, version, bundle); - } else { - throw new HapiLibraryNotFoundException(name, version); - } - } - - public CqlLibrary getLibraryResourceAsCqlLibrary(String name, String version) { - Bundle bundle = hapiFhirServer.fetchLibraryBundleByNameAndVersion(name, version); - - if (bundle.hasEntry()) { - Optional optional = - hapiFhirServer.findLibraryResourceInBundle(bundle, Library.class); - return optional - .map(libraryTranslatorService::convertToCqlLibrary) - .orElseThrow(() -> new HapiLibraryNotFoundException(name, version)); - } else { - throw new HapiLibraryNotFoundException(name, version); - } - } - - public boolean isLibraryResourcePresent(String name, String version) { - - Bundle bundle = hapiFhirServer.fetchLibraryBundleByNameAndVersion(name, version); - if (!bundle.hasEntry()) { - return false; - } - - return hapiFhirServer.findLibraryResourceInBundle(bundle, Library.class).isPresent(); - } - - private String processBundle(String name, String version, Bundle bundle) { - - Optional optional = hapiFhirServer.findLibraryResourceInBundle(bundle, Library.class); - if (optional.isPresent()) { - return getCqlFromHapiLibrary(optional.get()); - } else { - throw new HapiLibraryNotFoundException(name, version); - } - } - - private String getCqlFromHapiLibrary(Library library) { - - List attachments = library.getContent(); - - if (CollectionUtils.isEmpty(attachments)) { - throw new LibraryAttachmentNotFoundException(library); + public String getLibraryCql(String name, String version, final String accessToken) { + CqlLibrary library = cqlLibraryService.getLibrary(name, version, accessToken); + if (StringUtils.isBlank(library.getCql())) { + throw new MissingCqlException(library); } - Attachment cql = findCqlAttachment(library); - return new String(cql.getData()); + return cqlLibraryService.getLibrary(name, version, accessToken).getCql(); } private Attachment findCqlAttachment(Library library) { @@ -94,23 +43,19 @@ private Attachment findCqlAttachment(Library library) { .orElseThrow(() -> new LibraryAttachmentNotFoundException(library, "text/cql")); } - public Library createLibraryResourceForCqlLibrary(CqlLibrary cqlLibrary) { - boolean isLibraryPresent = - isLibraryResourcePresent( - cqlLibrary.getCqlLibraryName(), cqlLibrary.getVersion().toString()); - - if (isLibraryPresent) { - throw new DuplicateLibraryException( - cqlLibrary.getCqlLibraryName(), cqlLibrary.getVersion().toString()); - } - + public Library cqlLibraryToFhirLibrary(CqlLibrary cqlLibrary, final String bundleType) { Library library = libraryTranslatorService.convertToFhirLibrary(cqlLibrary, null); - library.setText(createLibraryNarrativeText(library)); - hapiFhirServer.createResource(library); + if (BundleUtil.MEASURE_BUNDLE_TYPE_EXPORT.equals(bundleType)) { + library.setText(createLibraryNarrativeText(library)); + } return library; } - public void getIncludedLibraries(String cql, Map libraryMap) { + public void getIncludedLibraries( + String cql, + Map libraryMap, + final String bundleType, + final String accessToken) { if (StringUtils.isBlank(cql) || libraryMap == null) { log.error("Invalid method arguments provided to getIncludedLibraries"); throw new IllegalArgumentException("Please provide valid arguments."); @@ -118,21 +63,16 @@ public void getIncludedLibraries(String cql, Map libraryMap) { LibraryCqlVisitor visitor = libCqlVisitorFactory.visit(cql); for (Pair libraryNameValuePair : visitor.getIncludedLibraries()) { - Optional optionalLibrary = - hapiFhirServer.fetchHapiLibrary( - libraryNameValuePair.getLeft(), libraryNameValuePair.getRight()); - if (optionalLibrary.isPresent()) { - Library library = optionalLibrary.get(); - String key = library.getName() + library.getVersion(); - if (!libraryMap.containsKey(key)) { - libraryMap.put(key, library); - } - Attachment attachment = findCqlAttachment(library); - getIncludedLibraries(new String(attachment.getData()), libraryMap); - } else { - throw new HapiLibraryNotFoundException( - libraryNameValuePair.getLeft(), libraryNameValuePair.getRight()); + CqlLibrary cqlLibrary = + cqlLibraryService.getLibrary( + libraryNameValuePair.getLeft(), libraryNameValuePair.getRight(), accessToken); + Library library = cqlLibraryToFhirLibrary(cqlLibrary, bundleType); + String key = library.getName() + library.getVersion(); + if (!libraryMap.containsKey(key)) { + libraryMap.put(key, library); } + Attachment attachment = findCqlAttachment(library); + getIncludedLibraries(new String(attachment.getData()), libraryMap, bundleType, accessToken); } } diff --git a/src/main/java/gov/cms/madie/madiefhirservice/services/MeasureBundleService.java b/src/main/java/gov/cms/madie/madiefhirservice/services/MeasureBundleService.java index 570f9d00..44221938 100644 --- a/src/main/java/gov/cms/madie/madiefhirservice/services/MeasureBundleService.java +++ b/src/main/java/gov/cms/madie/madiefhirservice/services/MeasureBundleService.java @@ -45,7 +45,8 @@ public class MeasureBundleService { */ public Bundle createMeasureBundle( Measure madieMeasure, Principal principal, String bundleType, String accessToken) { - log.info("Generating measure bundle for measure {}", madieMeasure.getId()); + log.info( + "Generating measure bundle of type [{}] for measure {}", bundleType, madieMeasure.getId()); madieMeasure.setCql(CqlFormatter.formatCql(madieMeasure.getCql(), principal)); org.hl7.fhir.r4.model.Measure measure = @@ -57,7 +58,7 @@ public Bundle createMeasureBundle( new Bundle().setType(Bundle.BundleType.TRANSACTION).addEntry(measureEntryComponent); // Bundle entries for all the library resources of a MADiE Measure List libraryEntryComponents = - createBundleComponentsForLibrariesOfMadieMeasure(madieMeasure); + createBundleComponentsForLibrariesOfMadieMeasure(madieMeasure, bundleType, accessToken); libraryEntryComponents.forEach(bundle::addEntry); if (BundleUtil.MEASURE_BUNDLE_TYPE_EXPORT.equals(bundleType)) { @@ -90,11 +91,12 @@ public Bundle createMeasureBundle( * @return list of Library BundleEntryComponents */ public List createBundleComponentsForLibrariesOfMadieMeasure( - Measure madieMeasure) { + Measure madieMeasure, final String bundleType, final String accessToken) { Library library = getMeasureLibraryResourceForMadieMeasure(madieMeasure); Bundle.BundleEntryComponent mainLibraryBundleComponent = getBundleEntryComponent(library); Map includedLibraryMap = new HashMap<>(); - libraryService.getIncludedLibraries(madieMeasure.getCql(), includedLibraryMap); + libraryService.getIncludedLibraries( + madieMeasure.getCql(), includedLibraryMap, bundleType, accessToken); List libraryBundleComponents = includedLibraryMap.values().stream() .map(this::getBundleEntryComponent) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 8837b097..c9af1951 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -14,6 +14,11 @@ madie: service: base-url: ${ELM_TRANSLATOR_SERVICE_URL:http://localhost:8084/api} effective-data-requirements-uri: /effective-data-requirements + library: + service: + baseUrl: ${CQL_LIBRARY_SERVICE_URL:http://localhost:8082/api} + versioned: + uri: /cql-libraries/versioned #springdoc: # swagger-ui: # path: ${SWAGGER_PATH:/swagger} diff --git a/src/test/java/gov/cms/madie/madiefhirservice/resources/HapiFhirLibraryControllerMvcTest.java b/src/test/java/gov/cms/madie/madiefhirservice/resources/HapiFhirLibraryControllerMvcTest.java deleted file mode 100644 index 304ab079..00000000 --- a/src/test/java/gov/cms/madie/madiefhirservice/resources/HapiFhirLibraryControllerMvcTest.java +++ /dev/null @@ -1,53 +0,0 @@ -package gov.cms.madie.madiefhirservice.resources; - -import gov.cms.madie.madiefhirservice.exceptions.HapiLibraryNotFoundException; -import gov.cms.madie.madiefhirservice.services.LibraryService; -import gov.cms.madie.models.library.CqlLibrary; -import gov.cms.madie.models.common.Version; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.test.web.servlet.MockMvc; - -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.when; -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user; -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@WebMvcTest({HapiFhirLibraryController.class}) -public class HapiFhirLibraryControllerMvcTest { - - private static final String TEST_USER_ID = "test-okta-user-id-123"; - - @MockBean private LibraryService libraryService; - - @Autowired private MockMvc mockMvc; - - @Test - public void testGetLibraryResourceAsCqlLibraryReturnsNotFound() throws Exception { - when(libraryService.getLibraryResourceAsCqlLibrary(anyString(), anyString())) - .thenThrow(new HapiLibraryNotFoundException("Test", "1.0.000")); - mockMvc - .perform( - get("/fhir/libraries?name=Test&version=1.0.000").with(user(TEST_USER_ID)).with(csrf())) - .andExpect(status().isNotFound()); - } - - @Test - public void testGetLibraryResourceAsCqlLibraryReturnsLibrary() throws Exception { - CqlLibrary library = - CqlLibrary.builder().cqlLibraryName("Test").version(Version.parse("1.0.000")).build(); - when(libraryService.getLibraryResourceAsCqlLibrary(anyString(), anyString())) - .thenReturn(library); - mockMvc - .perform( - get("/fhir/libraries?name=Test&version=1.0.000").with(user(TEST_USER_ID)).with(csrf())) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.cqlLibraryName").value("Test")) - .andExpect(jsonPath("$.version").value("1.0.000")); - } -} diff --git a/src/test/java/gov/cms/madie/madiefhirservice/resources/HapiFhirLibraryControllerTest.java b/src/test/java/gov/cms/madie/madiefhirservice/resources/HapiFhirLibraryControllerTest.java deleted file mode 100644 index 3a9061d6..00000000 --- a/src/test/java/gov/cms/madie/madiefhirservice/resources/HapiFhirLibraryControllerTest.java +++ /dev/null @@ -1,70 +0,0 @@ -package gov.cms.madie.madiefhirservice.resources; - -import gov.cms.madie.madiefhirservice.exceptions.HapiLibraryNotFoundException; -import gov.cms.madie.madiefhirservice.services.LibraryService; -import gov.cms.madie.madiefhirservice.utils.LibraryHelper; -import gov.cms.madie.madiefhirservice.utils.ResourceFileUtil; -import gov.cms.madie.models.library.CqlLibrary; -import org.hl7.fhir.r4.model.Library; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.http.ResponseEntity; - -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.Mockito.*; - -@ExtendWith(MockitoExtension.class) -class HapiFhirLibraryControllerTest implements LibraryHelper, ResourceFileUtil { - - @InjectMocks HapiFhirLibraryController hapiFhirLibraryController; - - @Mock LibraryService libraryService; - - @Test - void findLibraryHapiCql() { - when(libraryService.getLibraryCql("TestLibrary", "1.0.0")).thenReturn("Cql From HAPI FHIR"); - assertEquals( - "Cql From HAPI FHIR", hapiFhirLibraryController.getLibraryCql("TestLibrary", "1.0.0")); - verifyNoMoreInteractions(libraryService); - } - - @Test - void createLibraryResource() { - String cql = getStringFromTestResource("/test-cql/EXM124v7QICore4.cql"); - CqlLibrary cqlLibrary = createCqlLibrary(cql); - Library library = new Library(); - library.setName(cqlLibrary.getCqlLibraryName()); - library.setVersion(cqlLibrary.getVersion().toString()); - library.setUrl("test-url"); - when(libraryService.createLibraryResourceForCqlLibrary(any(CqlLibrary.class))) - .thenReturn(library); - ResponseEntity response = hapiFhirLibraryController.createLibraryResource(cqlLibrary); - verifyNoMoreInteractions(libraryService); - assertNotNull(response.getBody()); - assertEquals(library.getUrl(), response.getBody()); - } - - @Test - void testGetLibraryResourceAsCqlLibraryThrowsException() { - when(libraryService.getLibraryResourceAsCqlLibrary(anyString(), anyString())) - .thenThrow(new HapiLibraryNotFoundException("Test", "1.0.000")); - assertThrows( - HapiLibraryNotFoundException.class, - () -> hapiFhirLibraryController.getLibraryResourceAsCqlLibrary("Test", "1.0.000")); - } - - @Test - void testGetLibraryResourceAsCqlLibraryReturnsLibrary() { - CqlLibrary library = new CqlLibrary(); - when(libraryService.getLibraryResourceAsCqlLibrary(anyString(), anyString())) - .thenReturn(library); - CqlLibrary output = hapiFhirLibraryController.getLibraryResourceAsCqlLibrary("Test", "1.0.000"); - assertThat(output, is(equalTo(library))); - } -} diff --git a/src/test/java/gov/cms/madie/madiefhirservice/services/LibraryServiceTest.java b/src/test/java/gov/cms/madie/madiefhirservice/services/LibraryServiceTest.java index 0cbafc1c..3154b97a 100644 --- a/src/test/java/gov/cms/madie/madiefhirservice/services/LibraryServiceTest.java +++ b/src/test/java/gov/cms/madie/madiefhirservice/services/LibraryServiceTest.java @@ -1,13 +1,12 @@ package gov.cms.madie.madiefhirservice.services; -import ca.uhn.fhir.rest.api.MethodOutcome; import gov.cms.madie.madiefhirservice.cql.LibraryCqlVisitorFactory; -import gov.cms.madie.madiefhirservice.exceptions.DuplicateLibraryException; -import gov.cms.madie.madiefhirservice.exceptions.HapiLibraryNotFoundException; -import gov.cms.madie.madiefhirservice.exceptions.LibraryAttachmentNotFoundException; +import gov.cms.madie.madiefhirservice.exceptions.*; import gov.cms.madie.madiefhirservice.hapi.HapiFhirServer; +import gov.cms.madie.madiefhirservice.utils.BundleUtil; import gov.cms.madie.madiefhirservice.utils.LibraryHelper; import gov.cms.madie.madiefhirservice.utils.ResourceFileUtil; +import gov.cms.madie.models.common.Version; import gov.cms.madie.models.library.CqlLibrary; import org.hl7.fhir.r4.model.Attachment; import org.hl7.fhir.r4.model.Bundle; @@ -22,7 +21,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Optional; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; @@ -34,9 +32,6 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.any; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) @@ -44,7 +39,7 @@ class LibraryServiceTest implements LibraryHelper, ResourceFileUtil { @InjectMocks private LibraryService libraryService; - @Mock private HapiFhirServer hapiFhirServer; + @Mock private CqlLibraryService cqlLibraryService; @Mock private LibraryTranslatorService libraryTranslatorService; @Mock private LibraryCqlVisitorFactory libCqlVisitorFactory; @Mock private HumanReadableService humanReadableService; @@ -63,162 +58,50 @@ void buildLibraryBundle() { } @Test - void testSuccessfullyFindCqlInHapiLibrary() { - when(hapiFhirServer.fetchLibraryBundleByNameAndVersion(anyString(), anyString())) - .thenReturn(bundle); - when(hapiFhirServer.findLibraryResourceInBundle(bundle, Library.class)) - .thenReturn(Optional.of(fhirHelpersLibrary)); - String testCql = libraryService.getLibraryCql("FHIRHelpers", "4.0.001"); + void testSuccessfullyFindCqlInCqlLibrary() { + when(cqlLibraryService.getLibrary(anyString(), anyString(), anyString())) + .thenReturn( + CqlLibrary.builder() + .cqlLibraryName("FHIRHelpers") + .version(Version.builder().major(4).minor(0).revisionNumber(1).build()) + .cql("Valid FHIRHelpers CQL here") + .build()); + String testCql = libraryService.getLibraryCql("FHIRHelpers", "4.0.001", "TOKEN"); assertTrue(testCql.contains("FHIRHelpers")); } @Test void testLibraryBundleHasNoEntry() { - bundle.setEntry(null); - when(hapiFhirServer.fetchLibraryBundleByNameAndVersion(anyString(), anyString())) - .thenReturn(bundle); + when(cqlLibraryService.getLibrary(anyString(), anyString(), anyString())) + .thenThrow(new CqlLibraryNotFoundException("FHIRHelpers", "4.0.001")); Throwable exception = assertThrows( - HapiLibraryNotFoundException.class, - () -> libraryService.getLibraryCql("FHIRHelpers", "4.0.001")); + CqlLibraryNotFoundException.class, + () -> libraryService.getLibraryCql("FHIRHelpers", "4.0.001", "TOKEN")); assertEquals( - "Cannot find a Hapi Fhir Library with name: FHIRHelpers, version: 4.0.001", - exception.getMessage()); - } - - @Test - void testLibraryIsNotReturnedByHapi() { - when(hapiFhirServer.fetchLibraryBundleByNameAndVersion(anyString(), anyString())) - .thenReturn(bundle); - when(hapiFhirServer.findLibraryResourceInBundle(bundle, Library.class)) - .thenReturn(Optional.empty()); - - Throwable exception = - assertThrows( - HapiLibraryNotFoundException.class, - () -> libraryService.getLibraryCql("FHIRHelpers", "4.0.001")); - assertEquals( - "Cannot find a Hapi Fhir Library with name: FHIRHelpers, version: 4.0.001", - exception.getMessage()); - } - - @Test - void testLibraryDoesNotContainAnyAttachments() { - when(hapiFhirServer.fetchLibraryBundleByNameAndVersion(anyString(), anyString())) - .thenReturn(bundle); - when(hapiFhirServer.findLibraryResourceInBundle(bundle, Library.class)) - .thenReturn(Optional.of(fhirHelpersLibrary)); - - fhirHelpersLibrary.setContent(null); - Throwable exception = - assertThrows( - LibraryAttachmentNotFoundException.class, - () -> libraryService.getLibraryCql("FHIRHelpers", "4.0.001")); - assertEquals( - "Cannot find any attachment for library name: FHIRHelpers, version: 4.0.001", + "Cannot find a CQL Library with name: FHIRHelpers, version: 4.0.001", exception.getMessage()); } @Test void testLibraryDoesNotContainCqlTextAttachment() { - when(hapiFhirServer.fetchLibraryBundleByNameAndVersion(anyString(), anyString())) - .thenReturn(bundle); - when(hapiFhirServer.findLibraryResourceInBundle(bundle, Library.class)) - .thenReturn(Optional.of(fhirHelpersLibrary)); - - fhirHelpersLibrary.getContent().get(0).setContentType("text/test"); + // when(hapiFhirServer.fetchLibraryBundleByNameAndVersion(anyString(), anyString())) + // .thenReturn(bundle); + // when(hapiFhirServer.findLibraryResourceInBundle(bundle, Library.class)) + // .thenReturn(Optional.of(fhirHelpersLibrary)); + + when(cqlLibraryService.getLibrary(anyString(), anyString(), anyString())) + .thenReturn( + CqlLibrary.builder() + .cqlLibraryName("FHIRHelpers") + .version(Version.builder().major(4).minor(0).revisionNumber(1).build()) + .build()); Throwable exception = assertThrows( - LibraryAttachmentNotFoundException.class, - () -> libraryService.getLibraryCql("FHIRHelpers", "4.0.001")); - assertEquals( - "Cannot find attachment type text/cql for library name: FHIRHelpers, version: 4.0.001", - exception.getMessage()); - } - - @Test - void createLibraryResourceForCqlLibraryWhenLibraryIsValidAndNotDuplicate() { - String cql = getStringFromTestResource("/test-cql/EXM124v7QICore4.cql"); - CqlLibrary cqlLibrary = createCqlLibrary(cql); - Library library = createLibrary(cql); - - when(hapiFhirServer.fetchLibraryBundleByNameAndVersion(anyString(), anyString())) - .thenReturn(new Bundle()); - when(libraryTranslatorService.convertToFhirLibrary(eq(cqlLibrary), isNull())) - .thenReturn(library); - when(hapiFhirServer.createResource(any(Library.class))).thenReturn(new MethodOutcome()); - when(humanReadableService.generateLibraryHumanReadable(any(Library.class))) - .thenReturn("
Narrative Text
"); - - Library libraryResource = libraryService.createLibraryResourceForCqlLibrary(cqlLibrary); - - assertEquals(libraryResource.getName(), cqlLibrary.getCqlLibraryName()); - assertEquals(libraryResource.getVersion(), cqlLibrary.getVersion().toString()); + MissingCqlException.class, + () -> libraryService.getLibraryCql("FHIRHelpers", "4.0.001", "TOKEN")); assertEquals( - libraryResource.getText().getDivAsString(), - "
Narrative Text
"); - assertEquals(libraryResource.getText().getStatus().getDisplay(), "Extensions"); - } - - @Test - void testGetLibraryResourceAsCqlLibraryHandlesNoEntry() { - bundle.setEntry(null); - when(hapiFhirServer.fetchLibraryBundleByNameAndVersion(anyString(), anyString())) - .thenReturn(bundle); - assertThrows( - HapiLibraryNotFoundException.class, - () -> libraryService.getLibraryResourceAsCqlLibrary("TestLibrary", "1.0.000")); - verify(hapiFhirServer, times(0)) - .findLibraryResourceInBundle(any(Bundle.class), any(Class.class)); - } - - @Test - void testGetLibraryResourceAsCqlLibraryHandlesNoLibrary() { - when(hapiFhirServer.fetchLibraryBundleByNameAndVersion(anyString(), anyString())) - .thenReturn(bundle); - when(hapiFhirServer.findLibraryResourceInBundle(any(Bundle.class), any(Class.class))) - .thenReturn(Optional.empty()); - assertThrows( - HapiLibraryNotFoundException.class, - () -> libraryService.getLibraryResourceAsCqlLibrary("TestLibrary", "1.0.000")); - verify(hapiFhirServer, times(1)) - .findLibraryResourceInBundle(any(Bundle.class), any(Class.class)); - } - - @Test - void testGetLibraryResourceAsCqlLibraryReturnsCqlLibrary() { - Library library = (Library) bundle.getEntry().get(0).getResource(); - when(hapiFhirServer.fetchLibraryBundleByNameAndVersion(anyString(), anyString())) - .thenReturn(bundle); - when(hapiFhirServer.findLibraryResourceInBundle(any(Bundle.class), any(Class.class))) - .thenReturn(Optional.of(library)); - CqlLibrary cqlLibrary = new CqlLibrary(); - when(libraryTranslatorService.convertToCqlLibrary(eq(library))).thenReturn(cqlLibrary); - - CqlLibrary output = libraryService.getLibraryResourceAsCqlLibrary("TestLibrary", "1.0.000"); - assertThat(output, is(equalTo(cqlLibrary))); - verify(hapiFhirServer, times(1)) - .findLibraryResourceInBundle(any(Bundle.class), any(Class.class)); - } - - @Test - void createLibraryResourceForCqlLibraryWhenDuplicateLibrary() { - String cql = getStringFromTestResource("/test-cql/EXM124v7QICore4.cql"); - CqlLibrary cqlLibrary = createCqlLibrary(cql); - when(hapiFhirServer.fetchLibraryBundleByNameAndVersion(anyString(), anyString())) - .thenReturn(bundle); - when(hapiFhirServer.findLibraryResourceInBundle(bundle, Library.class)) - .thenReturn(Optional.of(new Library())); - - Throwable exception = - assertThrows( - DuplicateLibraryException.class, - () -> libraryService.createLibraryResourceForCqlLibrary(cqlLibrary)); - String exceptionMessage = - String.format( - "Library resource with name: %s, version: %s already exists.", - cqlLibrary.getCqlLibraryName(), cqlLibrary.getVersion()); - assertEquals(exceptionMessage, exception.getMessage()); + "Cannot find CQL for library name: FHIRHelpers, version: 4.0.001", exception.getMessage()); } @Test @@ -242,12 +125,21 @@ public void testGetIncludedLibraries() { .setVersion("0.1.0") .setContent(List.of(attachment)); + CqlLibrary cqlLibrary = + CqlLibrary.builder() + .cqlLibraryName("IncludedLibrary") + .version(Version.builder().major(0).minor(1).revisionNumber(0).build()) + .build(); + when(libCqlVisitorFactory.visit(anyString())).thenReturn(visitor1).thenReturn(visitor2); - when(hapiFhirServer.fetchHapiLibrary(anyString(), anyString())) - .thenReturn(Optional.of(library)); + when(cqlLibraryService.getLibrary(anyString(), anyString(), anyString())) + .thenReturn(cqlLibrary); + when(libraryTranslatorService.convertToFhirLibrary(any(CqlLibrary.class), isNull())) + .thenReturn(library); Map includedLibraryMap = new HashMap<>(); - libraryService.getIncludedLibraries(mainLibrary, includedLibraryMap); + libraryService.getIncludedLibraries( + mainLibrary, includedLibraryMap, BundleUtil.MEASURE_BUNDLE_TYPE_EXPORT, "TOKEN"); assertThat(includedLibraryMap.size(), is(equalTo(1))); assertNotNull(includedLibraryMap.get("IncludedLibrary0.1.0")); } @@ -260,7 +152,9 @@ public void testGetIncludedLibrariesWhenBlankCql() { Exception exception = assertThrows( IllegalArgumentException.class, - () -> libraryService.getIncludedLibraries(mainLibrary, libraries)); + () -> + libraryService.getIncludedLibraries( + mainLibrary, libraries, BundleUtil.MEASURE_BUNDLE_TYPE_EXPORT, "TOKEN")); assertThat(exception.getMessage(), is(equalTo("Please provide valid arguments."))); } @@ -279,18 +173,19 @@ public void testGetIncludedLibrariesWhenIncludedLibraryNotInHapi() { var visitor2 = new LibraryCqlVisitorFactory().visit(includedLibrary); when(libCqlVisitorFactory.visit(anyString())).thenReturn(visitor1).thenReturn(visitor2); - when(hapiFhirServer.fetchHapiLibrary(anyString(), anyString())).thenReturn(Optional.empty()); + when(cqlLibraryService.getLibrary(anyString(), anyString(), anyString())) + .thenThrow(new CqlLibraryNotFoundException("Test Exception Here!", "0.1.000")); Map libraries = new HashMap<>(); Exception exception = assertThrows( - HapiLibraryNotFoundException.class, - () -> libraryService.getIncludedLibraries(mainLibrary, libraries)); + CqlLibraryNotFoundException.class, + () -> + libraryService.getIncludedLibraries( + mainLibrary, libraries, BundleUtil.MEASURE_BUNDLE_TYPE_EXPORT, "TOKEN")); assertThat( exception.getMessage(), - is( - equalTo( - "Cannot find a Hapi Fhir Library with name: IncludedLibrary, version: 0.1.000"))); + is(equalTo("Cannot find a CQL Library with name: Test Exception Here!, version: 0.1.000"))); } } diff --git a/src/test/java/gov/cms/madie/madiefhirservice/services/MeasureBundleServiceTest.java b/src/test/java/gov/cms/madie/madiefhirservice/services/MeasureBundleServiceTest.java index b82bd782..add35586 100644 --- a/src/test/java/gov/cms/madie/madiefhirservice/services/MeasureBundleServiceTest.java +++ b/src/test/java/gov/cms/madie/madiefhirservice/services/MeasureBundleServiceTest.java @@ -4,6 +4,7 @@ import ca.uhn.fhir.rest.api.MethodOutcome; import gov.cms.madie.madiefhirservice.constants.UriConstants; +import gov.cms.madie.madiefhirservice.exceptions.CqlLibraryNotFoundException; import gov.cms.madie.madiefhirservice.exceptions.HapiLibraryNotFoundException; import gov.cms.madie.madiefhirservice.hapi.HapiFhirServer; import gov.cms.madie.madiefhirservice.utils.BundleUtil; @@ -99,7 +100,7 @@ public void testCreateMeasureBundle() { return null; }) .when(libraryService) - .getIncludedLibraries(anyString(), anyMap()); + .getIncludedLibraries(anyString(), anyMap(), anyString(), anyString()); Bundle bundle = measureBundleService.createMeasureBundle( @@ -130,12 +131,12 @@ public void testCreateMeasureBundleWhenIncludedLibraryNotFoundInHapi() { when(libraryTranslatorService.convertToFhirLibrary( any(CqlLibrary.class), any(ProgramUseContext.class))) .thenReturn(library); - doThrow(new HapiLibraryNotFoundException("FHIRHelpers", "4.0.001")) + doThrow(new CqlLibraryNotFoundException("FHIRHelpers", "4.0.001")) .when(libraryService) - .getIncludedLibraries(anyString(), anyMap()); + .getIncludedLibraries(anyString(), any(), anyString(), anyString()); Exception exception = Assertions.assertThrows( - HapiLibraryNotFoundException.class, + CqlLibraryNotFoundException.class, () -> measureBundleService.createMeasureBundle( madieMeasure, @@ -145,7 +146,7 @@ public void testCreateMeasureBundleWhenIncludedLibraryNotFoundInHapi() { assertThat( exception.getMessage(), - is(equalTo("Cannot find a Hapi Fhir Library with name: FHIRHelpers, version: 4.0.001"))); + is(equalTo("Cannot find a CQL Library with name: FHIRHelpers, version: 4.0.001"))); } @Test @@ -177,7 +178,7 @@ public void testCreateMeasureBundleForExport() { return null; }) .when(libraryService) - .getIncludedLibraries(anyString(), anyMap()); + .getIncludedLibraries(anyString(), anyMap(), anyString(), anyString()); when(elmTranslatorClient.getEffectiveDataRequirements( any(Bundle.class), anyString(), anyString(), anyString()))