JPATerminologyProvider tests and bug fixes (#2346)
* Add initial jpaTerminologyProvider tests, add EXM130 to test suite
This commit is contained in:
parent
f3c0ecd54d
commit
af5c45531a
|
@ -30,7 +30,6 @@ import ca.uhn.fhir.cql.dstu3.provider.JpaTerminologyProvider;
|
|||
import ca.uhn.fhir.cql.dstu3.provider.LibraryResolutionProviderImpl;
|
||||
import ca.uhn.fhir.cql.dstu3.provider.MeasureOperationsProvider;
|
||||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
import ca.uhn.fhir.jpa.rp.dstu3.ValueSetResourceProvider;
|
||||
import ca.uhn.fhir.jpa.term.api.ITermReadSvcDstu3;
|
||||
|
||||
import org.opencds.cqf.cql.engine.model.ModelResolver;
|
||||
|
@ -39,6 +38,7 @@ import java.util.Map;
|
|||
|
||||
import org.cqframework.cql.cql2elm.model.Model;
|
||||
import org.hl7.elm.r1.VersionedIdentifier;
|
||||
import org.hl7.fhir.dstu3.model.ValueSet;
|
||||
import org.opencds.cqf.cql.engine.fhir.model.Dstu3FhirModelResolver;
|
||||
import org.opencds.cqf.cql.engine.terminology.TerminologyProvider;
|
||||
import org.opencds.cqf.cql.evaluator.engine.model.CachingModelResolverDecorator;
|
||||
|
@ -50,14 +50,16 @@ import org.springframework.context.annotation.Lazy;
|
|||
public class CqlDstu3Config extends BaseCqlConfig {
|
||||
@Lazy
|
||||
@Bean
|
||||
TerminologyProvider terminologyProvider(ITermReadSvcDstu3 theITermReadSvc,
|
||||
ValueSetResourceProvider theValueSetResourceProvider, IValidationSupport theValidationSupport) {
|
||||
return new JpaTerminologyProvider(theITermReadSvc, theValueSetResourceProvider, theValidationSupport);
|
||||
TerminologyProvider terminologyProvider(ITermReadSvcDstu3 theITermReadSvc, DaoRegistry daoRegistry,
|
||||
IValidationSupport theValidationSupport) {
|
||||
return new JpaTerminologyProvider(theITermReadSvc, daoRegistry.getResourceDao(ValueSet.class),
|
||||
theValidationSupport);
|
||||
}
|
||||
|
||||
@Lazy
|
||||
@Bean
|
||||
EvaluationProviderFactory evaluationProviderFactory(FhirContext theFhirContext, DaoRegistry theDaoRegistry, TerminologyProvider theLocalSystemTerminologyProvider, ModelResolver modelResolver) {
|
||||
EvaluationProviderFactory evaluationProviderFactory(FhirContext theFhirContext, DaoRegistry theDaoRegistry,
|
||||
TerminologyProvider theLocalSystemTerminologyProvider, ModelResolver modelResolver) {
|
||||
return new ProviderFactory(theFhirContext, theDaoRegistry, theLocalSystemTerminologyProvider, modelResolver);
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,6 @@ import ca.uhn.fhir.cql.r4.helper.LibraryHelper;
|
|||
import ca.uhn.fhir.cql.r4.provider.JpaTerminologyProvider;
|
||||
import ca.uhn.fhir.cql.r4.provider.MeasureOperationsProvider;
|
||||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
import ca.uhn.fhir.jpa.rp.r4.ValueSetResourceProvider;
|
||||
import ca.uhn.fhir.jpa.term.api.ITermReadSvcR4;
|
||||
|
||||
import org.opencds.cqf.cql.engine.model.ModelResolver;
|
||||
|
@ -40,6 +39,7 @@ import java.util.Map;
|
|||
|
||||
import org.cqframework.cql.cql2elm.model.Model;
|
||||
import org.hl7.elm.r1.VersionedIdentifier;
|
||||
import org.hl7.fhir.r4.model.ValueSet;
|
||||
import org.opencds.cqf.cql.engine.fhir.model.R4FhirModelResolver;
|
||||
import org.opencds.cqf.cql.engine.terminology.TerminologyProvider;
|
||||
import org.opencds.cqf.cql.evaluator.engine.model.CachingModelResolverDecorator;
|
||||
|
@ -58,13 +58,15 @@ public class CqlR4Config extends BaseCqlConfig {
|
|||
|
||||
@Lazy
|
||||
@Bean
|
||||
TerminologyProvider terminologyProvider(ITermReadSvcR4 theITermReadSvc, ValueSetResourceProvider theValueSetResourceProvider, IValidationSupport theValidationSupport) {
|
||||
return new JpaTerminologyProvider(theITermReadSvc,theValueSetResourceProvider, theValidationSupport);
|
||||
TerminologyProvider terminologyProvider(ITermReadSvcR4 theITermReadSvc, DaoRegistry daoRegistry,
|
||||
IValidationSupport theValidationSupport) {
|
||||
return new JpaTerminologyProvider(theITermReadSvc, daoRegistry.getResourceDao(ValueSet.class), theValidationSupport);
|
||||
}
|
||||
|
||||
@Lazy
|
||||
@Bean
|
||||
EvaluationProviderFactory evaluationProviderFactory(FhirContext theFhirContext, DaoRegistry theDaoRegistry, TerminologyProvider theLocalSystemTerminologyProvider, ModelResolver modelResolver) {
|
||||
EvaluationProviderFactory evaluationProviderFactory(FhirContext theFhirContext, DaoRegistry theDaoRegistry,
|
||||
TerminologyProvider theLocalSystemTerminologyProvider, ModelResolver modelResolver) {
|
||||
return new ProviderFactory(theFhirContext, theDaoRegistry, theLocalSystemTerminologyProvider, modelResolver);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,12 +20,10 @@ package ca.uhn.fhir.cql.dstu3.provider;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
import ca.uhn.fhir.context.support.IValidationSupport.LookupCodeResult;
|
||||
import ca.uhn.fhir.context.support.ValidationSupportContext;
|
||||
import ca.uhn.fhir.context.support.ValueSetExpansionOptions;
|
||||
import ca.uhn.fhir.jpa.rp.dstu3.ValueSetResourceProvider;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.jpa.term.api.ITermReadSvcDstu3;
|
||||
|
@ -34,7 +32,6 @@ import ca.uhn.fhir.rest.param.UriParam;
|
|||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
import org.hl7.fhir.dstu3.model.IdType;
|
||||
import org.hl7.fhir.dstu3.model.ValueSet;
|
||||
import org.hl7.fhir.dstu3.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.opencds.cqf.cql.engine.runtime.Code;
|
||||
import org.opencds.cqf.cql.engine.terminology.CodeSystemInfo;
|
||||
|
@ -53,14 +50,14 @@ import java.util.List;
|
|||
public class JpaTerminologyProvider implements TerminologyProvider {
|
||||
|
||||
private ITermReadSvcDstu3 terminologySvc;
|
||||
private ValueSetResourceProvider valueSetResourceProvider;
|
||||
private IFhirResourceDao<ValueSet> valueSetDao;
|
||||
private final IValidationSupport validationSupport;
|
||||
|
||||
@Autowired
|
||||
public JpaTerminologyProvider(ITermReadSvcDstu3 terminologySvc,
|
||||
ValueSetResourceProvider valueSetResourceProvider, IValidationSupport validationSupport) {
|
||||
IFhirResourceDao<ValueSet> valueSetDao, IValidationSupport validationSupport) {
|
||||
this.terminologySvc = terminologySvc;
|
||||
this.valueSetResourceProvider = valueSetResourceProvider;
|
||||
this.valueSetDao = valueSetDao;
|
||||
this.validationSupport = validationSupport;
|
||||
}
|
||||
|
||||
|
@ -78,9 +75,8 @@ public class JpaTerminologyProvider implements TerminologyProvider {
|
|||
|
||||
@Override
|
||||
public Iterable<Code> expand(ValueSetInfo valueSet) throws ResourceNotFoundException {
|
||||
List<Code> codes = new ArrayList<>();
|
||||
boolean needsExpand = false;
|
||||
ValueSet vs = null;
|
||||
// This could possibly be refactored into a single call to the underlying HAPI Terminology service. Need to think through that..,
|
||||
ValueSet vs;
|
||||
if (valueSet.getId().startsWith("http://") || valueSet.getId().startsWith("https://")) {
|
||||
if (valueSet.getVersion() != null
|
||||
|| (valueSet.getCodeSystems() != null && valueSet.getCodeSystems().size() > 0)) {
|
||||
|
@ -90,7 +86,8 @@ public class JpaTerminologyProvider implements TerminologyProvider {
|
|||
valueSet.getId()));
|
||||
}
|
||||
}
|
||||
IBundleProvider bundleProvider = valueSetResourceProvider.getDao()
|
||||
|
||||
IBundleProvider bundleProvider = this.valueSetDao
|
||||
.search(new SearchParameterMap().add(ValueSet.SP_URL, new UriParam(valueSet.getId())));
|
||||
List<IBaseResource> valueSets = bundleProvider.getResources(0, bundleProvider.size());
|
||||
if (valueSets.isEmpty()) {
|
||||
|
@ -101,41 +98,37 @@ public class JpaTerminologyProvider implements TerminologyProvider {
|
|||
throw new IllegalArgumentException("Found more than 1 ValueSet with url: " + valueSet.getId());
|
||||
}
|
||||
} else {
|
||||
vs = valueSetResourceProvider.getDao().read(new IdType(valueSet.getId()));
|
||||
vs = this.valueSetDao.read(new IdType(valueSet.getId()));
|
||||
if (vs == null) {
|
||||
throw new IllegalArgumentException(String.format("Could not resolve value set %s.", valueSet.getId()));
|
||||
}
|
||||
if (vs != null) {
|
||||
if (vs.hasCompose()) {
|
||||
if (vs.getCompose().hasInclude()) {
|
||||
}
|
||||
|
||||
// Attempt to expand the ValueSet if it's not already expanded.
|
||||
if (!(vs.hasExpansion() && vs.getExpansion().hasContains())) {
|
||||
vs = (ValueSet)this.terminologySvc.expandValueSet(
|
||||
new ValueSetExpansionOptions().setCount(Integer.MAX_VALUE).setFailOnMissingCodeSystem(false), vs);
|
||||
}
|
||||
|
||||
List<Code> codes = new ArrayList<>();
|
||||
|
||||
// If expansion was successful, use the codes.
|
||||
if (vs.hasExpansion() && vs.getExpansion().hasContains()) {
|
||||
for (ValueSet.ValueSetExpansionContainsComponent vsecc : vs.getExpansion().getContains()) {
|
||||
codes.add(new Code().withCode(vsecc.getCode()).withSystem(vsecc.getSystem()));
|
||||
}
|
||||
}
|
||||
// If not, best-effort based on codes. Should probably make this configurable to match the behavior of the
|
||||
// underlying terminology service implementation
|
||||
else if (vs.hasCompose() && vs.getCompose().hasInclude()) {
|
||||
for (ValueSet.ConceptSetComponent include : vs.getCompose().getInclude()) {
|
||||
if (include.hasValueSet() || include.hasFilter()) {
|
||||
needsExpand = true;
|
||||
break;
|
||||
}
|
||||
for (ValueSet.ConceptReferenceComponent concept : include.getConcept()) {
|
||||
if (concept.hasCode()) {
|
||||
codes.add(new Code().withCode(concept.getCode()).withSystem(include.getSystem()));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!needsExpand) {
|
||||
return codes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (vs.hasExpansion() && vs.getExpansion().hasContains()) {
|
||||
for (ValueSetExpansionContainsComponent vsecc : vs.getExpansion().getContains()) {
|
||||
codes.add(new Code().withCode(vsecc.getCode()).withSystem(vsecc.getSystem()));
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
}
|
||||
|
||||
org.hl7.fhir.r4.model.ValueSet expansion = terminologySvc
|
||||
.expandValueSet(new ValueSetExpansionOptions().setCount(Integer.MAX_VALUE), valueSet.getId(), null);
|
||||
expansion.getExpansion().getContains()
|
||||
.forEach(concept -> codes.add(new Code().withCode(concept.getCode()).withSystem(concept.getSystem())));
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
|
|
@ -20,12 +20,11 @@ package ca.uhn.fhir.cql.r4.provider;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
import ca.uhn.fhir.context.support.IValidationSupport.LookupCodeResult;
|
||||
import ca.uhn.fhir.context.support.ValidationSupportContext;
|
||||
import ca.uhn.fhir.context.support.ValueSetExpansionOptions;
|
||||
import ca.uhn.fhir.jpa.rp.r4.ValueSetResourceProvider;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.jpa.term.api.ITermReadSvcR4;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
|
@ -49,14 +48,14 @@ import java.util.List;
|
|||
public class JpaTerminologyProvider implements TerminologyProvider {
|
||||
|
||||
private ITermReadSvcR4 terminologySvc;
|
||||
private ValueSetResourceProvider valueSetResourceProvider;
|
||||
private IFhirResourceDao<ValueSet> valueSetDao;
|
||||
private final IValidationSupport validationSupport;
|
||||
|
||||
@Autowired
|
||||
public JpaTerminologyProvider(ITermReadSvcR4 terminologySvc,
|
||||
ValueSetResourceProvider valueSetResourceProvider, IValidationSupport validationSupport) {
|
||||
public JpaTerminologyProvider(ITermReadSvcR4 terminologySvc, IFhirResourceDao<ValueSet> valueSetDao,
|
||||
IValidationSupport validationSupport) {
|
||||
this.terminologySvc = terminologySvc;
|
||||
this.valueSetResourceProvider = valueSetResourceProvider;
|
||||
this.valueSetDao = valueSetDao;
|
||||
this.validationSupport = validationSupport;
|
||||
}
|
||||
|
||||
|
@ -74,8 +73,7 @@ public class JpaTerminologyProvider implements TerminologyProvider {
|
|||
|
||||
@Override
|
||||
public Iterable<Code> expand(ValueSetInfo valueSet) throws ResourceNotFoundException {
|
||||
List<Code> codes = new ArrayList<>();
|
||||
boolean needsExpand = false;
|
||||
// This could possibly be refactored into a single call to the underlying HAPI Terminology service. Need to think through that..,
|
||||
ValueSet vs;
|
||||
if (valueSet.getId().startsWith("http://") || valueSet.getId().startsWith("https://")) {
|
||||
if (valueSet.getVersion() != null
|
||||
|
@ -86,7 +84,8 @@ public class JpaTerminologyProvider implements TerminologyProvider {
|
|||
valueSet.getId()));
|
||||
}
|
||||
}
|
||||
IBundleProvider bundleProvider = valueSetResourceProvider.getDao()
|
||||
|
||||
IBundleProvider bundleProvider = this.valueSetDao
|
||||
.search(new SearchParameterMap().add(ValueSet.SP_URL, new UriParam(valueSet.getId())));
|
||||
List<IBaseResource> valueSets = bundleProvider.getResources(0, bundleProvider.size());
|
||||
if (valueSets.isEmpty()) {
|
||||
|
@ -97,49 +96,45 @@ public class JpaTerminologyProvider implements TerminologyProvider {
|
|||
throw new IllegalArgumentException("Found more than 1 ValueSet with url: " + valueSet.getId());
|
||||
}
|
||||
} else {
|
||||
vs = valueSetResourceProvider.getDao().read(new IdType(valueSet.getId()));
|
||||
vs = this.valueSetDao.read(new IdType(valueSet.getId()));
|
||||
if (vs == null) {
|
||||
throw new IllegalArgumentException(String.format("Could not resolve value set %s.", valueSet.getId()));
|
||||
}
|
||||
if (vs != null) {
|
||||
if (vs.hasCompose()) {
|
||||
if (vs.getCompose().hasInclude()) {
|
||||
}
|
||||
|
||||
// Attempt to expand the ValueSet if it's not already expanded.
|
||||
if (!(vs.hasExpansion() && vs.getExpansion().hasContains())) {
|
||||
vs = (ValueSet)this.terminologySvc.expandValueSet(
|
||||
new ValueSetExpansionOptions().setCount(Integer.MAX_VALUE).setFailOnMissingCodeSystem(false), vs);
|
||||
}
|
||||
|
||||
List<Code> codes = new ArrayList<>();
|
||||
|
||||
// If expansion was successful, use the codes.
|
||||
if (vs.hasExpansion() && vs.getExpansion().hasContains()) {
|
||||
for (ValueSetExpansionContainsComponent vsecc : vs.getExpansion().getContains()) {
|
||||
codes.add(new Code().withCode(vsecc.getCode()).withSystem(vsecc.getSystem()));
|
||||
}
|
||||
}
|
||||
// If not, best-effort based on codes. Should probably make this configurable to match the behavior of the
|
||||
// underlying terminology service implementation
|
||||
else if (vs.hasCompose() && vs.getCompose().hasInclude()) {
|
||||
for (ValueSet.ConceptSetComponent include : vs.getCompose().getInclude()) {
|
||||
if (include.hasValueSet() || include.hasFilter()) {
|
||||
needsExpand = true;
|
||||
break;
|
||||
}
|
||||
for (ValueSet.ConceptReferenceComponent concept : include.getConcept()) {
|
||||
if (concept.hasCode()) {
|
||||
codes.add(new Code().withCode(concept.getCode()).withSystem(include.getSystem()));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!needsExpand) {
|
||||
return codes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (vs.hasExpansion() && vs.getExpansion().hasContains()) {
|
||||
for (ValueSetExpansionContainsComponent vsecc : vs.getExpansion().getContains()) {
|
||||
codes.add(new Code().withCode(vsecc.getCode()).withSystem(vsecc.getSystem()));
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ValueSet expansion = terminologySvc
|
||||
.expandValueSet(new ValueSetExpansionOptions().setCount(Integer.MAX_VALUE), valueSet.getId(), null);
|
||||
expansion.getExpansion().getContains()
|
||||
.forEach(concept -> codes.add(new Code().withCode(concept.getCode()).withSystem(concept.getSystem())));
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Code lookup(Code code, CodeSystemInfo codeSystem) throws ResourceNotFoundException {
|
||||
LookupCodeResult cs = terminologySvc.lookupCode(new ValidationSupportContext(validationSupport), codeSystem.getId(), code.getCode());
|
||||
LookupCodeResult cs = terminologySvc.lookupCode(new ValidationSupportContext(validationSupport),
|
||||
codeSystem.getId(), code.getCode());
|
||||
|
||||
code.setDisplay(cs.getCodeDisplay());
|
||||
code.setSystem(codeSystem.getId());
|
||||
|
|
|
@ -4,6 +4,10 @@ import ca.uhn.fhir.jpa.subscription.channel.config.SubscriptionChannelConfig;
|
|||
import ca.uhn.fhir.jpa.subscription.submit.config.SubscriptionSubmitterConfig;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
|
||||
|
||||
|
||||
@Configuration
|
||||
@Import({SubscriptionSubmitterConfig.class, SubscriptionChannelConfig.class})
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
package ca.uhn.fhir.cql.dstu3.provider;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.opencds.cqf.cql.engine.runtime.Code;
|
||||
import org.opencds.cqf.cql.engine.terminology.TerminologyProvider;
|
||||
import org.opencds.cqf.cql.engine.terminology.ValueSetInfo;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import ca.uhn.fhir.cql.BaseCqlDstu3Test;
|
||||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||
|
||||
public class JpaTerminologyProviderTest extends BaseCqlDstu3Test {
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(JpaTerminologyProviderTest.class);
|
||||
|
||||
@Autowired
|
||||
protected TerminologyProvider jpaTerminologyProvider;
|
||||
|
||||
@Autowired
|
||||
protected DaoConfig daoConfig;
|
||||
|
||||
@BeforeEach
|
||||
public void before() throws IOException {
|
||||
// Load executable (i.e. "pre-expanded") value set
|
||||
loadResource("dstu3/provider/test-executable-value-set.json");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTerminologyProviderExpand() {
|
||||
ValueSetInfo valueSetInfo = new ValueSetInfo().withId("http://test.com/fhir/ValueSet/test-executable-value-set");
|
||||
Iterable<Code> codeIterable = this.jpaTerminologyProvider.expand(valueSetInfo);
|
||||
|
||||
assertNotNull(codeIterable);
|
||||
|
||||
List<Code> codes = new ArrayList<>();
|
||||
|
||||
codeIterable.forEach(codes::add);
|
||||
|
||||
assertThat(codes, hasSize(2));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package ca.uhn.fhir.cql.r4;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import org.hl7.fhir.r4.model.IdType;
|
||||
import org.hl7.fhir.r4.model.MeasureReport;
|
||||
import org.hl7.fhir.r4.model.Quantity;
|
||||
import org.hl7.fhir.r4.model.MeasureReport.MeasureReportGroupPopulationComponent;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import ca.uhn.fhir.cql.BaseCqlR4Test;
|
||||
import ca.uhn.fhir.cql.common.provider.CqlProviderTestBase;
|
||||
import ca.uhn.fhir.cql.r4.provider.MeasureOperationsProvider;
|
||||
|
||||
public class CqlMeasureEvaluationR4Test extends BaseCqlR4Test implements CqlProviderTestBase {
|
||||
|
||||
private static final IdType measureId = new IdType("Measure", "measure-EXM130-7.3.000");
|
||||
private static final String periodStart = "2019-01-01";
|
||||
private static final String periodEnd = "2019-12-31";
|
||||
|
||||
@Autowired
|
||||
MeasureOperationsProvider myMeasureOperationsProvider;
|
||||
|
||||
public void loadBundles() throws IOException {
|
||||
loadBundle("r4/connectathon/EXM130-7.3.000-bundle.json");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExm130PatientNumerator() throws IOException {
|
||||
loadBundles();
|
||||
MeasureReport report = myMeasureOperationsProvider.evaluateMeasure(measureId, periodStart, periodEnd, null, "patient",
|
||||
"numer-EXM130", null, null, null, null, null, null);
|
||||
// Assert it worked
|
||||
assertThat(report.getGroup(), hasSize(1));
|
||||
assertEquals(new BigDecimal("1.0"), report.getGroupFirstRep().getMeasureScore().getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExm130PatientDenominator() throws IOException {
|
||||
loadBundles();
|
||||
MeasureReport report = myMeasureOperationsProvider.evaluateMeasure(measureId, periodStart, periodEnd, null, "patient",
|
||||
"denom-EXM130", null, null, null, null, null, null);
|
||||
// Assert it worked
|
||||
assertThat(report.getGroup(), hasSize(1));
|
||||
assertEquals(new BigDecimal("0.0"), report.getGroupFirstRep().getMeasureScore().getValue());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package ca.uhn.fhir.cql.r4.provider;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.opencds.cqf.cql.engine.runtime.Code;
|
||||
import org.opencds.cqf.cql.engine.terminology.TerminologyProvider;
|
||||
import org.opencds.cqf.cql.engine.terminology.ValueSetInfo;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import ca.uhn.fhir.cql.BaseCqlR4Test;
|
||||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||
|
||||
public class JpaTerminologyProviderTest extends BaseCqlR4Test {
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(JpaTerminologyProviderTest.class);
|
||||
|
||||
@Autowired
|
||||
protected TerminologyProvider jpaTerminologyProvider;
|
||||
|
||||
@Autowired
|
||||
protected DaoConfig daoConfig;
|
||||
|
||||
@BeforeEach
|
||||
public void before() throws IOException {
|
||||
// Load executable (i.e. "pre-expanded") value set
|
||||
loadResource("r4/provider/test-executable-value-set.json");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTerminologyProviderExpand() {
|
||||
ValueSetInfo valueSetInfo = new ValueSetInfo().withId("http://test.com/fhir/ValueSet/test-executable-value-set");
|
||||
Iterable<Code> codeIterable = this.jpaTerminologyProvider.expand(valueSetInfo);
|
||||
|
||||
assertNotNull(codeIterable);
|
||||
|
||||
List<Code> codes = new ArrayList<>();
|
||||
|
||||
codeIterable.forEach(codes::add);
|
||||
|
||||
assertThat(codes, hasSize(2));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
"resourceType": "ValueSet",
|
||||
"id": "test-executable-value-set",
|
||||
"meta" : {
|
||||
"profile" : [
|
||||
"http://hl7.org/fhir/uv/cpg/StructureDefinition/cpg-executablevalueset"
|
||||
]
|
||||
},
|
||||
"url": "http://test.com/fhir/ValueSet/test-executable-value-set",
|
||||
"extension" : [
|
||||
{
|
||||
"url" : "http://hl7.org/fhir/uv/cpg/StructureDefinition/cpg-knowledgeCapability",
|
||||
"valueCode" : "executable"
|
||||
},
|
||||
{
|
||||
"url" : "http://hl7.org/fhir/uv/cpg/StructureDefinition/cpg-knowledgeRepresentationLevel",
|
||||
"valueCode" : "executable"
|
||||
},
|
||||
{
|
||||
"url" : "http://hl7.org/fhir/uv/cpg/StructureDefinition/cpg-usageWarning",
|
||||
"valueString" : "This value set contains a point-in-time expansion enumerating the codes that meet the value set intent. As new versions of the code systems used by the value set are released, the contents of this expansion will need to be updated to incorporate newly defined codes that meet the value set intent. Before, and periodically during production use, the value set expansion contents SHOULD be updated. The value set expansion specifies the timestamp when the expansion was produced, SHOULD contain the parameters used for the expansion, and SHALL contain the codes that are obtained by evaluating the value set definition. If this is ONLY an executable value set, a distributable definition of the value set must be obtained to compute the updated expansion."
|
||||
}
|
||||
],
|
||||
"expansion": {
|
||||
"timestamp" : "2020-03-26T17:39:09-06:00",
|
||||
"contains" : [
|
||||
{
|
||||
"system" : "http://test.com/codesystem/test",
|
||||
"code" : "1234",
|
||||
"display" : "1234"
|
||||
},
|
||||
{
|
||||
"system" : "http://test.com/codesystem/test",
|
||||
"code" : "ABCD",
|
||||
"display" : "ABCD"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
"resourceType": "ValueSet",
|
||||
"id": "test-executable-value-set",
|
||||
"meta" : {
|
||||
"profile" : [
|
||||
"http://hl7.org/fhir/uv/cpg/StructureDefinition/cpg-executablevalueset"
|
||||
]
|
||||
},
|
||||
"url": "http://test.com/fhir/ValueSet/test-executable-value-set",
|
||||
"extension" : [
|
||||
{
|
||||
"url" : "http://hl7.org/fhir/uv/cpg/StructureDefinition/cpg-knowledgeCapability",
|
||||
"valueCode" : "executable"
|
||||
},
|
||||
{
|
||||
"url" : "http://hl7.org/fhir/uv/cpg/StructureDefinition/cpg-knowledgeRepresentationLevel",
|
||||
"valueCode" : "executable"
|
||||
},
|
||||
{
|
||||
"url" : "http://hl7.org/fhir/uv/cpg/StructureDefinition/cpg-usageWarning",
|
||||
"valueString" : "This value set contains a point-in-time expansion enumerating the codes that meet the value set intent. As new versions of the code systems used by the value set are released, the contents of this expansion will need to be updated to incorporate newly defined codes that meet the value set intent. Before, and periodically during production use, the value set expansion contents SHOULD be updated. The value set expansion specifies the timestamp when the expansion was produced, SHOULD contain the parameters used for the expansion, and SHALL contain the codes that are obtained by evaluating the value set definition. If this is ONLY an executable value set, a distributable definition of the value set must be obtained to compute the updated expansion."
|
||||
}
|
||||
],
|
||||
"expansion": {
|
||||
"timestamp" : "2020-03-26T17:39:09-06:00",
|
||||
"contains" : [
|
||||
{
|
||||
"system" : "http://test.com/codesystem/test",
|
||||
"code" : "1234",
|
||||
"display" : "1234"
|
||||
},
|
||||
{
|
||||
"system" : "http://test.com/codesystem/test",
|
||||
"code" : "ABCD",
|
||||
"display" : "ABCD"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue