From 80117cc80a50acb4d46894c7add149794d7c7cb9 Mon Sep 17 00:00:00 2001 From: Steven Williams Date: Thu, 21 Mar 2024 10:50:30 -0400 Subject: [PATCH 1/3] Fix progress reporting - Report both `Patient` and initial data retrieval. - Don't preemptively round to the nearest cent. - Report to the nearest mille. --- .../com/lantanagroup/link/api/ReportGenerator.java | 4 ++-- .../link/query/uscore/PatientScoop.java | 14 ++++++++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/api/src/main/java/com/lantanagroup/link/api/ReportGenerator.java b/api/src/main/java/com/lantanagroup/link/api/ReportGenerator.java index 7bc375f8b..f8e32f765 100644 --- a/api/src/main/java/com/lantanagroup/link/api/ReportGenerator.java +++ b/api/src/main/java/com/lantanagroup/link/api/ReportGenerator.java @@ -80,8 +80,8 @@ public void generate(QueryPhase queryPhase) throws ExecutionException, Interrupt logger.error("Error generating measure report for patient {}", patient.getId(), e); } finally { int completed = progress.incrementAndGet(); - double percent = Math.round((completed * 100.0) / pois.size()); - logger.info("Progress ({}%) for report {} is {} of {}", String.format("%.2f", percent), reportContext.getMasterIdentifierValue(), completed, pois.size()); + double percent = (completed * 100.0) / pois.size(); + logger.info("Progress ({}%) for report {} is {} of {}", String.format("%.1f", percent), reportContext.getMasterIdentifierValue(), completed, pois.size()); } })) .get(); diff --git a/query/src/main/java/com/lantanagroup/link/query/uscore/PatientScoop.java b/query/src/main/java/com/lantanagroup/link/query/uscore/PatientScoop.java index 174bee1b8..977602eb4 100644 --- a/query/src/main/java/com/lantanagroup/link/query/uscore/PatientScoop.java +++ b/query/src/main/java/com/lantanagroup/link/query/uscore/PatientScoop.java @@ -164,8 +164,8 @@ public void loadInitialPatientData(ReportCriteria criteria, ReportContext contex logger.error("Unable to retrieve patient with identifier " + Helper.sanitizeString(poi.toString()), e); } finally { int completed = progress.incrementAndGet(); - double percent = Math.round((completed * 100.0) / patientsOfInterest.size()); - logger.info("Progress ({}%) for Initial Patient Data {} is {} of {}", String.format("%.2f", percent), context.getMasterIdentifierValue(), completed, patientsOfInterest.size()); + double percent = (completed * 100.0) / patientsOfInterest.size(); + logger.info("Progress ({}%) for Patient Resource {} is {} of {}", String.format("%.1f", percent), context.getMasterIdentifierValue(), completed, patientsOfInterest.size()); } return null; }).collect(Collectors.toList())).get(); @@ -174,6 +174,8 @@ public void loadInitialPatientData(ReportCriteria criteria, ReportContext contex return; } + progress.set(0); + try { // loop through the patient ids to retrieve the patientData using each patient. List patients = new ArrayList<>(patientMap.values()); @@ -188,6 +190,10 @@ public void loadInitialPatientData(ReportCriteria criteria, ReportContext contex } catch (Exception ex) { logger.error("Error loading patient data for patient {}: {}", patient.getId(), ex.getMessage(), ex); return null; + } finally { + int completed = progress.incrementAndGet(); + double percent = (completed * 100.0) / patients.size(); + logger.info("Progress ({}%) for Initial Patient Data {} is {} of {}", String.format("%.1f", percent), context.getMasterIdentifierValue(), completed, patients.size()); } this.storePatientData(criteria, context, patient.getIdElement().getIdPart(), patientData.getBundle()); @@ -217,8 +223,8 @@ public void loadSupplementalPatientData(ReportCriteria criteria, ReportContext c return null; } finally { int completed = progress.incrementAndGet(); - double percent = Math.round((completed * 100.0) / patientsOfInterest.size()); - logger.info("Progress ({}%) for Supplemental Patient Data {} is {} of {}", String.format("%.2f", percent), context.getMasterIdentifierValue(), completed, patientsOfInterest.size()); + double percent = (completed * 100.0) / patientsOfInterest.size(); + logger.info("Progress ({}%) for Supplemental Patient Data {} is {} of {}", String.format("%.1f", percent), context.getMasterIdentifierValue(), completed, patientsOfInterest.size()); } this.storePatientData(criteria, context, poi.getId(), patientData.getBundle()); From b0419678b2ed32018a1227aff77682e0d440752c Mon Sep 17 00:00:00 2001 From: Steven Williams Date: Thu, 21 Mar 2024 13:39:42 -0400 Subject: [PATCH 2/3] Fix unsafe publication Since `ReportContext` is accessed from both the main request-handling thread and thread-pool threads (e.g., during query and evaluation, which are parallelized across patients), its fields must be published safely in order to ensure proper visibility. --- .../link/model/ReportContext.java | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/core/src/main/java/com/lantanagroup/link/model/ReportContext.java b/core/src/main/java/com/lantanagroup/link/model/ReportContext.java index 727d1e505..74ecc7fa1 100644 --- a/core/src/main/java/com/lantanagroup/link/model/ReportContext.java +++ b/core/src/main/java/com/lantanagroup/link/model/ReportContext.java @@ -19,15 +19,15 @@ @Getter @Setter public class ReportContext { - private HttpServletRequest request; - private LinkCredentials user; - private String masterIdentifierValue; - private List patientLists = new ArrayList<>(); - private List patientsOfInterest = new ArrayList<>(); - private List measureContexts = new ArrayList<>(); - private QueryPlan queryPlan; - private IGenericClient client; - private List debugPatients = new ArrayList<>(); + private volatile HttpServletRequest request; + private volatile LinkCredentials user; + private volatile String masterIdentifierValue; + private volatile List patientLists = new ArrayList<>(); + private volatile List patientsOfInterest = new ArrayList<>(); + private volatile List measureContexts = new ArrayList<>(); + private volatile QueryPlan queryPlan; + private volatile IGenericClient client; + private volatile List debugPatients = new ArrayList<>(); public ReportContext() { } @@ -54,13 +54,13 @@ public List getPatientsOfInterest(QueryPhase queryPhase) @Getter @Setter public static class MeasureContext { - private String bundleId; - private Bundle reportDefBundle; - private Measure measure; - private String reportId; - private List patientsOfInterest = new ArrayList<>(); - private Map patientReportsByPatientId = new HashMap<>(); - private MeasureReport measureReport; + private volatile String bundleId; + private volatile Bundle reportDefBundle; + private volatile Measure measure; + private volatile String reportId; + private volatile List patientsOfInterest = new ArrayList<>(); + private volatile Map patientReportsByPatientId = new HashMap<>(); + private volatile MeasureReport measureReport; public List getPatientsOfInterest(QueryPhase queryPhase) { switch (queryPhase) { From 7d07583df6f3856020832243064c23d9da7cc9c2 Mon Sep 17 00:00:00 2001 From: Steven Williams Date: Thu, 21 Mar 2024 16:13:34 -0400 Subject: [PATCH 3/3] Remove IMRs from measure context This was causing `OutOfMemoryError`s for large ACH reports. To work around, store *only* POIs (not entire IMRs) to be evaluated in the supplemental phase. Then during aggregation, retrieve IMRs from the database since we don't have them lying around in memory. --- .../link/api/ReportGenerator.java | 7 ++-- .../lantanagroup/link/GenericAggregator.java | 22 ++++++++++--- .../lantanagroup/link/IReportAggregator.java | 3 +- .../link/model/ReportContext.java | 31 ++++++++---------- .../link/nhsn/ApplyConceptMapsTest.java | 2 +- .../link/nhsn/ReportAggregator.java | 29 ++++++++--------- .../link/nhsn/StoredListProvider.java | 4 +-- .../nhsn/EncounterStatusTransformerTest.java | 2 +- .../link/nhsn/ReportAggregatorTests.java | 32 +++++++++++++++---- 9 files changed, 81 insertions(+), 51 deletions(-) diff --git a/api/src/main/java/com/lantanagroup/link/api/ReportGenerator.java b/api/src/main/java/com/lantanagroup/link/api/ReportGenerator.java index f8e32f765..c7a920cb6 100644 --- a/api/src/main/java/com/lantanagroup/link/api/ReportGenerator.java +++ b/api/src/main/java/com/lantanagroup/link/api/ReportGenerator.java @@ -1,6 +1,7 @@ package com.lantanagroup.link.api; import com.lantanagroup.link.Constants; +import com.lantanagroup.link.FhirHelper; import com.lantanagroup.link.IReportAggregator; import com.lantanagroup.link.ReportIdHelper; import com.lantanagroup.link.config.api.ApiConfig; @@ -73,8 +74,8 @@ public void generate(QueryPhase queryPhase) throws ExecutionException, Interrupt } try { MeasureReport measureReport = generate(measureServiceWrapper, patient); - synchronized (this) { - measureContext.getPatientReportsByPatientId().put(patient.getId(), measureReport); + if (queryPhase == QueryPhase.INITIAL && FhirHelper.hasNonzeroPopulationCount(measureReport)) { + measureContext.getSupplementalPatientsOfInterest().add(patient); } } catch (Exception e) { logger.error("Error generating measure report for patient {}", patient.getId(), e); @@ -111,7 +112,7 @@ private MeasureReport generate(MeasureServiceWrapper measureServiceWrapper, Pati } public void aggregate() throws ParseException { - MeasureReport masterMeasureReport = this.reportAggregator.generate(this.criteria, this.measureContext); + MeasureReport masterMeasureReport = this.reportAggregator.generate(this.tenantService, this.criteria, this.measureContext); this.measureContext.setMeasureReport(masterMeasureReport); Aggregate aggregateReport = new Aggregate(); diff --git a/core/src/main/java/com/lantanagroup/link/GenericAggregator.java b/core/src/main/java/com/lantanagroup/link/GenericAggregator.java index 6e6bac5e6..46dbf3330 100644 --- a/core/src/main/java/com/lantanagroup/link/GenericAggregator.java +++ b/core/src/main/java/com/lantanagroup/link/GenericAggregator.java @@ -1,6 +1,9 @@ package com.lantanagroup.link; import com.lantanagroup.link.config.api.ApiConfig; +import com.lantanagroup.link.db.TenantService; +import com.lantanagroup.link.db.model.PatientMeasureReport; +import com.lantanagroup.link.model.PatientOfInterestModel; import com.lantanagroup.link.model.ReportContext; import com.lantanagroup.link.model.ReportCriteria; import org.apache.commons.lang3.StringUtils; @@ -11,7 +14,6 @@ import org.springframework.beans.factory.annotation.Autowired; import java.text.ParseException; -import java.util.Collection; import java.util.Optional; public abstract class GenericAggregator implements IReportAggregator { @@ -20,10 +22,12 @@ public abstract class GenericAggregator implements IReportAggregator { @Autowired private ApiConfig config; - protected abstract void aggregatePatientReports(MeasureReport masterMeasureReport, Collection measureReports); + protected abstract void aggregatePatientReport(MeasureReport masterMeasureReport, MeasureReport measureReport); + + protected abstract void finishAggregation(MeasureReport masterMeasureReport); @Override - public MeasureReport generate(ReportCriteria criteria, ReportContext.MeasureContext measureContext) throws ParseException { + public MeasureReport generate(TenantService tenantService, ReportCriteria criteria, ReportContext.MeasureContext measureContext) throws ParseException { // Create the master measure report MeasureReport masterMeasureReport = new MeasureReport(); masterMeasureReport.setId(measureContext.getReportId()); @@ -39,8 +43,16 @@ public MeasureReport generate(ReportCriteria criteria, ReportContext.MeasureCont masterMeasureReport.setMeasure(measureContext.getMeasure().getUrl()); } - // TODO: Swap the order of aggregatePatientReports and createGroupsFromMeasure? - this.aggregatePatientReports(masterMeasureReport, measureContext.getPatientReports()); + for (PatientOfInterestModel poi : measureContext.getPatientsOfInterest()) { + String pmrId = ReportIdHelper.getPatientMeasureReportId(measureContext.getReportId(), poi.getId()); + PatientMeasureReport pmr = tenantService.getPatientMeasureReport(pmrId); + if (pmr == null) { + logger.warn("Patient measure report not found in database: {}", pmrId); + continue; + } + this.aggregatePatientReport(masterMeasureReport, pmr.getMeasureReport()); + } + this.finishAggregation(masterMeasureReport); this.createGroupsFromMeasure(masterMeasureReport, measureContext); diff --git a/core/src/main/java/com/lantanagroup/link/IReportAggregator.java b/core/src/main/java/com/lantanagroup/link/IReportAggregator.java index 2bc5d18d7..bd01a3e0d 100644 --- a/core/src/main/java/com/lantanagroup/link/IReportAggregator.java +++ b/core/src/main/java/com/lantanagroup/link/IReportAggregator.java @@ -1,5 +1,6 @@ package com.lantanagroup.link; +import com.lantanagroup.link.db.TenantService; import com.lantanagroup.link.model.ReportContext; import com.lantanagroup.link.model.ReportCriteria; import org.hl7.fhir.r4.model.MeasureReport; @@ -7,5 +8,5 @@ import java.text.ParseException; public interface IReportAggregator { - MeasureReport generate(ReportCriteria criteria, ReportContext.MeasureContext measureContext) throws ParseException; + MeasureReport generate(TenantService tenantService, ReportCriteria criteria, ReportContext.MeasureContext measureContext) throws ParseException; } diff --git a/core/src/main/java/com/lantanagroup/link/model/ReportContext.java b/core/src/main/java/com/lantanagroup/link/model/ReportContext.java index 74ecc7fa1..b4b66c19e 100644 --- a/core/src/main/java/com/lantanagroup/link/model/ReportContext.java +++ b/core/src/main/java/com/lantanagroup/link/model/ReportContext.java @@ -1,7 +1,6 @@ package com.lantanagroup.link.model; import ca.uhn.fhir.rest.client.api.IGenericClient; -import com.lantanagroup.link.FhirHelper; import com.lantanagroup.link.auth.LinkCredentials; import com.lantanagroup.link.db.model.PatientList; import com.lantanagroup.link.db.model.tenant.QueryPlan; @@ -23,7 +22,7 @@ public class ReportContext { private volatile LinkCredentials user; private volatile String masterIdentifierValue; private volatile List patientLists = new ArrayList<>(); - private volatile List patientsOfInterest = new ArrayList<>(); + private volatile List initialPatientsOfInterest = new ArrayList<>(); private volatile List measureContexts = new ArrayList<>(); private volatile QueryPlan queryPlan; private volatile IGenericClient client; @@ -37,10 +36,14 @@ public ReportContext(HttpServletRequest request, LinkCredentials user) { this.user = user; } + public List getPatientsOfInterest() { + return initialPatientsOfInterest; + } + public List getPatientsOfInterest(QueryPhase queryPhase) { switch (queryPhase) { case INITIAL: - return patientsOfInterest; + return initialPatientsOfInterest; case SUPPLEMENTAL: return measureContexts.stream() .flatMap(measureContext -> measureContext.getPatientsOfInterest(queryPhase).stream()) @@ -58,29 +61,23 @@ public static class MeasureContext { private volatile Bundle reportDefBundle; private volatile Measure measure; private volatile String reportId; - private volatile List patientsOfInterest = new ArrayList<>(); - private volatile Map patientReportsByPatientId = new HashMap<>(); + private volatile List initialPatientsOfInterest = new ArrayList<>(); + private volatile List supplementalPatientsOfInterest = Collections.synchronizedList(new ArrayList<>()); private volatile MeasureReport measureReport; + public List getPatientsOfInterest() { + return initialPatientsOfInterest; + } + public List getPatientsOfInterest(QueryPhase queryPhase) { switch (queryPhase) { case INITIAL: - return patientsOfInterest; + return initialPatientsOfInterest; case SUPPLEMENTAL: - Set patientIds = patientReportsByPatientId.entrySet().stream() - .filter(reportById -> FhirHelper.hasNonzeroPopulationCount(reportById.getValue())) - .map(Map.Entry::getKey) - .collect(Collectors.toSet()); - return patientsOfInterest.stream() - .filter(poi -> patientIds.contains(poi.getId())) - .collect(Collectors.toList()); + return supplementalPatientsOfInterest; default: throw new IllegalArgumentException(queryPhase.toString()); } } - - public Collection getPatientReports() { - return patientReportsByPatientId.values(); - } } } diff --git a/core/src/test/java/com/lantanagroup/link/nhsn/ApplyConceptMapsTest.java b/core/src/test/java/com/lantanagroup/link/nhsn/ApplyConceptMapsTest.java index 3cd5918be..3c2edd2d7 100644 --- a/core/src/test/java/com/lantanagroup/link/nhsn/ApplyConceptMapsTest.java +++ b/core/src/test/java/com/lantanagroup/link/nhsn/ApplyConceptMapsTest.java @@ -95,7 +95,7 @@ public void testExecute() { model.setId("10000"); patientOfInterestModel.add(model); - context.setPatientsOfInterest(patientOfInterestModel); + context.setInitialPatientsOfInterest(patientOfInterestModel); List codes = new ArrayList<>(); codes.add(getLocation().getType().get(0).getCoding().get(0)); diff --git a/nhsn/src/main/java/com/lantanagroup/link/nhsn/ReportAggregator.java b/nhsn/src/main/java/com/lantanagroup/link/nhsn/ReportAggregator.java index 621e6a98f..2917c152b 100644 --- a/nhsn/src/main/java/com/lantanagroup/link/nhsn/ReportAggregator.java +++ b/nhsn/src/main/java/com/lantanagroup/link/nhsn/ReportAggregator.java @@ -9,7 +9,6 @@ import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; -import java.util.Collection; import java.util.Optional; @Component @@ -38,23 +37,23 @@ protected void addSubjectResult( "MeasureReport/" + individualMeasureReport.getIdElement().getIdPart()); } - public void aggregatePatientReports(MeasureReport masterMeasureReport, Collection measureReports) { - // aggregate all individual reports in ones - for (MeasureReport patientMeasureReportResource : measureReports) { - for (MeasureReport.MeasureReportGroupComponent group : patientMeasureReportResource.getGroup()) { - for (MeasureReport.MeasureReportGroupPopulationComponent population : group.getPopulation()) { - // Check if group and population code exist in master, if not create - MeasureReport.MeasureReportGroupPopulationComponent measureGroupPopulation = getOrCreateGroupAndPopulation(masterMeasureReport, population, group); - // Add population.count to the master group/population count - measureGroupPopulation.setCount(measureGroupPopulation.getCount() + population.getCount()); - // If this population incremented the master - if (population.getCount() > 0) { - // add subject results - addSubjectResult(patientMeasureReportResource, measureGroupPopulation); - } + public void aggregatePatientReport(MeasureReport masterMeasureReport, MeasureReport measureReport) { + for (MeasureReport.MeasureReportGroupComponent group : measureReport.getGroup()) { + for (MeasureReport.MeasureReportGroupPopulationComponent population : group.getPopulation()) { + // Check if group and population code exist in master, if not create + MeasureReport.MeasureReportGroupPopulationComponent measureGroupPopulation = getOrCreateGroupAndPopulation(masterMeasureReport, population, group); + // Add population.count to the master group/population count + measureGroupPopulation.setCount(measureGroupPopulation.getCount() + population.getCount()); + // If this population incremented the master + if (population.getCount() > 0) { + // add subject results + addSubjectResult(measureReport, measureGroupPopulation); } } } + } + + public void finishAggregation(MeasureReport masterMeasureReport) { for (MeasureReport.MeasureReportGroupComponent group : masterMeasureReport.getGroup()) { for (MeasureReport.MeasureReportGroupPopulationComponent population : group.getPopulation()) { logger.debug( diff --git a/nhsn/src/main/java/com/lantanagroup/link/nhsn/StoredListProvider.java b/nhsn/src/main/java/com/lantanagroup/link/nhsn/StoredListProvider.java index c6e63ba2e..361c69c6e 100644 --- a/nhsn/src/main/java/com/lantanagroup/link/nhsn/StoredListProvider.java +++ b/nhsn/src/main/java/com/lantanagroup/link/nhsn/StoredListProvider.java @@ -54,9 +54,9 @@ public void loadPatientsOfInterest(TenantService tenantService, ReportCriteria c Collector> deduplicator = Collectors.toMap(PatientOfInterestModel::toString, Function.identity(), (poi1, poi2) -> poi1); Map poiMap = context.getPatientsOfInterest().stream().collect(deduplicator); - context.setPatientsOfInterest(new ArrayList<>(poiMap.values())); + context.setInitialPatientsOfInterest(new ArrayList<>(poiMap.values())); for (ReportContext.MeasureContext measureContext : context.getMeasureContexts()) { - measureContext.setPatientsOfInterest(measureContext.getPatientsOfInterest().stream() + measureContext.setInitialPatientsOfInterest(measureContext.getPatientsOfInterest().stream() .collect(deduplicator) .values().stream() .map(poi -> poiMap.get(poi.toString())) diff --git a/nhsn/src/test/java/com/lantanagroup/link/nhsn/EncounterStatusTransformerTest.java b/nhsn/src/test/java/com/lantanagroup/link/nhsn/EncounterStatusTransformerTest.java index 5ce69bc43..d3a449959 100644 --- a/nhsn/src/test/java/com/lantanagroup/link/nhsn/EncounterStatusTransformerTest.java +++ b/nhsn/src/test/java/com/lantanagroup/link/nhsn/EncounterStatusTransformerTest.java @@ -58,7 +58,7 @@ public void execute() throws ParseException { patientOfInterest.setId(patientID); List patientsOfInterest = new ArrayList<>(); patientsOfInterest.add(patientOfInterest); - context.setPatientsOfInterest(patientsOfInterest); + context.setInitialPatientsOfInterest(patientsOfInterest); context.setMasterIdentifierValue(reportID); String bundleId = ReportIdHelper.getPatientDataBundleId(context.getMasterIdentifierValue(), patientOfInterest.getId()); diff --git a/nhsn/src/test/java/com/lantanagroup/link/nhsn/ReportAggregatorTests.java b/nhsn/src/test/java/com/lantanagroup/link/nhsn/ReportAggregatorTests.java index 421324c84..0ba931026 100644 --- a/nhsn/src/test/java/com/lantanagroup/link/nhsn/ReportAggregatorTests.java +++ b/nhsn/src/test/java/com/lantanagroup/link/nhsn/ReportAggregatorTests.java @@ -1,5 +1,9 @@ package com.lantanagroup.link.nhsn; +import com.lantanagroup.link.ReportIdHelper; +import com.lantanagroup.link.db.TenantService; +import com.lantanagroup.link.db.model.PatientMeasureReport; +import com.lantanagroup.link.model.PatientOfInterestModel; import com.lantanagroup.link.model.ReportContext; import com.lantanagroup.link.model.ReportCriteria; import org.hl7.fhir.r4.model.*; @@ -9,6 +13,9 @@ import java.text.ParseException; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + public class ReportAggregatorTests { private Bundle getReportDefBundle() { Bundle measureDefBundle = new Bundle(); @@ -36,12 +43,21 @@ private ReportContext.MeasureContext getMeasureContext(String version) { context.getMeasure().setUrl("http://test.com/fhir/Measure/SomeMeasure"); context.getMeasure().setVersion(version); context.setReportDefBundle(this.getReportDefBundle()); - context.getPatientReportsByPatientId().put("test-patient1", this.getPatientMeasureReport("test-patient1", 1)); - context.getPatientReportsByPatientId().put("test-patient2", this.getPatientMeasureReport("test-patient2", 2)); - context.getPatientReportsByPatientId().put("test-patient3", this.getPatientMeasureReport("test-patient3", 0)); + context.setReportId("abc123"); return context; } + private void addPatientOfInterest(ReportContext.MeasureContext context, TenantService tenantService, String patientId, int populationCount) { + PatientOfInterestModel poi = new PatientOfInterestModel(); + poi.setReference("Patient/" + patientId); + poi.setId(patientId); + context.getPatientsOfInterest().add(poi); + String pmrId = ReportIdHelper.getPatientMeasureReportId(context.getReportId(), patientId); + PatientMeasureReport pmr = new PatientMeasureReport(); + pmr.setMeasureReport(this.getPatientMeasureReport(patientId, populationCount)); + when(tenantService.getPatientMeasureReport(pmrId)).thenReturn(pmr); + } + @Test public void aggregationWithoutMeasureVersionTest() throws ParseException { ReportContext.MeasureContext context = this.getMeasureContext(null); @@ -50,7 +66,7 @@ public void aggregationWithoutMeasureVersionTest() throws ParseException { "2023-08-22T00:00:00Z", "2023-08-22T23:59:59Z"); ReportAggregator aggregator = new ReportAggregator(); - MeasureReport aggregate = aggregator.generate(criteria, context); + MeasureReport aggregate = aggregator.generate(mock(TenantService.class), criteria, context); Assert.assertEquals("http://test.com/fhir/Measure/SomeMeasure", aggregate.getMeasure()); } @@ -62,7 +78,7 @@ public void aggregationWithMeasureVersionTest() throws ParseException { "2023-08-22T00:00:00Z", "2023-08-22T23:59:59Z"); ReportAggregator aggregator = new ReportAggregator(); - MeasureReport aggregate = aggregator.generate(criteria, context); + MeasureReport aggregate = aggregator.generate(mock(TenantService.class), criteria, context); Assert.assertEquals("http://test.com/fhir/Measure/SomeMeasure|1.0.1", aggregate.getMeasure()); } @@ -74,7 +90,11 @@ public void aggregationCountTest() throws ParseException { "2023-08-22T00:00:00Z", "2023-08-22T23:59:59Z"); ReportAggregator aggregator = new ReportAggregator(); - MeasureReport aggregate = aggregator.generate(criteria, context); + TenantService tenantService = mock(TenantService.class); + addPatientOfInterest(context, tenantService, "test-patient1", 1); + addPatientOfInterest(context, tenantService, "test-patient2", 2); + addPatientOfInterest(context, tenantService, "test-patient3", 0); + MeasureReport aggregate = aggregator.generate(tenantService, criteria, context); Assert.assertEquals(MeasurePopulation.INITIALPOPULATION.toCode(), aggregate.getGroupFirstRep().getPopulationFirstRep().getCode().getCodingFirstRep().getCode()); Assert.assertEquals(3, aggregate.getGroupFirstRep().getPopulationFirstRep().getCount()); }