collect-data and data-requirements operations and tests (#5854)

* collect-data and data-requirements operations and tests

* remove unused imports

* additional test coverage

* move assertions out of method to pass static code analysis

* camelCase test names

* remove underscore on test methods

* requested edits to changelog

* version bump to 7.1.10-SNAPSHOT

* condense unit tests to prevent pipeline timeout

* method camel case naming
This commit is contained in:
Justin McKelvy 2024-04-18 16:34:26 -06:00 committed by GitHub
parent a90ccde71c
commit e400db5fb8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
92 changed files with 598 additions and 285 deletions

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId> <artifactId>hapi-fhir</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-bom</artifactId> <artifactId>hapi-fhir-bom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<name>HAPI FHIR BOM</name> <name>HAPI FHIR BOM</name>
@ -12,7 +12,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId> <artifactId>hapi-fhir</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-cli</artifactId> <artifactId>hapi-fhir-cli</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId> <artifactId>hapi-fhir</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId> <artifactId>hapi-fhir</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -0,0 +1,6 @@
---
type: add
issue: 5850
title: "Add additional Clinical Reasoning operations $collect-data and $data-requirements to HAPI-FHIR to expand capability
for clinical reasoning module users. These operations will assist users in identifying data requirements for evaluating a measure, and what
data was used for a measure evaluation"

View File

@ -11,7 +11,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -3,7 +3,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -3,7 +3,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId> <artifactId>hapi-fhir</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -7,7 +7,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -7,7 +7,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -123,7 +123,8 @@ public class ProviderConstants {
public static final String CR_OPERATION_EXTRACT = "$extract"; public static final String CR_OPERATION_EXTRACT = "$extract";
public static final String CR_OPERATION_PACKAGE = "$package"; public static final String CR_OPERATION_PACKAGE = "$package";
public static final String CR_OPERATION_QUESTIONNAIRE = "$questionnaire"; public static final String CR_OPERATION_QUESTIONNAIRE = "$questionnaire";
public static final String CR_OPERATION_COLLECTDATA = "$collect-data";
public static final String CR_OPERATION_DATAREQUIREMENTS = "$data-requirements";
/** /**
* Operation name for the $meta operation * Operation name for the $meta operation
*/ */

View File

@ -7,7 +7,7 @@
<parent> <parent>
<artifactId>hapi-fhir-serviceloaders</artifactId> <artifactId>hapi-fhir-serviceloaders</artifactId>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -7,7 +7,7 @@
<parent> <parent>
<artifactId>hapi-fhir-serviceloaders</artifactId> <artifactId>hapi-fhir-serviceloaders</artifactId>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
@ -21,7 +21,7 @@
<dependency> <dependency>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-caching-api</artifactId> <artifactId>hapi-fhir-caching-api</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -7,7 +7,7 @@
<parent> <parent>
<artifactId>hapi-fhir-serviceloaders</artifactId> <artifactId>hapi-fhir-serviceloaders</artifactId>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -7,7 +7,7 @@
<parent> <parent>
<artifactId>hapi-fhir</artifactId> <artifactId>hapi-fhir</artifactId>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath> <relativePath>../../pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-spring-boot-samples</artifactId> <artifactId>hapi-fhir-spring-boot-samples</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
</parent> </parent>
<artifactId>hapi-fhir-spring-boot-sample-client-apache</artifactId> <artifactId>hapi-fhir-spring-boot-sample-client-apache</artifactId>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-spring-boot-samples</artifactId> <artifactId>hapi-fhir-spring-boot-samples</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-spring-boot-samples</artifactId> <artifactId>hapi-fhir-spring-boot-samples</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-spring-boot</artifactId> <artifactId>hapi-fhir-spring-boot</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId> <artifactId>hapi-fhir</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -7,7 +7,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -7,7 +7,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -7,7 +7,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -26,13 +26,17 @@ import ca.uhn.fhir.cr.config.ProviderLoader;
import ca.uhn.fhir.cr.config.ProviderSelector; import ca.uhn.fhir.cr.config.ProviderSelector;
import ca.uhn.fhir.cr.config.RepositoryConfig; import ca.uhn.fhir.cr.config.RepositoryConfig;
import ca.uhn.fhir.cr.r4.ICareGapsServiceFactory; import ca.uhn.fhir.cr.r4.ICareGapsServiceFactory;
import ca.uhn.fhir.cr.r4.ICollectDataServiceFactory;
import ca.uhn.fhir.cr.r4.ICqlExecutionServiceFactory; import ca.uhn.fhir.cr.r4.ICqlExecutionServiceFactory;
import ca.uhn.fhir.cr.r4.IDataRequirementsServiceFactory;
import ca.uhn.fhir.cr.r4.ILibraryEvaluationServiceFactory; import ca.uhn.fhir.cr.r4.ILibraryEvaluationServiceFactory;
import ca.uhn.fhir.cr.r4.IMeasureServiceFactory; import ca.uhn.fhir.cr.r4.IMeasureServiceFactory;
import ca.uhn.fhir.cr.r4.ISubmitDataProcessorFactory; import ca.uhn.fhir.cr.r4.ISubmitDataProcessorFactory;
import ca.uhn.fhir.cr.r4.cpg.CqlExecutionOperationProvider; import ca.uhn.fhir.cr.r4.cpg.CqlExecutionOperationProvider;
import ca.uhn.fhir.cr.r4.cpg.LibraryEvaluationOperationProvider; import ca.uhn.fhir.cr.r4.cpg.LibraryEvaluationOperationProvider;
import ca.uhn.fhir.cr.r4.measure.CareGapsOperationProvider; import ca.uhn.fhir.cr.r4.measure.CareGapsOperationProvider;
import ca.uhn.fhir.cr.r4.measure.CollectDataOperationProvider;
import ca.uhn.fhir.cr.r4.measure.DataRequirementsOperationProvider;
import ca.uhn.fhir.cr.r4.measure.MeasureOperationsProvider; import ca.uhn.fhir.cr.r4.measure.MeasureOperationsProvider;
import ca.uhn.fhir.cr.r4.measure.SubmitDataProvider; import ca.uhn.fhir.cr.r4.measure.SubmitDataProvider;
import ca.uhn.fhir.rest.server.RestfulServer; import ca.uhn.fhir.rest.server.RestfulServer;
@ -42,6 +46,8 @@ import org.opencds.cqf.fhir.cr.cpg.r4.R4LibraryEvaluationService;
import org.opencds.cqf.fhir.cr.measure.CareGapsProperties; import org.opencds.cqf.fhir.cr.measure.CareGapsProperties;
import org.opencds.cqf.fhir.cr.measure.MeasureEvaluationOptions; import org.opencds.cqf.fhir.cr.measure.MeasureEvaluationOptions;
import org.opencds.cqf.fhir.cr.measure.r4.R4CareGapsService; import org.opencds.cqf.fhir.cr.measure.r4.R4CareGapsService;
import org.opencds.cqf.fhir.cr.measure.r4.R4CollectDataService;
import org.opencds.cqf.fhir.cr.measure.r4.R4DataRequirementsService;
import org.opencds.cqf.fhir.cr.measure.r4.R4MeasureService; import org.opencds.cqf.fhir.cr.measure.r4.R4MeasureService;
import org.opencds.cqf.fhir.cr.measure.r4.R4SubmitDataService; import org.opencds.cqf.fhir.cr.measure.r4.R4SubmitDataService;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
@ -86,6 +92,28 @@ public class CrR4Config {
return new CqlExecutionOperationProvider(); return new CqlExecutionOperationProvider();
} }
@Bean
CollectDataOperationProvider r4CollectDataOperationProvider() {
return new CollectDataOperationProvider();
}
@Bean
ICollectDataServiceFactory collectDataServiceFactory(
IRepositoryFactory theRepositoryFactory, MeasureEvaluationOptions theMeasureEvaluationOptions) {
return rd -> new R4CollectDataService(theRepositoryFactory.create(rd), theMeasureEvaluationOptions);
}
@Bean
DataRequirementsOperationProvider r4DataRequirementsOperationProvider() {
return new DataRequirementsOperationProvider();
}
@Bean
IDataRequirementsServiceFactory dataRequirementsServiceFactory(
IRepositoryFactory theRepositoryFactory, MeasureEvaluationOptions theMeasureEvaluationOptions) {
return rd -> new R4DataRequirementsService(theRepositoryFactory.create(rd), theMeasureEvaluationOptions);
}
@Bean @Bean
LibraryEvaluationOperationProvider r4LibraryEvaluationOperationProvider() { LibraryEvaluationOperationProvider r4LibraryEvaluationOperationProvider() {
return new LibraryEvaluationOperationProvider(); return new LibraryEvaluationOperationProvider();
@ -132,7 +160,9 @@ public class CrR4Config {
SubmitDataProvider.class, SubmitDataProvider.class,
CareGapsOperationProvider.class, CareGapsOperationProvider.class,
CqlExecutionOperationProvider.class, CqlExecutionOperationProvider.class,
LibraryEvaluationOperationProvider.class))); LibraryEvaluationOperationProvider.class,
CollectDataOperationProvider.class,
DataRequirementsOperationProvider.class)));
return new ProviderLoader(theRestfulServer, theApplicationContext, selector); return new ProviderLoader(theRestfulServer, theApplicationContext, selector);
} }

View File

@ -0,0 +1,9 @@
package ca.uhn.fhir.cr.r4;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import org.opencds.cqf.fhir.cr.measure.r4.R4CollectDataService;
@FunctionalInterface
public interface ICollectDataServiceFactory {
R4CollectDataService create(RequestDetails theRequestDetails);
}

View File

@ -0,0 +1,9 @@
package ca.uhn.fhir.cr.r4;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import org.opencds.cqf.fhir.cr.measure.r4.R4DataRequirementsService;
@FunctionalInterface
public interface IDataRequirementsServiceFactory {
R4DataRequirementsService create(RequestDetails theRequestDetails);
}

View File

@ -113,7 +113,7 @@ public class CqlExecutionOperationProvider {
* is a CQL system-defined or FHIR-defined type, the result is returned * is a CQL system-defined or FHIR-defined type, the result is returned
* as a {@link Parameters} Parameters resource * as a {@link Parameters} Parameters resource
*/ */
@Operation(name = ProviderConstants.CR_OPERATION_CQL) @Operation(name = ProviderConstants.CR_OPERATION_CQL, idempotent = true)
@Description( @Description(
shortDefinition = "$cql", shortDefinition = "$cql",
value = value =
@ -145,6 +145,6 @@ public class CqlExecutionOperationProvider {
theDataEndpoint, theDataEndpoint,
theContentEndpoint, theContentEndpoint,
theTerminologyEndpoint, theTerminologyEndpoint,
null); theContent);
} }
} }

View File

@ -0,0 +1,56 @@
package ca.uhn.fhir.cr.r4.measure;
import ca.uhn.fhir.cr.r4.ICollectDataServiceFactory;
import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.Operation;
import ca.uhn.fhir.rest.annotation.OperationParam;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.provider.ProviderConstants;
import org.hl7.fhir.r4.model.IdType;
import org.hl7.fhir.r4.model.Measure;
import org.hl7.fhir.r4.model.Parameters;
import org.springframework.beans.factory.annotation.Autowired;
public class CollectDataOperationProvider {
@Autowired
ICollectDataServiceFactory myR4CollectDataServiceFactory;
/**
* Implements the <a href=
* "http://hl7.org/fhir/R4/measure-operation-collect-data.html">$collect-data</a>
* operation found in the
* <a href="http://hl7.org/fhir/R4/clinicalreasoning-module.html">FHIR Clinical
* Reasoning Module</a>.
*
* <p>
* Returns a set of parameters with the generated MeasureReport and the
* resources that were used during the Measure evaluation
*
* @param theRequestDetails generally auto-populated by the HAPI server
* framework.
* @param theId the Id of the Measure to sub data for
* @param thePeriodStart The start of the reporting period
* @param thePeriodEnd The end of the reporting period
* @param theSubject the subject to use for the evaluation
* @param thePractitioner the practitioner to use for the evaluation
*
* @return Parameters the parameters containing the MeasureReport and the
* evaluated Resources
*/
@Description(
shortDefinition = "$collect-data",
value =
"Implements the <a href=\"http://hl7.org/fhir/R4/measure-operation-collect-data.html\">$collect-data</a> operation found in the <a href=\"http://hl7.org/fhir/R4/clinicalreasoning-module.html\">FHIR Clinical Reasoning Module</a>.")
@Operation(name = ProviderConstants.CR_OPERATION_COLLECTDATA, idempotent = true, type = Measure.class)
public Parameters collectData(
@IdParam IdType theId,
@OperationParam(name = "periodStart") String thePeriodStart,
@OperationParam(name = "periodEnd") String thePeriodEnd,
@OperationParam(name = "subject") String theSubject,
@OperationParam(name = "practitioner") String thePractitioner,
RequestDetails theRequestDetails) {
return myR4CollectDataServiceFactory
.create(theRequestDetails)
.collectData(theId, thePeriodStart, thePeriodEnd, theSubject, thePractitioner);
}
}

View File

@ -0,0 +1,42 @@
package ca.uhn.fhir.cr.r4.measure;
import ca.uhn.fhir.cr.r4.IDataRequirementsServiceFactory;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.Operation;
import ca.uhn.fhir.rest.annotation.OperationParam;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.provider.ProviderConstants;
import org.hl7.fhir.r4.model.IdType;
import org.hl7.fhir.r4.model.Library;
import org.hl7.fhir.r4.model.Measure;
import org.springframework.beans.factory.annotation.Autowired;
public class DataRequirementsOperationProvider {
@Autowired
IDataRequirementsServiceFactory myR4DataRequirementsServiceFactory;
/**
* Implements the <a href=
* "https://www.hl7.org/fhir/R4/measure-operation-data-requirements.html">$evaluate-measure</a>
* operation found in the
* <a href="http://www.hl7.org/fhir/clinicalreasoning-module.html">FHIR Clinical
* Reasoning Module</a>. This implementation aims to be compatible with the CQF
* IG.
*
* @param theId the id of the Measure to evaluate
* @param thePeriodStart The start of the reporting period
* @param thePeriodEnd The end of the reporting period
* @param theRequestDetails The details (such as tenant) of this request. Usually
* autopopulated HAPI.
* @return the calculated Library dataRequirements
*/
@Operation(name = ProviderConstants.CR_OPERATION_DATAREQUIREMENTS, idempotent = true, type = Measure.class)
public Library dataRequirements(
@IdParam IdType theId,
@OperationParam(name = "periodStart") String thePeriodStart,
@OperationParam(name = "periodEnd") String thePeriodEnd,
RequestDetails theRequestDetails) {
return myR4DataRequirementsServiceFactory
.create(theRequestDetails)
.dataRequirements(theId, thePeriodStart, thePeriodEnd);
}
}

View File

@ -0,0 +1,73 @@
package ca.uhn.fhir.cr.r4;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.rest.server.provider.ProviderConstants;
import org.hl7.fhir.r4.model.DateType;
import org.hl7.fhir.r4.model.Parameters;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import static org.junit.jupiter.api.Assertions.assertThrows;
@ExtendWith(SpringExtension.class)
public class CollectDataTest extends BaseCrR4TestServer{
public Parameters runCollectData(String thePeriodStart, String thePeriodEnd, String theMeasureId, String theSubject, String thePractitioner){
var parametersEval = new Parameters();
parametersEval.addParameter("periodStart", new DateType(thePeriodStart));
parametersEval.addParameter("periodEnd", new DateType(thePeriodEnd));
parametersEval.addParameter("practitioner", thePractitioner);
parametersEval.addParameter("subject", theSubject);
var report = ourClient.operation().onInstance("Measure/" + theMeasureId)
.named(ProviderConstants.CR_OPERATION_COLLECTDATA)
.withParameters(parametersEval)
.returnResourceType(Parameters.class)
.execute();
return report;
}
@Test
void testMeasureDataRequirements() {
loadBundle("ColorectalCancerScreeningsFHIR-bundle.json");
var reportAllSubjects = runCollectData("2019-01-01", "2019-12-31", "ColorectalCancerScreeningsFHIR", null, null);
Assertions.assertFalse(reportAllSubjects.getParameter().isEmpty());
// use same loaded bundle for all tests
testCollectDataSubject();
testCollectDataGroup();
testCollectDataPractitioner();
testCollectDataInvalidInterval();
testCollectDataInvalidMeasure();
}
void testCollectDataSubject() {
var report = runCollectData("2019-01-01", "2019-12-31", "ColorectalCancerScreeningsFHIR", "Patient/numer-EXM130", null);
Assertions.assertFalse(report.getParameter().isEmpty());
}
void testCollectDataGroup() {
var report = runCollectData("2019-01-01", "2019-12-31", "ColorectalCancerScreeningsFHIR", "Group/group-EXM130", null);
Assertions.assertFalse(report.getParameter().isEmpty());
}
void testCollectDataPractitioner() {
var report = runCollectData("2019-01-01", "2019-12-31", "ColorectalCancerScreeningsFHIR", null, "Practitioner/practitioner-EXM130");
Assertions.assertFalse(report.getParameter().isEmpty());
}
void testCollectDataInvalidInterval() {
assertThrows(InternalErrorException.class, ()->runCollectData("2020-01-01", "2019-12-31", "ColorectalCancerScreeningsFHIR", null, null));
}
void testCollectDataInvalidMeasure() {
assertThrows(ResourceNotFoundException.class, ()->runCollectData("2019-01-01", "2019-12-31", "ColorectalCancerScreeningsFHI", null, null));
}
}

View File

@ -30,23 +30,37 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
public class CpgOperationProviderTest extends BaseCrR4TestServer{ public class CpgOperationProviderTest extends BaseCrR4TestServer{
@BeforeEach @BeforeEach
void setup() { void setup() {
var reqDeets = setupRequestDetails(); var requestDetails = setupRequestDetails();
loadResource(Library.class, "SimpleR4Library.json", reqDeets); loadResource(Library.class, "SimpleR4Library.json", requestDetails);
loadResource(Patient.class, "SimplePatient.json", reqDeets); loadResource(Patient.class, "SimplePatient.json", requestDetails);
loadResource(Observation.class, "SimpleObservation.json", reqDeets); loadResource(Observation.class, "SimpleObservation.json", requestDetails);
loadResource(Condition.class, "SimpleCondition.json", reqDeets); loadResource(Condition.class, "SimpleCondition.json", requestDetails);
}
@Test
void cpgProviderTest(){
// reuse loaded resources for all tests
assertTrue(cqlExecutionProviderTestSimpleDate());
cqlExecutionProviderTestSimpleArithmetic();
evaluateLibraryProviderTestLibraryWithSubject();
evaluateLibraryProviderTestSimpleExpression();
cqlExecutionProviderTestReferencedLibrary();
cqlExecutionProviderTestDataBundle();
cqlExecutionProviderTestDataBundleWithSubject();
cqlExecutionProviderTestSimpleParameters();
cqlExecutionProviderTestExpression();
cqlExecutionProviderTestErrorExpression();
} }
@Test
void cqlExecutionProvider_testSimpleDate() { private Boolean cqlExecutionProviderTestSimpleDate() {
// execute cql expression on date interval // execute cql expression on date interval
Parameters params = parameters(stringPart("expression", "Interval[Today() - 2 years, Today())")); Parameters params = parameters(stringPart("expression", "Interval[Today() - 2 years, Today())"));
Parameters results = runCqlExecution(params); Parameters results = runCqlExecution(params);
assertTrue(results.getParameter("return").getValue() instanceof Period); return results.getParameter("return").getValue() instanceof Period;
} }
@Test
void cqlExecutionProvider_testSimpleArithmetic() { void cqlExecutionProviderTestSimpleArithmetic() {
// execute simple cql expression // execute simple cql expression
Parameters params = parameters(stringPart("expression", "5 * 5")); Parameters params = parameters(stringPart("expression", "5 * 5"));
Parameters results = runCqlExecution(params); Parameters results = runCqlExecution(params);
@ -54,8 +68,7 @@ public class CpgOperationProviderTest extends BaseCrR4TestServer{
assertEquals("25", ((IntegerType) results.getParameter("return").getValue()).asStringValue()); assertEquals("25", ((IntegerType) results.getParameter("return").getValue()).asStringValue());
} }
@Test void evaluateLibraryProviderTestLibraryWithSubject() {
void evaluateLibraryProvider_testLibraryWithSubject() {
// evaluate library resource for a subject // evaluate library resource for a subject
var params = new Parameters(); var params = new Parameters();
params.addParameter("subject", new StringType("Patient/SimplePatient")); params.addParameter("subject", new StringType("Patient/SimplePatient"));
@ -71,8 +84,8 @@ public class CpgOperationProviderTest extends BaseCrR4TestServer{
assertTrue(((BooleanType) report.getParameter("Denominator").getValue()).booleanValue()); assertTrue(((BooleanType) report.getParameter("Denominator").getValue()).booleanValue());
} }
@Test
void evaluateLibraryProvider_testSimpleExpression() { void evaluateLibraryProviderTestSimpleExpression() {
// evaluate expression for subject from specified library resource // evaluate expression for subject from specified library resource
var params = new Parameters(); var params = new Parameters();
params.addParameter("subject", new StringType("Patient/SimplePatient")); params.addParameter("subject", new StringType("Patient/SimplePatient"));
@ -84,8 +97,7 @@ public class CpgOperationProviderTest extends BaseCrR4TestServer{
assertTrue(((BooleanType) report.getParameter("Numerator").getValue()).booleanValue()); assertTrue(((BooleanType) report.getParameter("Numerator").getValue()).booleanValue());
} }
@Test void cqlExecutionProviderTestReferencedLibrary() {
void cqlExecutionProvider_testReferencedLibrary() {
// execute cql expression from referenced library on subject // execute cql expression from referenced library on subject
Parameters libraryParameter = parameters( Parameters libraryParameter = parameters(
canonicalPart("url", ourClient.getServerBase() + "/Library/SimpleR4Library|0.0.1"), canonicalPart("url", ourClient.getServerBase() + "/Library/SimpleR4Library|0.0.1"),
@ -100,8 +112,7 @@ public class CpgOperationProviderTest extends BaseCrR4TestServer{
assertTrue(((BooleanType) results.getParameter("return").getValue()).booleanValue()); assertTrue(((BooleanType) results.getParameter("return").getValue()).booleanValue());
} }
@Test void cqlExecutionProviderTestDataBundle() {
void cqlExecutionProvider_testDataBundle() {
// execute cql expression from library over data from bundle with no subject // execute cql expression from library over data from bundle with no subject
Parameters libraryParameter = parameters( Parameters libraryParameter = parameters(
canonicalPart("url", ourClient.getServerBase() + "/Library/SimpleR4Library"), canonicalPart("url", ourClient.getServerBase() + "/Library/SimpleR4Library"),
@ -118,8 +129,8 @@ public class CpgOperationProviderTest extends BaseCrR4TestServer{
assertTrue(results.getParameter().get(0).getResource() instanceof Observation); assertTrue(results.getParameter().get(0).getResource() instanceof Observation);
} }
@Test
void cqlExecutionProvider_testDataBundleWithSubject() { void cqlExecutionProviderTestDataBundleWithSubject() {
// execute cql expression from library over data from bundle with subject // execute cql expression from library over data from bundle with subject
Parameters libraryParameter = parameters( Parameters libraryParameter = parameters(
canonicalPart("url", ourClient.getServerBase() + "/Library/SimpleR4Library"), canonicalPart("url", ourClient.getServerBase() + "/Library/SimpleR4Library"),
@ -135,8 +146,8 @@ public class CpgOperationProviderTest extends BaseCrR4TestServer{
assertTrue(results.getParameter().get(0).getResource() instanceof Observation); assertTrue(results.getParameter().get(0).getResource() instanceof Observation);
} }
@Test
void cqlExecutionProvider_testSimpleParameters() { void cqlExecutionProviderTestSimpleParameters() {
// execute inline cql date expression with input valuemv // execute inline cql date expression with input valuemv
Parameters evaluationParams = parameters( Parameters evaluationParams = parameters(
datePart("%inputDate", "2019-11-01")); datePart("%inputDate", "2019-11-01"));
@ -148,8 +159,7 @@ public class CpgOperationProviderTest extends BaseCrR4TestServer{
assertTrue(((BooleanType) results.getParameter("return").getValue()).booleanValue()); assertTrue(((BooleanType) results.getParameter("return").getValue()).booleanValue());
} }
@Test void cqlExecutionProviderTestExpression() {
void cqlExecutionProvider_testExpression() {
// execute cql expression from referenced library // execute cql expression from referenced library
Parameters libraryParameter = parameters( Parameters libraryParameter = parameters(
canonicalPart("url", ourClient.getServerBase() + "/Library/SimpleR4Library"), canonicalPart("url", ourClient.getServerBase() + "/Library/SimpleR4Library"),
@ -168,8 +178,7 @@ public class CpgOperationProviderTest extends BaseCrR4TestServer{
assertTrue(((BooleanType) results.getParameter("return").getValue()).booleanValue()); assertTrue(((BooleanType) results.getParameter("return").getValue()).booleanValue());
} }
@Test void cqlExecutionProviderTestErrorExpression() {
void cqlExecutionProvider_testErrorExpression() {
// execute invalid cql expression // execute invalid cql expression
Parameters params = parameters(stringPart("expression", "Interval[1,5]")); Parameters params = parameters(stringPart("expression", "Interval[1,5]"));

View File

@ -0,0 +1,49 @@
package ca.uhn.fhir.cr.r4;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.rest.server.provider.ProviderConstants;
import org.hl7.fhir.r4.model.DateType;
import org.hl7.fhir.r4.model.Library;
import org.hl7.fhir.r4.model.Parameters;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import static org.junit.jupiter.api.Assertions.assertThrows;
@ExtendWith(SpringExtension.class)
public class DataRequirementsTest extends BaseCrR4TestServer{
public Library runDataRequirements(String periodStart, String periodEnd, String measureId){
var parametersEval = new Parameters();
parametersEval.addParameter("periodStart", new DateType(periodStart));
parametersEval.addParameter("periodEnd", new DateType(periodEnd));
var report = ourClient.operation().onInstance("Measure/" + measureId)
.named(ProviderConstants.CR_OPERATION_DATAREQUIREMENTS)
.withParameters(parametersEval)
.returnResourceType(Library.class)
.execute();
return report;
}
@Test
void testMeasureDataRequirements() {
loadBundle("ColorectalCancerScreeningsFHIR-bundle.json");
Assertions.assertFalse(runDataRequirements("2019-01-01", "2019-12-31", "ColorectalCancerScreeningsFHIR").getDataRequirement().isEmpty());
testMeasureDataRequirementsInvalidInterval();
testMeasureDataRequirementsInvalidMeasure();
}
void testMeasureDataRequirementsInvalidInterval() {
assertThrows(InternalErrorException.class, ()->runDataRequirements("2020-01-01", "2019-12-31", "ColorectalCancerScreeningsFHIR"));
}
void testMeasureDataRequirementsInvalidMeasure() {
assertThrows(ResourceNotFoundException.class, ()->runDataRequirements("2019-01-01", "2019-12-31", "ColorectalCancerScreeningsFHI"));
}
}

View File

@ -5,7 +5,6 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
import ca.uhn.fhir.rest.param.*; import ca.uhn.fhir.rest.param.*;
import ca.uhn.fhir.rest.server.RestfulServer; import ca.uhn.fhir.rest.server.RestfulServer;
@ -15,6 +14,7 @@ import org.hl7.fhir.r4.model.HumanName;
import org.hl7.fhir.r4.model.IdType; import org.hl7.fhir.r4.model.IdType;
import org.hl7.fhir.r4.model.Immunization; import org.hl7.fhir.r4.model.Immunization;
import org.hl7.fhir.r4.model.Patient; import org.hl7.fhir.r4.model.Patient;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import ca.uhn.fhir.cr.repo.HapiFhirRepository; import ca.uhn.fhir.cr.repo.HapiFhirRepository;
@ -28,13 +28,28 @@ public class HapiFhirRepositoryR4Test extends BaseCrR4TestServer {
private static final String MY_TEST_DATA = private static final String MY_TEST_DATA =
"ca/uhn/fhir/cr/r4/immunization/Patients_Encounters_Immunizations_Practitioners.json"; "ca/uhn/fhir/cr/r4/immunization/Patients_Encounters_Immunizations_Practitioners.json";
@BeforeEach
void setup() {
loadBundle("ColorectalCancerScreeningsFHIR-bundle.json");
loadBundle(MY_TEST_DATA);
}
@Test @Test
void crudTest() { void repositoryTests(){
var requestDetails = setupRequestDetails(); var repository = new HapiFhirRepository(myDaoRegistry, setupRequestDetails(), myRestfulServer);
//register repo //run repository tests
//regster providers transactionReadsImmunizationResources(repository);
var repository = new HapiFhirRepository(myDaoRegistry, requestDetails, myRestfulServer); repositorySearchForEncounterWithMatchingCode(repository);
var result = repository canSearchMoreThan50Patients(repository);
canSearchWithPagination(repository);
transactionReadsPatientResources(repository);
transactionReadsEncounterResources(repository);
assertTrue(crudTest(repository));
}
Boolean crudTest(HapiFhirRepository theRepository) {
var result = theRepository
.create(new Patient().addName(new HumanName().setFamily("Test").addGiven("Name1"))); .create(new Patient().addName(new HumanName().setFamily("Test").addGiven("Name1")));
assertEquals(true, result.getCreated()); assertEquals(true, result.getCreated());
var patient = (Patient) result.getResource(); var patient = (Patient) result.getResource();
@ -42,64 +57,24 @@ public class HapiFhirRepositoryR4Test extends BaseCrR4TestServer {
assertEquals("Test", patient.getName().get(0).getFamily()); assertEquals("Test", patient.getName().get(0).getFamily());
assertEquals(1, patient.getName().get(0).getGiven().size()); assertEquals(1, patient.getName().get(0).getGiven().size());
patient.getName().get(0).addGiven("Name2"); patient.getName().get(0).addGiven("Name2");
repository.update(patient); theRepository.update(patient);
var updatedPatient = repository.read(Patient.class, patient.getIdElement()); var updatedPatient = theRepository.read(Patient.class, patient.getIdElement());
assertEquals(2, updatedPatient.getName().get(0).getGiven().size()); assertEquals(2, updatedPatient.getName().get(0).getGiven().size());
repository.delete(Patient.class, patient.getIdElement()); theRepository.delete(Patient.class, patient.getIdElement());
var ex = assertThrows(Exception.class, var ex = assertThrows(Exception.class,
() -> repository.read(Patient.class, new IdType(patient.getIdElement().getIdPart()))); () -> theRepository.read(Patient.class, new IdType(patient.getIdElement().getIdPart())));
assertTrue(ex.getMessage().contains("Resource was deleted")); return ex.getMessage().contains("Resource was deleted");
} }
@Test void canSearchMoreThan50Patients(HapiFhirRepository theRepository) {
void canSearchMoreThan50Patients() { var expectedPatientCount = 65;
loadBundle(MY_TEST_DATA);
var expectedPatientCount = 63;
ourPagingProvider.setMaximumPageSize(100); ourPagingProvider.setMaximumPageSize(100);
var repository = new HapiFhirRepository(myDaoRegistry, setupRequestDetails(), myRestfulServer);
// get all patient resources posted // get all patient resources posted
var result = repository.search(Bundle.class, Patient.class, withCountParam(100)); var result = theRepository.search(Bundle.class, Patient.class, withCountParam(100));
assertEquals(expectedPatientCount, result.getTotal()); assertEquals(expectedPatientCount, result.getTotal());
// count all resources in result // count all resources in result
int counter = 0; int counter = 0;
for (var e : result.getEntry()) {
counter++;
}
// verify all patient resources captured
assertEquals(expectedPatientCount, counter,
"Patient search results don't match available resources");
}
@Test
void canSearchWithPagination() {
loadBundle(MY_TEST_DATA);
var requestDetails = setupRequestDetails();
var repository = new HapiFhirRepository(myDaoRegistry, requestDetails, myRestfulServer);
var result = repository.search(Bundle.class, Patient.class, withCountParam(20));
assertEquals(20, result.getEntry().size());
var next = result.getLink().get(1);
assertEquals("next", next.getRelation());
var nextUrl = next.getUrl();
var nextResult = repository.link(Bundle.class, nextUrl);
assertEquals(20, nextResult.getEntry().size());
assertEquals(false,
result.getEntry().stream().map(e -> e.getResource().getIdPart()).anyMatch(
i -> nextResult.getEntry().stream().map(e -> e.getResource().getIdPart())
.collect(Collectors.toList()).contains(i)));
}
@Test
void transactionReadsPatientResources() {
var expectedPatientCount = 63;
var theBundle = readResource(Bundle.class, MY_TEST_DATA);
ourPagingProvider.setMaximumPageSize(100);
var repository = new HapiFhirRepository(myDaoRegistry, setupRequestDetails(), myRestfulServer);
repository.transaction(theBundle);
var result = repository.search(Bundle.class, Patient.class, withCountParam(100));
// count all resources in result
int counter = 0;
for (Object i : result.getEntry()) { for (Object i : result.getEntry()) {
counter++; counter++;
} }
@ -108,14 +83,41 @@ public class HapiFhirRepositoryR4Test extends BaseCrR4TestServer {
"Patient search results don't match available resources"); "Patient search results don't match available resources");
} }
@Test
void transactionReadsEncounterResources() { void canSearchWithPagination(HapiFhirRepository theRepository) {
var expectedEncounterCount = 652;
var theBundle = readResource(Bundle.class, MY_TEST_DATA); var result = theRepository.search(Bundle.class, Patient.class, withCountParam(20));
assertEquals(20, result.getEntry().size());
var next = result.getLink().get(1);
assertEquals("next", next.getRelation());
var nextUrl = next.getUrl();
var nextResult = theRepository.link(Bundle.class, nextUrl);
assertEquals(20, nextResult.getEntry().size());
assertEquals(false,
result.getEntry().stream().map(e -> e.getResource().getIdPart()).anyMatch(
i -> nextResult.getEntry().stream().map(e -> e.getResource().getIdPart())
.toList().contains(i)));
}
void transactionReadsPatientResources(HapiFhirRepository theRepository) {
var expectedPatientCount = 65;
ourPagingProvider.setMaximumPageSize(100);
var result = theRepository.search(Bundle.class, Patient.class, withCountParam(100));
// count all resources in result
int counter = 0;
for (Object i : result.getEntry()) {
counter++;
}
// verify all patient resources captured
assertEquals(expectedPatientCount, counter,
"Patient search results don't match available resources");
}
void transactionReadsEncounterResources(HapiFhirRepository theRepository) {
var expectedEncounterCount = 654;
ourPagingProvider.setMaximumPageSize(1000); ourPagingProvider.setMaximumPageSize(1000);
var repository = new HapiFhirRepository(myDaoRegistry, setupRequestDetails(), myRestfulServer); var result = theRepository.search(Bundle.class, Encounter.class, withCountParam(1000));
repository.transaction(theBundle);
var result = repository.search(Bundle.class, Encounter.class, withCountParam(1000));
// count all resources in result // count all resources in result
int counter = 0; int counter = 0;
for (Object i : result.getEntry()) { for (Object i : result.getEntry()) {
@ -125,10 +127,8 @@ public class HapiFhirRepositoryR4Test extends BaseCrR4TestServer {
assertEquals(expectedEncounterCount, counter, assertEquals(expectedEncounterCount, counter,
"Encounter search results don't match available resources"); "Encounter search results don't match available resources");
} }
@Test void repositorySearchForEncounterWithMatchingCode(HapiFhirRepository theRepository) {
void repositorySearchForEncounterWithMatchingCode() {
loadBundle("ColorectalCancerScreeningsFHIR-bundle.json");
//SearchConverter validation test for repository //SearchConverter validation test for repository
List<IQueryParameterType> codeList = new ArrayList<>(); List<IQueryParameterType> codeList = new ArrayList<>();
@ -152,10 +152,8 @@ public class HapiFhirRepositoryR4Test extends BaseCrR4TestServer {
// replicate repository searchParam list // replicate repository searchParam list
Map<String, List<IQueryParameterType>> searchParams = Map.of("type", codeList, "subject", Collections.singletonList(new ReferenceParam("Patient/numer-EXM130"))); Map<String, List<IQueryParameterType>> searchParams = Map.of("type", codeList, "subject", Collections.singletonList(new ReferenceParam("Patient/numer-EXM130")));
var repository = new HapiFhirRepository(myDaoRegistry, setupRequestDetails(), myRestfulServer);
// replicate search for valueset codes // replicate search for valueset codes
var result = repository.search(Bundle.class, Encounter.class, searchParams); var result = theRepository.search(Bundle.class, Encounter.class, searchParams);
// count all resources in result // count all resources in result
int counter = 0; int counter = 0;
@ -166,15 +164,12 @@ public class HapiFhirRepositoryR4Test extends BaseCrR4TestServer {
assertEquals(1, counter, assertEquals(1, counter,
"Encounter search results don't match available resources"); "Encounter search results don't match available resources");
} }
@Test void transactionReadsImmunizationResources(HapiFhirRepository theRepository) {
void transactionReadsImmunizationResources() {
var expectedEncounterCount = 638; var expectedEncounterCount = 638;
var theBundle = readResource(Bundle.class, MY_TEST_DATA);
ourPagingProvider.setMaximumPageSize(1000); ourPagingProvider.setMaximumPageSize(1000);
var repository = new HapiFhirRepository(myDaoRegistry, setupRequestDetails(), myRestfulServer);
repository.transaction(theBundle); var result = theRepository.search(Bundle.class, Immunization.class, withCountParam(1000));
var result = repository.search(Bundle.class, Immunization.class, withCountParam(1000));
// count all resources in result // count all resources in result
int counter = 0; int counter = 0;
for (Object i : result.getEntry()) { for (Object i : result.getEntry()) {

View File

@ -7,6 +7,7 @@ import org.hl7.fhir.r4.model.MeasureReport;
import org.hl7.fhir.r4.model.Observation; import org.hl7.fhir.r4.model.Observation;
import org.hl7.fhir.r4.model.Parameters; import org.hl7.fhir.r4.model.Parameters;
import org.hl7.fhir.r4.model.Resource; import org.hl7.fhir.r4.model.Resource;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
@ -21,6 +22,27 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
@ExtendWith(SpringExtension.class) @ExtendWith(SpringExtension.class)
class MeasureOperationProviderTest extends BaseCrR4TestServer { class MeasureOperationProviderTest extends BaseCrR4TestServer {
@BeforeEach
void setup() {
// load resources
loadBundle("ColorectalCancerScreeningsFHIR-bundle.json");
loadBundle("Exm104FhirR4MeasureBundle.json");
loadBundle("ClientNonPatientBasedMeasureBundle.json");
loadBundle("multiversion/EXM124-7.0.000-bundle.json");
loadBundle("multiversion/EXM124-9.0.000-bundle.json");
loadBundle("largeValueSetMeasureTest-Bundle.json");
loadBundle("BCSEHEDISMY2022-bundle.json");
}
@Test
void runMeasureTests(){
// run tests
assertNotNull(testMeasureEvaluateExm130());
assertNotNull(testMeasureEvaluateExm104());
testClientNonPatientBasedMeasureEvaluate();
testMeasureEvaluateMultiVersion();
testLargeValuesetMeasure();
testHedis2022();
}
public MeasureReport runEvaluateMeasure(String periodStart, String periodEnd, String subject, String measureId, String reportType, String practitioner){ public MeasureReport runEvaluateMeasure(String periodStart, String periodEnd, String subject, String measureId, String reportType, String practitioner){
@ -31,43 +53,96 @@ class MeasureOperationProviderTest extends BaseCrR4TestServer {
parametersEval.addParameter("reportType", reportType); parametersEval.addParameter("reportType", reportType);
parametersEval.addParameter("subject", subject); parametersEval.addParameter("subject", subject);
var report = ourClient.operation().onInstance("Measure/" + measureId) return ourClient.operation().onInstance("Measure/" + measureId)
.named(ProviderConstants.CR_OPERATION_EVALUATE_MEASURE) .named(ProviderConstants.CR_OPERATION_EVALUATE_MEASURE)
.withParameters(parametersEval) .withParameters(parametersEval)
.returnResourceType(MeasureReport.class) .returnResourceType(MeasureReport.class)
.execute(); .execute();
}
assertNotNull(report); MeasureReport testMeasureEvaluateExm130() {
return runEvaluateMeasure("2019-01-01", "2019-12-31", "Patient/numer-EXM130", "ColorectalCancerScreeningsFHIR", "Individual", null);
return report;
} }
@Test MeasureReport testMeasureEvaluateExm104() {
void testMeasureEvaluate_EXM130() { return runEvaluateMeasure("2019-01-01", "2019-12-31", "Patient/numer-EXM104", "measure-EXM104-8.2.000", "Individual", null);
loadBundle("ColorectalCancerScreeningsFHIR-bundle.json");
runEvaluateMeasure("2019-01-01", "2019-12-31", "Patient/numer-EXM130", "ColorectalCancerScreeningsFHIR", "Individual", null);
}
@Test
void testMeasureEvaluate_EXM104() {
loadBundle("Exm104FhirR4MeasureBundle.json");
runEvaluateMeasure("2019-01-01", "2019-12-31", "Patient/numer-EXM104", "measure-EXM104-8.2.000", "Individual", null);
} }
void testHedis2022() {
runWithPatient("BCSEHEDISMY2022", "Patient/Patient-5", 0, 0, 0, 0, false,
"Interval[2020-10-01T00:00:00.000, 2022-12-31T23:59:59.999]");
runWithPatient("BCSEHEDISMY2022", "Patient/Patient-7", 1, 1, 0, 0, true,
"Interval[2020-10-01T00:00:00.000, 2022-12-31T23:59:59.999]");
runWithPatient("BCSEHEDISMY2022", "Patient/Patient-9", 0, 0, 0, 0, true,
"Interval[2020-10-01T00:00:00.000, 2022-12-31T23:59:59.999]");
runWithPatient("BCSEHEDISMY2022", "Patient/Patient-21", 1, 0, 1, 0, true,
"Interval[2020-10-01T00:00:00.000, 2022-12-31T23:59:59.999]");
runWithPatient("BCSEHEDISMY2022", "Patient/Patient-23", 1, 1, 0, 0, true,
"Interval[2020-10-01T00:00:00.000, 2022-12-31T23:59:59.999]");
runWithPatient("BCSEHEDISMY2022", "Patient/Patient-65", 1, 1, 0, 1, true,
"Interval[2020-10-01T00:00:00.000, 2022-12-31T23:59:59.999]");
}
void testClientNonPatientBasedMeasureEvaluate() {
var measure = read(new IdType("Measure", "InitialInpatientPopulation"));
assertNotNull(measure);
var returnMeasureReport = runEvaluateMeasure("2019-01-01", "2020-01-01", "Patient/97f27374-8a5c-4aa1-a26f-5a1ab03caa47", "InitialInpatientPopulation", "Individual", null);
String populationName = "initial-population";
int expectedCount = 2;
Optional<MeasureReport.MeasureReportGroupPopulationComponent> population = returnMeasureReport.getGroup().get(0)
.getPopulation().stream().filter(x -> x.hasCode() && x.getCode().hasCoding()
&& x.getCode().getCoding().get(0).getCode().equals(populationName))
.findFirst();
assertTrue(population.isPresent(), String.format("Unable to locate a population with id \"%s\"", populationName));
assertEquals(population.get().getCount(), expectedCount,
String.format("expected count for population \"%s\" did not match", populationName));
}
void testMeasureEvaluateMultiVersion() {
assertNotNull(runEvaluateMeasure("2019-01-01", "2020-01-01", "Patient/numer-EXM124", "measure-EXM124-7.0.000", "Individual", null));
assertNotNull(runEvaluateMeasure("2019-01-01", "2020-01-01", "Patient/numer-EXM124", "measure-EXM124-9.0.000", "Individual", null));
}
void testLargeValuesetMeasure() throws NoSuchElementException {
var returnMeasureReport = runEvaluateMeasure("2023-01-01", "2024-01-01", null, "CMSTest", "population", null);
String populationName = "numerator";
int expectedCount = 1;
Optional<MeasureReport.MeasureReportGroupPopulationComponent> population = returnMeasureReport.getGroup().get(0)
.getPopulation().stream().filter(x -> x.hasCode() && x.getCode().hasCoding()
&& x.getCode().getCoding().get(0).getCode().equals(populationName))
.findFirst();
assertTrue(population.isPresent(), String.format("population \"%s\" not found in report", populationName));
assertEquals(
expectedCount,
population.get().getCount(),
String.format("expected count for population \"%s\" did not match", populationName)
);
}
private void runWithPatient(String measureId, String patientId, int initialPopulationCount, int denominatorCount, private void runWithPatient(String measureId, String patientId, int initialPopulationCount, int denominatorCount,
int denominatorExclusionCount, int numeratorCount, boolean enrolledDuringParticipationPeriod, int denominatorExclusionCount, int numeratorCount, boolean enrolledDuringParticipationPeriod,
String participationPeriod) { String participationPeriod) {
var returnMeasureReport = runEvaluateMeasure("2022-01-01", "2022-12-31", patientId, measureId, "Individual", null); var returnMeasureReport = runEvaluateMeasure("2022-01-01", "2022-12-31", patientId, measureId, "Individual", null);
for (MeasureReport.MeasureReportGroupPopulationComponent population : returnMeasureReport.getGroupFirstRep() for (MeasureReport.MeasureReportGroupPopulationComponent population : returnMeasureReport.getGroupFirstRep()
.getPopulation()) .getPopulation())
switch (population.getCode().getCodingFirstRep().getCode()) { switch (population.getCode().getCodingFirstRep().getCode()) {
case "initial-population" -> assertEquals(initialPopulationCount, population.getCount()); case "initial-population" -> assertEquals(initialPopulationCount, population.getCount());
case "denominator" -> assertEquals(denominatorCount, population.getCount()); case "denominator" -> assertEquals(denominatorCount, population.getCount());
case "denominator-exclusion" -> assertEquals(denominatorExclusionCount, population.getCount()); case "denominator-exclusion" -> assertEquals(denominatorExclusionCount, population.getCount());
case "numerator" -> assertEquals(numeratorCount, population.getCount()); case "numerator" -> assertEquals(numeratorCount, population.getCount());
} }
Observation enrolledDuringParticipationPeriodObs = null; Observation enrolledDuringParticipationPeriodObs = null;
Observation participationPeriodObs = null; Observation participationPeriodObs = null;
@ -88,76 +163,4 @@ class MeasureOperationProviderTest extends BaseCrR4TestServer {
assertNotNull(participationPeriodObs); assertNotNull(participationPeriodObs);
assertEquals(participationPeriod, participationPeriodObs.getValueCodeableConcept().getCodingFirstRep().getCode()); assertEquals(participationPeriod, participationPeriodObs.getValueCodeableConcept().getCodingFirstRep().getCode());
} }
@Test
void testBCSEHEDISMY2022() {
loadBundle("BCSEHEDISMY2022-bundle.json");
runWithPatient("BCSEHEDISMY2022", "Patient/Patient-5", 0, 0, 0, 0, false,
"Interval[2020-10-01T00:00:00.000, 2022-12-31T23:59:59.999]");
runWithPatient("BCSEHEDISMY2022", "Patient/Patient-7", 1, 1, 0, 0, true,
"Interval[2020-10-01T00:00:00.000, 2022-12-31T23:59:59.999]");
runWithPatient("BCSEHEDISMY2022", "Patient/Patient-9", 0, 0, 0, 0, true,
"Interval[2020-10-01T00:00:00.000, 2022-12-31T23:59:59.999]");
runWithPatient("BCSEHEDISMY2022", "Patient/Patient-21", 1, 0, 1, 0, true,
"Interval[2020-10-01T00:00:00.000, 2022-12-31T23:59:59.999]");
runWithPatient("BCSEHEDISMY2022", "Patient/Patient-23", 1, 1, 0, 0, true,
"Interval[2020-10-01T00:00:00.000, 2022-12-31T23:59:59.999]");
runWithPatient("BCSEHEDISMY2022", "Patient/Patient-65", 1, 1, 0, 1, true,
"Interval[2020-10-01T00:00:00.000, 2022-12-31T23:59:59.999]");
}
@Test
void testClientNonPatientBasedMeasureEvaluate() {
this.loadBundle("ClientNonPatientBasedMeasureBundle.json");
var measure = read(new IdType("Measure", "InitialInpatientPopulation"));
assertNotNull(measure);
var returnMeasureReport = runEvaluateMeasure("2019-01-01", "2020-01-01", "Patient/97f27374-8a5c-4aa1-a26f-5a1ab03caa47", "InitialInpatientPopulation", "Individual", null);
String populationName = "initial-population";
int expectedCount = 2;
Optional<MeasureReport.MeasureReportGroupPopulationComponent> population = returnMeasureReport.getGroup().get(0)
.getPopulation().stream().filter(x -> x.hasCode() && x.getCode().hasCoding()
&& x.getCode().getCoding().get(0).getCode().equals(populationName))
.findFirst();
assertTrue(population.isPresent(), String.format("Unable to locate a population with id \"%s\"", populationName));
assertEquals(population.get().getCount(), expectedCount,
String.format("expected count for population \"%s\" did not match", populationName));
}
@Test
void testMeasureEvaluateMultiVersion() {
this.loadBundle("multiversion/EXM124-7.0.000-bundle.json");
this.loadBundle("multiversion/EXM124-9.0.000-bundle.json");
runEvaluateMeasure("2019-01-01", "2020-01-01", "Patient/numer-EXM124", "measure-EXM124-7.0.000", "Individual", null);
runEvaluateMeasure("2019-01-01", "2020-01-01", "Patient/numer-EXM124", "measure-EXM124-9.0.000", "Individual", null);
}
@Test
void testLargeValuesetMeasure() throws NoSuchElementException {
this.loadBundle("largeValueSetMeasureTest-Bundle.json");
var returnMeasureReport = runEvaluateMeasure("2023-01-01", "2024-01-01", null, "CMSTest", "population", null);
String populationName = "numerator";
int expectedCount = 1;
Optional<MeasureReport.MeasureReportGroupPopulationComponent> population = returnMeasureReport.getGroup().get(0)
.getPopulation().stream().filter(x -> x.hasCode() && x.getCode().hasCoding()
&& x.getCode().getCoding().get(0).getCode().equals(populationName))
.findFirst();
assertTrue(population.isPresent(), String.format("population \"%s\" not found in report", populationName));
assertEquals(
expectedCount,
population.get().getCount(),
String.format("expected count for population \"%s\" did not match", populationName)
);
}
} }

View File

@ -4,7 +4,6 @@ import ca.uhn.fhir.cr.TestCqlProperties;
import ca.uhn.fhir.cr.TestCrConfig; import ca.uhn.fhir.cr.TestCrConfig;
import ca.uhn.fhir.cr.common.CqlThreadFactory; import ca.uhn.fhir.cr.common.CqlThreadFactory;
import ca.uhn.fhir.cr.config.r4.CrR4Config; import ca.uhn.fhir.cr.config.r4.CrR4Config;
import ca.uhn.fhir.rest.api.SearchStyleEnum;
import org.cqframework.cql.cql2elm.CqlCompilerOptions; import org.cqframework.cql.cql2elm.CqlCompilerOptions;
import org.cqframework.cql.cql2elm.model.CompiledLibrary; import org.cqframework.cql.cql2elm.model.CompiledLibrary;
import org.cqframework.cql.cql2elm.model.Model; import org.cqframework.cql.cql2elm.model.Model;
@ -13,7 +12,6 @@ import org.hl7.elm.r1.VersionedIdentifier;
import org.opencds.cqf.cql.engine.execution.CqlEngine; import org.opencds.cqf.cql.engine.execution.CqlEngine;
import org.opencds.cqf.cql.engine.runtime.Code; import org.opencds.cqf.cql.engine.runtime.Code;
import org.opencds.cqf.fhir.cql.EvaluationSettings; import org.opencds.cqf.fhir.cql.EvaluationSettings;
import org.opencds.cqf.fhir.cql.engine.retrieve.BaseRetrieveProvider;
import org.opencds.cqf.fhir.cql.engine.retrieve.RetrieveSettings; import org.opencds.cqf.fhir.cql.engine.retrieve.RetrieveSettings;
import org.opencds.cqf.fhir.cql.engine.terminology.TerminologySettings; import org.opencds.cqf.fhir.cql.engine.terminology.TerminologySettings;
import org.opencds.cqf.fhir.cr.measure.CareGapsProperties; import org.opencds.cqf.fhir.cr.measure.CareGapsProperties;

View File

@ -645,7 +645,7 @@
{ {
"type": "depends-on", "type": "depends-on",
"display": "Code system SNOMEDCT:2017-09", "display": "Code system SNOMEDCT:2017-09",
"resource": "http://snomed.info/sct|http://snomed.info/sct/version/201709" "resource": "http://snomed.info/sct/version/201709"
}, },
{ {
"type": "depends-on", "type": "depends-on",
@ -91120,7 +91120,7 @@
{ {
"type": "depends-on", "type": "depends-on",
"display": "Code system SNOMEDCT:2017-09", "display": "Code system SNOMEDCT:2017-09",
"resource": "http://snomed.info/sct|http://snomed.info/sct/version/201709" "resource": "http://snomed.info"
}, },
{ {
"type": "depends-on", "type": "depends-on",
@ -149191,13 +149191,46 @@
} }
], ],
"gender": "male", "gender": "male",
"birthDate": "1965-01-01" "birthDate": "1965-01-01",
"generalPractitioner":[
{"reference": "Practitioner/practitioner-EXM130"}
]
}, },
"request": { "request": {
"method": "PUT", "method": "PUT",
"url": "Patient/numer-EXM130" "url": "Patient/numer-EXM130"
} }
}, },
{"resource":{
"resourceType": "Group",
"id": "group-EXM130",
"type": "person",
"actual": true,
"member": [
{ "entity": { "reference": "Patient/denom-EXM130" } },
{ "entity": { "reference": "Patient/numer-EXM130" } },
{ "entity": { "reference": "Patient/neg-ip-EXM130" } }
]
},
"request": {
"method": "PUT",
"url": "Group/group-EXM130"
}
},
{"resource":{
"resourceType": "Practitioner",
"id": "practitioner-EXM130",
"name": [ {
"family": "Dawg",
"given": [ "Jay" ],
"prefix": [ "Dr" ]
} ]
},
"request": {
"method": "PUT",
"url": "Practitioner/practitioner-EXM130"
}
},
{ {
"resource": { "resource": {
"resourceType": "ValueSet", "resourceType": "ValueSet",

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId> <artifactId>hapi-fhir</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId> <artifactId>hapi-fhir</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId> <artifactId>hapi-fhir</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -9,7 +9,7 @@
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId> <artifactId>hapi-fhir</artifactId>
<packaging>pom</packaging> <packaging>pom</packaging>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<name>HAPI-FHIR</name> <name>HAPI-FHIR</name>
<description>An open-source implementation of the FHIR specification in Java.</description> <description>An open-source implementation of the FHIR specification in Java.</description>
@ -1006,7 +1006,7 @@
<ucum_version>1.0.8</ucum_version> <ucum_version>1.0.8</ucum_version>
<!-- CQL Support --> <!-- CQL Support -->
<clinical-reasoning.version>3.3.1</clinical-reasoning.version> <clinical-reasoning.version>3.4.0</clinical-reasoning.version>
<!-- Site properties --> <!-- Site properties -->
<fontawesomeVersion>5.4.1</fontawesomeVersion> <fontawesomeVersion>5.4.1</fontawesomeVersion>

View File

@ -7,7 +7,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId> <artifactId>hapi-fhir</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath> <relativePath>../../pom.xml</relativePath>
</parent> </parent>

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId> <artifactId>hapi-fhir</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath> <relativePath>../../pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId> <artifactId>hapi-fhir</artifactId>
<version>7.1.9-SNAPSHOT</version> <version>7.1.10-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath> <relativePath>../../pom.xml</relativePath>
</parent> </parent>