-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Library evaluation provider into CR (#394)
* library evaluate provider * testing for library evaluate and cql evaluate * removing file errors * more test coverage, update class names
- Loading branch information
Showing
16 changed files
with
803 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
70 changes: 70 additions & 0 deletions
70
cqf-fhir-cr/src/main/java/org/opencds/cqf/fhir/cr/cpg/r4/R4LibraryEvaluationService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
package org.opencds.cqf.fhir.cr.cpg.r4; | ||
|
||
import static org.opencds.cqf.fhir.utility.r4.Parameters.parameters; | ||
import static org.opencds.cqf.fhir.utility.r4.Parameters.part; | ||
|
||
import java.util.HashSet; | ||
import java.util.List; | ||
import java.util.Set; | ||
import org.hl7.fhir.r4.model.Bundle; | ||
import org.hl7.fhir.r4.model.Endpoint; | ||
import org.hl7.fhir.r4.model.IdType; | ||
import org.hl7.fhir.r4.model.Library; | ||
import org.hl7.fhir.r4.model.OperationOutcome; | ||
import org.hl7.fhir.r4.model.Parameters; | ||
import org.opencds.cqf.fhir.api.Repository; | ||
import org.opencds.cqf.fhir.cql.Engines; | ||
import org.opencds.cqf.fhir.cql.EvaluationSettings; | ||
import org.opencds.cqf.fhir.cql.LibraryEngine; | ||
import org.opencds.cqf.fhir.cr.cpg.BaseCqlExecutionProcessor; | ||
import org.opencds.cqf.fhir.utility.repository.Repositories; | ||
|
||
public class R4LibraryEvaluationService { | ||
|
||
protected Repository repository; | ||
protected EvaluationSettings evaluationSettings; | ||
|
||
public R4LibraryEvaluationService(Repository repository, EvaluationSettings evaluationSettings) { | ||
this.repository = repository; | ||
this.evaluationSettings = evaluationSettings; | ||
} | ||
|
||
public Parameters evaluate( | ||
IdType theId, | ||
String subject, | ||
List<String> expression, | ||
Parameters parameters, | ||
Bundle data, | ||
List<Parameters> prefetchData, | ||
Endpoint dataEndpoint, | ||
Endpoint contentEndpoint, | ||
Endpoint terminologyEndpoint) { | ||
|
||
var baseCqlExecutionProcessor = new BaseCqlExecutionProcessor(); | ||
|
||
if (prefetchData != null) { | ||
return parameters(part("invalid parameters", (OperationOutcome) | ||
baseCqlExecutionProcessor.createIssue("warning", "prefetchData is not yet supported", repository))); | ||
} | ||
|
||
if (contentEndpoint != null) { | ||
repository = Repositories.proxy(repository, dataEndpoint, contentEndpoint, terminologyEndpoint); | ||
} | ||
var libraryEngine = new LibraryEngine(repository, this.evaluationSettings); | ||
var library = repository.read(Library.class, theId); | ||
var engine = Engines.forRepositoryAndSettings(evaluationSettings, repository, data); | ||
var libraryManager = engine.getEnvironment().getLibraryManager(); | ||
var libraryIdentifier = baseCqlExecutionProcessor.resolveLibraryIdentifier(null, library, libraryManager); | ||
|
||
Set<String> expressionSet = null; | ||
if (expression != null) { | ||
expressionSet = new HashSet<>(expression); | ||
} | ||
try { | ||
return (Parameters) libraryEngine.evaluate(libraryIdentifier, subject, parameters, data, expressionSet); | ||
} catch (Exception e) { | ||
return parameters(part("evaluation error", (OperationOutcome) | ||
baseCqlExecutionProcessor.createIssue("error", e.getMessage(), repository))); | ||
} | ||
} | ||
} |
128 changes: 128 additions & 0 deletions
128
cqf-fhir-cr/src/test/java/org/opencds/cqf/fhir/cr/cpg/r4/CqlEvaluationServiceTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
package org.opencds.cqf.fhir.cr.cpg.r4; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
import static org.junit.jupiter.api.Assertions.assertFalse; | ||
import static org.junit.jupiter.api.Assertions.assertTrue; | ||
import static org.opencds.cqf.fhir.utility.r4.Parameters.datePart; | ||
import static org.opencds.cqf.fhir.utility.r4.Parameters.parameters; | ||
|
||
import org.hl7.fhir.r4.model.BooleanType; | ||
import org.hl7.fhir.r4.model.IntegerType; | ||
import org.hl7.fhir.r4.model.OperationOutcome; | ||
import org.hl7.fhir.r4.model.Parameters; | ||
import org.junit.jupiter.api.Test; | ||
|
||
public class CqlEvaluationServiceTest { | ||
@Test | ||
void libraryEvaluationService_inlineAsthma() { | ||
var content = "library AsthmaTest version '1.0.0'\n" + "\n" | ||
+ "using FHIR version '4.0.1'\n" | ||
+ "\n" | ||
+ "include FHIRHelpers version '4.0.1'\n" | ||
+ "\n" | ||
+ "codesystem \"SNOMED\": 'http://snomed.info/sct'\n" | ||
+ "\n" | ||
+ "code \"Asthma\": '195967001' from \"SNOMED\"\n" | ||
+ "\n" | ||
+ "context Patient\n" | ||
+ "\n" | ||
+ "define \"Asthma Diagnosis\":\n" | ||
+ " [Condition: \"Asthma\"]\n" | ||
+ "\n" | ||
+ "define \"Has Asthma Diagnosis\":\n" | ||
+ " exists(\"Asthma Diagnosis\")\n"; | ||
var when = Library.given() | ||
.repositoryFor("libraryeval") | ||
.when() | ||
.subject("Patient/SimplePatient") | ||
.content(content) | ||
.evaluateCql(); | ||
var results = when.then().parameters(); | ||
assertTrue(results.hasParameter()); | ||
assertEquals(3, results.getParameter().size()); | ||
} | ||
|
||
@Test | ||
void libraryEvaluationService_contentAndExpression() { | ||
var content = "library SimpleR4Library\n" + "\n" | ||
+ "using FHIR version '4.0.1'\n" | ||
+ "\n" | ||
+ "include FHIRHelpers version '4.0.1' called FHIRHelpers\n" | ||
+ "\n" | ||
+ "context Patient\n" | ||
+ "\n" | ||
+ "define simpleBooleanExpression: true\n" | ||
+ "\n" | ||
+ "define observationRetrieve: [Observation]\n" | ||
+ "\n" | ||
+ "define observationHasCode: not IsNull(([Observation]).code)\n" | ||
+ "\n" | ||
+ "define \"Initial Population\": observationHasCode\n" | ||
+ "\n" | ||
+ "define \"Denominator\": \"Initial Population\"\n" | ||
+ "\n" | ||
+ "define \"Numerator\": \"Denominator\""; | ||
var when = Library.given() | ||
.repositoryFor("libraryeval") | ||
.when() | ||
.subject("Patient/SimplePatient") | ||
.expression("Numerator") | ||
.content(content) | ||
.evaluateCql(); | ||
var results = when.then().parameters(); | ||
assertFalse(results.isEmpty()); | ||
assertEquals(1, results.getParameter().size()); | ||
assertTrue(results.getParameter("Numerator").getValue() instanceof BooleanType); | ||
assertTrue(((BooleanType) results.getParameter("Numerator").getValue()).booleanValue()); | ||
; | ||
} | ||
|
||
@Test | ||
void libraryEvaluationService_arithmetic() { | ||
var when = Library.given() | ||
.repositoryFor("libraryeval") | ||
.when() | ||
.expression("5*5") | ||
.evaluateCql(); | ||
var results = when.then().parameters(); | ||
assertTrue(results.getParameter("return").getValue() instanceof IntegerType); | ||
assertEquals("25", ((IntegerType) results.getParameter("return").getValue()).asStringValue()); | ||
} | ||
|
||
@Test | ||
void libraryEvaluationService_paramsAndExpression() { | ||
Parameters evaluationParams = parameters(datePart("%inputDate", "2019-11-01")); | ||
var when = Library.given() | ||
.repositoryFor("libraryeval") | ||
.when() | ||
.subject("Patient/SimplePatient") | ||
.parameters(evaluationParams) | ||
.expression("year from %inputDate before 2020") | ||
.evaluateCql(); | ||
var results = when.then().parameters(); | ||
assertTrue(results.getParameter("return").getValue() instanceof BooleanType); | ||
assertTrue(((BooleanType) results.getParameter("return").getValue()).booleanValue()); | ||
} | ||
|
||
@Test | ||
void libraryEvaluationService_ErrorLibrary() { | ||
var expression = "Interval[1,5]"; | ||
var when = Library.given() | ||
.repositoryFor("libraryeval") | ||
.when() | ||
.expression(expression) | ||
.evaluateCql(); | ||
var report = when.then().parameters(); | ||
assertTrue(report.hasParameter()); | ||
assertTrue(report.getParameterFirstRep().hasName()); | ||
assertEquals("evaluation error", report.getParameterFirstRep().getName()); | ||
assertTrue(report.getParameterFirstRep().hasResource()); | ||
assertTrue(report.getParameterFirstRep().getResource() instanceof OperationOutcome); | ||
assertEquals( | ||
"Unsupported interval point type for FHIR conversion java.lang.Integer", | ||
((OperationOutcome) report.getParameterFirstRep().getResource()) | ||
.getIssueFirstRep() | ||
.getDetails() | ||
.getText()); | ||
} | ||
} |
Oops, something went wrong.