Skip to content

Commit

Permalink
Merge pull request #156 from MeasureAuthoringTool/MAT-6103_OrderingPa…
Browse files Browse the repository at this point in the history
…rametersInHR

Mat 6103 ordering parameters in Human Readable
  • Loading branch information
gregory-akins authored Sep 14, 2023
2 parents dccf467 + f6181a7 commit 9d162e9
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 21 deletions.
Original file line number Diff line number Diff line change
@@ -1,31 +1,41 @@
package gov.cms.madie.madiefhirservice.services;

import gov.cms.madie.madiefhirservice.constants.UriConstants.CqfMeasures;
import gov.cms.madie.madiefhirservice.exceptions.HumanReadableGenerationException;
import gov.cms.madie.madiefhirservice.exceptions.ResourceNotFoundException;
import gov.cms.madie.madiefhirservice.utils.ResourceUtils;
import gov.cms.madie.models.measure.Measure;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import static org.springframework.web.util.HtmlUtils.htmlEscape;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

import org.hl7.fhir.convertors.advisors.impl.BaseAdvisor_40_50;
import org.hl7.fhir.convertors.conv40_50.VersionConvertor_40_50;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.Library;
import org.hl7.fhir.r4.model.Resource;
import org.hl7.fhir.r5.model.Enumerations.FHIRTypes;
import org.hl7.fhir.r5.model.Expression;
import org.hl7.fhir.r5.model.Extension;
import org.hl7.fhir.r5.model.ParameterDefinition;
import org.hl7.fhir.r5.model.RelatedArtifact;
import org.hl7.fhir.r5.model.StringType;
import org.hl7.fhir.r5.utils.LiquidEngine;
import org.springframework.stereotype.Service;
import java.util.List;
import static org.springframework.web.util.HtmlUtils.htmlEscape;

import gov.cms.madie.madiefhirservice.constants.UriConstants.CqfMeasures;
import gov.cms.madie.madiefhirservice.exceptions.HumanReadableGenerationException;
import gov.cms.madie.madiefhirservice.exceptions.ResourceNotFoundException;
import gov.cms.madie.madiefhirservice.utils.ResourceUtils;
import gov.cms.madie.models.measure.Measure;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
@RequiredArgsConstructor
public class HumanReadableService extends ResourceUtils {


private final LiquidEngine liquidEngine;

Expand All @@ -49,7 +59,7 @@ private void escapeTopLevelProperties(org.hl7.fhir.r5.model.Measure measure) {
}

private void escapeSupplementalProperties(org.hl7.fhir.r5.model.Measure measure) {
// supplemental data Elements
// supplemental data Elements
measure
.getSupplementalData()
.forEach(
Expand Down Expand Up @@ -80,7 +90,7 @@ public void escapeContainedProperties(org.hl7.fhir.r5.model.Measure measure) {
escapeStr(innerExtension.getValue().primitiveValue())));
});
});
// population criteria
// population criteria
relatedArtifacts.forEach(
relatedArtifact -> {
relatedArtifact.setLabel(escapeStr(relatedArtifact.getLabel()));
Expand All @@ -95,7 +105,7 @@ public org.hl7.fhir.r5.model.Measure escapeMeasure(org.hl7.fhir.r5.model.Measure
escapeTopLevelProperties(measure);
escapeSupplementalProperties(measure);
escapeContainedProperties(measure);
// logic definitions, effective data requirements
// logic definitions, effective data requirements
// risk factors and supplemental data guidance
measure
.getExtension()
Expand Down Expand Up @@ -153,8 +163,10 @@ public String generateMeasureHumanReadable(
var versionConvertor_40_50 = new VersionConvertor_40_50(new BaseAdvisor_40_50());
org.hl7.fhir.r5.model.Measure r5Measure =
(org.hl7.fhir.r5.model.Measure) versionConvertor_40_50.convertResource(measureResource);

// sort effectiveDataRequirements.parameters
sortParameters(madieMeasure, effectiveDataRequirements);
r5Measure.addContained(effectiveDataRequirements);

r5Measure.getExtension().add(createEffectiveDataRequirementExtension());
// escape html
org.hl7.fhir.r5.model.Measure escapedR5Measure = escapeMeasure(r5Measure);
Expand All @@ -171,6 +183,75 @@ public String generateMeasureHumanReadable(
}
}

private void sortParameters(
Measure madieMeasure, org.hl7.fhir.r5.model.Library effectiveDataRequirements) {
List<String> suppDataDefs =
madieMeasure.getSupplementalData().stream()
.map((s) -> s.getDefinition())
.collect(Collectors.toList());
List<String> riskAdjDefs =
madieMeasure.getRiskAdjustments().stream()
.map((s) -> s.getDefinition())
.collect(Collectors.toList());
List<String> strats = new ArrayList<String>();
if (madieMeasure.getGroups() != null) {
madieMeasure.getGroups().stream()
.forEach(
(g) ->
strats.addAll(
g.getStratifications().stream()
.map(s -> s.getCqlDefinition())
.collect(Collectors.toList())));
}

Collections.sort(
effectiveDataRequirements.getParameter(),
new Comparator<ParameterDefinition>() {

@Override
public int compare(ParameterDefinition o1, ParameterDefinition o2) {

int ord1 = determineOrd(o1, suppDataDefs, riskAdjDefs, strats);
int ord2 = determineOrd(o2, suppDataDefs, riskAdjDefs, strats);

int result = ord1 - ord2;
return result;
}
});
}

private int determineOrd(
ParameterDefinition paramDef,
List<String> suppDataDefs,
List<String> riskAdjDefs,
List<String> strats) {
int result = 1; // default = 1

// if paramDef is a period, then ord = 0
if (paramDef != null
&& paramDef.getType() != null
&& paramDef.getType().toCode().equals(FHIRTypes.PERIOD.toCode())) {
result = 0;
}
// if paramDef is a supp data then ord = 2
if (paramDef != null && suppDataDefs.contains(paramDef.getName())) {
result = 2;
}

// if paramDef is a risk adjustment data then ord = 3
if (paramDef != null && riskAdjDefs.contains(paramDef.getName())) {
result = 3;
}

// if paramDef is a stratification data then ord = 4
if (paramDef != null && strats.contains(paramDef.getName())) {
result = 4;
}

// if paramDef is anything else then ord = 1
return result;
}

/**
* Generate human-readable for a library
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.hl7.fhir.r4.model.Library;
import org.hl7.fhir.r4.model.Period;
import org.hl7.fhir.r4.model.Resource;
import org.hl7.fhir.r5.model.ParameterDefinition;
import org.hl7.fhir.r5.utils.LiquidEngine;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
Expand All @@ -30,6 +31,7 @@
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
Expand Down Expand Up @@ -134,6 +136,43 @@ public void generateMeasureHumanReadable() {
assertTrue(generatedHumanReadable.contains(hrText));
}

@Test
public void generateMeasureHumanReadableOrdered() {
Bundle.BundleEntryComponent measureBundleEntryComponent = getBundleEntryComponent(measure);
Bundle.BundleEntryComponent libraryBundleEntryComponent = getBundleEntryComponent(library);
Bundle bundle =
new Bundle()
.setType(Bundle.BundleType.TRANSACTION)
.addEntry(measureBundleEntryComponent)
.addEntry(libraryBundleEntryComponent);

String hrText = "<div>Human Readable for Measure: " + madieMeasure.getMeasureName() + "</div>";

when(liquidEngine.parse(anyString(), anyString()))
.thenReturn(new LiquidEngine.LiquidDocument());

when(liquidEngine.evaluate(
any(LiquidEngine.LiquidDocument.class),
argThat(
(measure) -> {
org.hl7.fhir.r5.model.Measure m = (org.hl7.fhir.r5.model.Measure) measure;

org.hl7.fhir.r5.model.Library library =
(org.hl7.fhir.r5.model.Library) m.getContained().get(0);
ParameterDefinition paramDef = library.getParameter().get(0);

return "Period".equals(paramDef.getType().toCode());
}),
any()))
.thenReturn(hrText);

String generatedHumanReadable =
humanReadableService.generateMeasureHumanReadable(
madieMeasure, bundle, effectiveDataRequirements);
assertNotNull(generatedHumanReadable);
assertTrue(generatedHumanReadable.contains(hrText));
}

@Test
public void generateHumanReadableThrowsResourceNotFoundExceptionForNoBundle() {
assertThrows(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,19 +134,20 @@
"display": "Library FHIRHelpers",
"resource": "Library/FHIRHelpers|4.1.000"
} ],
"parameter": [ {
"name": "Measurement Period",
"use": "in",
"min": 0,
"max": "1",
"type": "Period"
}, {
"parameter": [ {
"name": "boolDenom",
"use": "out",
"min": 0,
"max": "1",
"type": "boolean"
}, {
},{
"name": "Measurement Period",
"use": "in",
"min": 0,
"max": "1",
"type": "Period"
},
{
"name": "ex",
"use": "out",
"min": 0,
Expand Down

0 comments on commit 9d162e9

Please sign in to comment.