fixing value expansion filtered by url (#5969)
* test * adding support for expansion based on filters and properties * added changelog * adding test cases * spotless * fixed some warnings * spotless * merge conflict resolution --------- Co-authored-by: leif stawnyczy <leifstawnyczy@leifs-mbp.home>
This commit is contained in:
parent
48c387ecb0
commit
5b75639718
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
type: add
|
||||
issue: 5968
|
||||
title: "Added support for filtering on CodeSystem defined properties when
|
||||
using database (hibernate) filtering.
|
||||
The following ValueSet filters can be used to filter on
|
||||
CodeSystem defined properties: EQUAL, EXISTS, IN, NOTIN
|
||||
"
|
|
@ -118,7 +118,7 @@ public class TermConceptProperty implements Serializable {
|
|||
private byte[] myValueBin;
|
||||
|
||||
@Enumerated(EnumType.ORDINAL)
|
||||
@Column(name = "PROP_TYPE", nullable = false, length = MAX_PROPTYPE_ENUM_LENGTH)
|
||||
@Column(name = "PROP_TYPE", nullable = false)
|
||||
@JdbcTypeCode(SqlTypes.INTEGER)
|
||||
private TermConceptPropertyTypeEnum myType;
|
||||
|
||||
|
|
|
@ -21,13 +21,11 @@ package ca.uhn.fhir.jpa.entity;
|
|||
|
||||
/**
|
||||
* @see TermConceptProperty#getType()
|
||||
* @see TermConceptProperty#MAX_PROPTYPE_ENUM_LENGTH
|
||||
*/
|
||||
public enum TermConceptPropertyTypeEnum {
|
||||
/*
|
||||
* VALUES SHOULD BE <= 6 CHARS LONG!
|
||||
*
|
||||
* We store this in a DB column of that length
|
||||
/**
|
||||
* Do not change order - the ordinal is used by hibernate in the column.
|
||||
* TermConceptProperty#getType()
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -37,5 +35,21 @@ public enum TermConceptPropertyTypeEnum {
|
|||
/**
|
||||
* Coding
|
||||
*/
|
||||
CODING
|
||||
CODING,
|
||||
/**
|
||||
* Boolean values
|
||||
*/
|
||||
BOOLEAN,
|
||||
/**
|
||||
* Integer values
|
||||
*/
|
||||
INTEGER,
|
||||
/**
|
||||
* Decimal or float values.
|
||||
*/
|
||||
DECIMAL,
|
||||
/**
|
||||
* Date and time values.
|
||||
*/
|
||||
DATETIME
|
||||
}
|
||||
|
|
|
@ -133,6 +133,8 @@ import org.hl7.fhir.r4.model.CanonicalType;
|
|||
import org.hl7.fhir.r4.model.CodeSystem;
|
||||
import org.hl7.fhir.r4.model.CodeableConcept;
|
||||
import org.hl7.fhir.r4.model.Coding;
|
||||
import org.hl7.fhir.r4.model.DateTimeType;
|
||||
import org.hl7.fhir.r4.model.DecimalType;
|
||||
import org.hl7.fhir.r4.model.DomainResource;
|
||||
import org.hl7.fhir.r4.model.Enumerations;
|
||||
import org.hl7.fhir.r4.model.Extension;
|
||||
|
@ -1159,7 +1161,6 @@ public class TermReadSvcImpl implements ITermReadSvc, IHasScheduledJobs {
|
|||
int accumulatedBatchesSoFar = 0;
|
||||
for (var next : searchProps.getSearchScroll()) {
|
||||
try (SearchScroll<EntityReference> scroll = next.get()) {
|
||||
|
||||
ourLog.debug(
|
||||
"Beginning batch expansion for {} with max results per batch: {}",
|
||||
(theAdd ? "inclusion" : "exclusion"),
|
||||
|
@ -1394,7 +1395,10 @@ public class TermReadSvcImpl implements ITermReadSvc, IHasScheduledJobs {
|
|||
return;
|
||||
}
|
||||
|
||||
if (isBlank(theFilter.getValue()) || theFilter.getOp() == null || isBlank(theFilter.getProperty())) {
|
||||
// if filter type is EXISTS, there's no reason to worry about the value (we won't set it anyways)
|
||||
if ((isBlank(theFilter.getValue()) && theFilter.getOp() != ValueSet.FilterOperator.EXISTS)
|
||||
|| theFilter.getOp() == null
|
||||
|| isBlank(theFilter.getProperty())) {
|
||||
throw new InvalidRequestException(
|
||||
Msg.code(891) + "Invalid filter, must have fields populated: property op value");
|
||||
}
|
||||
|
@ -1441,8 +1445,37 @@ public class TermReadSvcImpl implements ITermReadSvc, IHasScheduledJobs {
|
|||
ValueSet.ConceptSetFilterComponent theFilter) {
|
||||
|
||||
String value = theFilter.getValue();
|
||||
if (theFilter.getOp() == ValueSet.FilterOperator.EXISTS) {
|
||||
// EXISTS has no value and is thus handled differently
|
||||
Term term = new Term(CONCEPT_PROPERTY_PREFIX_NAME + theFilter.getProperty());
|
||||
theB.must(theF.exists().field(term.field()));
|
||||
} else {
|
||||
Term term = new Term(CONCEPT_PROPERTY_PREFIX_NAME + theFilter.getProperty(), value);
|
||||
switch (theFilter.getOp()) {
|
||||
case EQUAL:
|
||||
theB.must(theF.match().field(term.field()).matching(term.text()));
|
||||
break;
|
||||
case IN:
|
||||
case NOTIN:
|
||||
boolean isNotFilter = theFilter.getOp() == ValueSet.FilterOperator.NOTIN;
|
||||
// IN and NOTIN expect comma separated lists
|
||||
String[] values = term.text().split(",");
|
||||
Set<String> valueSet = new HashSet<>(Arrays.asList(values));
|
||||
if (isNotFilter) {
|
||||
theB.filter(theF.not(theF.terms().field(term.field()).matchingAny(valueSet)));
|
||||
} else {
|
||||
theB.filter(theF.terms().field(term.field()).matchingAny(valueSet));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* We do not need to handle REGEX, because that's handled in parent
|
||||
* We also don't handle EXISTS because that's a separate area (with different term)
|
||||
*/
|
||||
throw new InvalidRequestException(Msg.code(2526) + "Unsupported property filter "
|
||||
+ theFilter.getOp().getDisplay());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleFilterRegex(
|
||||
|
@ -1598,7 +1631,7 @@ public class TermReadSvcImpl implements ITermReadSvc, IHasScheduledJobs {
|
|||
SearchPredicateFactory f,
|
||||
BooleanPredicateClausesStep<?> b,
|
||||
ValueSet.ConceptSetFilterComponent theFilter) {
|
||||
TermConcept code = findCodeForFilterCriteria(theSystem, theFilter);
|
||||
TermConcept code = findCodeForFilterCriteriaCodeOrConcept(theSystem, theFilter);
|
||||
|
||||
if (theFilter.getOp() == ValueSet.FilterOperator.ISA) {
|
||||
ourLog.debug(
|
||||
|
@ -1621,7 +1654,8 @@ public class TermReadSvcImpl implements ITermReadSvc, IHasScheduledJobs {
|
|||
}
|
||||
|
||||
@Nonnull
|
||||
private TermConcept findCodeForFilterCriteria(String theSystem, ValueSet.ConceptSetFilterComponent theFilter) {
|
||||
private TermConcept findCodeForFilterCriteriaCodeOrConcept(
|
||||
String theSystem, ValueSet.ConceptSetFilterComponent theFilter) {
|
||||
return findCode(theSystem, theFilter.getValue())
|
||||
.orElseThrow(() ->
|
||||
new InvalidRequestException(Msg.code(2071) + "Invalid filter criteria - code does not exist: {"
|
||||
|
@ -1866,18 +1900,23 @@ public class TermReadSvcImpl implements ITermReadSvc, IHasScheduledJobs {
|
|||
|
||||
for (ValueSet.ConceptSetFilterComponent nextFilter : theInclude.getFilter()) {
|
||||
boolean handled = false;
|
||||
switch (nextFilter.getProperty()) {
|
||||
switch (nextFilter.getProperty().toLowerCase()) {
|
||||
case "concept":
|
||||
case "code":
|
||||
if (nextFilter.getOp() == ValueSet.FilterOperator.ISA) {
|
||||
theValueSetCodeAccumulator.addMessage(
|
||||
"Processing IS-A filter in database - Note that Hibernate Search is not enabled on this server, so this operation can be inefficient.");
|
||||
TermConcept code = findCodeForFilterCriteria(theSystem, nextFilter);
|
||||
TermConcept code = findCodeForFilterCriteriaCodeOrConcept(theSystem, nextFilter);
|
||||
addConceptAndChildren(
|
||||
theValueSetCodeAccumulator, theAddedCodes, theInclude, theSystem, theAdd, code);
|
||||
handled = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// TODO - we need to handle other properties (fields)
|
||||
// and other operations (not just is-a)
|
||||
// in some (preferably generic) way
|
||||
break;
|
||||
}
|
||||
|
||||
if (!handled) {
|
||||
|
@ -3300,6 +3339,20 @@ public class TermReadSvcImpl implements ITermReadSvc, IHasScheduledJobs {
|
|||
if (next.getValue() instanceof StringType) {
|
||||
property.setType(TermConceptPropertyTypeEnum.STRING);
|
||||
property.setValue(next.getValueStringType().getValue());
|
||||
} else if (next.getValue() instanceof BooleanType) {
|
||||
property.setType(TermConceptPropertyTypeEnum.BOOLEAN);
|
||||
property.setValue(((BooleanType) next.getValue()).getValueAsString());
|
||||
} else if (next.getValue() instanceof IntegerType) {
|
||||
property.setType(TermConceptPropertyTypeEnum.INTEGER);
|
||||
property.setValue(((IntegerType) next.getValue()).getValueAsString());
|
||||
} else if (next.getValue() instanceof DecimalType) {
|
||||
property.setType(TermConceptPropertyTypeEnum.DECIMAL);
|
||||
property.setValue(((DecimalType) next.getValue()).getValueAsString());
|
||||
} else if (next.getValue() instanceof DateTimeType) {
|
||||
// DateType is not supported because it's not
|
||||
// supported in CodeSystem.setValue
|
||||
property.setType(TermConceptPropertyTypeEnum.DATETIME);
|
||||
property.setValue(((DateTimeType) next.getValue()).getValueAsString());
|
||||
} else if (next.getValue() instanceof Coding) {
|
||||
Coding nextCoding = next.getValueCoding();
|
||||
property.setType(TermConceptPropertyTypeEnum.CODING);
|
||||
|
@ -3307,7 +3360,6 @@ public class TermReadSvcImpl implements ITermReadSvc, IHasScheduledJobs {
|
|||
property.setValue(nextCoding.getCode());
|
||||
property.setDisplay(nextCoding.getDisplay());
|
||||
} else if (next.getValue() != null) {
|
||||
// TODO: LOINC has properties of type BOOLEAN that we should handle
|
||||
ourLog.warn("Don't know how to handle properties of type: "
|
||||
+ next.getValue().getClass());
|
||||
continue;
|
||||
|
|
|
@ -3,6 +3,7 @@ package ca.uhn.fhir.jpa.term;
|
|||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.jpa.api.config.JpaStorageSettings;
|
||||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoCodeSystem;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirSystemDao;
|
||||
|
@ -66,7 +67,7 @@ import static org.mockito.Mockito.when;
|
|||
@ExtendWith(SpringExtension.class)
|
||||
@ContextConfiguration(classes = TestR4ConfigWithElasticHSearch.class)
|
||||
@RequiresDocker
|
||||
public class ValueSetExpansionR4ElasticsearchIT extends BaseJpaTest {
|
||||
public class ValueSetExpansionR4ElasticsearchIT extends BaseJpaTest implements IValueSetExpansionIT {
|
||||
|
||||
protected static final String CS_URL = "http://example.com/my_code_system";
|
||||
@Autowired
|
||||
|
@ -118,6 +119,41 @@ public class ValueSetExpansionR4ElasticsearchIT extends BaseJpaTest {
|
|||
purgeDatabase(myStorageSettings, mySystemDao, myResourceReindexingSvc, mySearchCoordinatorSvc, mySearchParamRegistry, myBulkDataExportJobSchedulingHelper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FhirContext getFhirContext() {
|
||||
return myFhirContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITermDeferredStorageSvc getTerminologyDefferedStorageService() {
|
||||
return myTerminologyDeferredStorageSvc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITermReadSvc getTerminologyReadSvc() {
|
||||
return myTermSvc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DaoRegistry getDaoRegistry() {
|
||||
return myDaoRegistry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IFhirResourceDaoValueSet<ValueSet> getValueSetDao() {
|
||||
return myValueSetDao;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JpaStorageSettings getJpaStorageSettings() {
|
||||
return myStorageSettings;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PlatformTransactionManager getTxManager() {
|
||||
return myTxManager;
|
||||
}
|
||||
|
||||
void createCodeSystem() {
|
||||
CodeSystem codeSystem = new CodeSystem();
|
||||
codeSystem.setUrl(CS_URL);
|
||||
|
@ -332,15 +368,4 @@ public class ValueSetExpansionR4ElasticsearchIT extends BaseJpaTest {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected FhirContext getFhirContext() {
|
||||
return myFhirContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PlatformTransactionManager getTxManager() {
|
||||
return myTxManager;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
package ca.uhn.fhir.jpa.term;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.context.support.ConceptValidationOptions;
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
import ca.uhn.fhir.context.support.ValueSetExpansionOptions;
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.jpa.api.config.JpaStorageSettings;
|
||||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
|
||||
import ca.uhn.fhir.jpa.entity.TermCodeSystem;
|
||||
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
|
||||
import ca.uhn.fhir.jpa.entity.TermConcept;
|
||||
|
@ -17,12 +18,15 @@ import ca.uhn.fhir.jpa.entity.TermValueSetPreExpansionStatusEnum;
|
|||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
||||
import ca.uhn.fhir.jpa.search.builder.SearchBuilder;
|
||||
import ca.uhn.fhir.jpa.term.api.ITermDeferredStorageSvc;
|
||||
import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
|
||||
import ca.uhn.fhir.jpa.term.custom.CustomTerminologySet;
|
||||
import ca.uhn.fhir.jpa.util.SqlQuery;
|
||||
import ca.uhn.fhir.jpa.util.ValueSetTestUtil;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import com.google.common.collect.Lists;
|
||||
import jakarta.annotation.Nonnull;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.r4.model.Bundle;
|
||||
|
@ -43,7 +47,6 @@ import org.springframework.transaction.TransactionStatus;
|
|||
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import jakarta.annotation.Nonnull;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
@ -51,17 +54,17 @@ import java.util.stream.Collectors;
|
|||
|
||||
import static ca.uhn.fhir.util.HapiExtensions.EXT_VALUESET_EXPANSION_MESSAGE;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
import static org.awaitility.Awaitility.await;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
|
||||
public class ValueSetExpansionR4Test extends BaseTermR4Test {
|
||||
public class ValueSetExpansionR4Test extends BaseTermR4Test implements IValueSetExpansionIT {
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(ValueSetExpansionR4Test.class);
|
||||
|
||||
private final ValueSetTestUtil myValueSetTestUtil = new ValueSetTestUtil(FhirVersionEnum.R4);
|
||||
|
@ -71,6 +74,31 @@ public class ValueSetExpansionR4Test extends BaseTermR4Test {
|
|||
SearchBuilder.setMaxPageSize50ForTest(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITermDeferredStorageSvc getTerminologyDefferedStorageService() {
|
||||
return myTerminologyDeferredStorageSvc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITermReadSvc getTerminologyReadSvc() {
|
||||
return myTermSvc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DaoRegistry getDaoRegistry() {
|
||||
return myDaoRegistry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IFhirResourceDaoValueSet<ValueSet> getValueSetDao() {
|
||||
return myValueSetDao;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JpaStorageSettings getJpaStorageSettings() {
|
||||
return myStorageSettings;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeletePreExpandedValueSet() throws IOException {
|
||||
myStorageSettings.setPreExpandValueSets(true);
|
||||
|
@ -2046,5 +2074,4 @@ public class ValueSetExpansionR4Test extends BaseTermR4Test {
|
|||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,601 @@
|
|||
package ca.uhn.fhir.jpa.term;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.support.ValueSetExpansionOptions;
|
||||
import ca.uhn.fhir.jpa.api.config.JpaStorageSettings;
|
||||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
|
||||
import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome;
|
||||
import ca.uhn.fhir.jpa.term.api.ITermDeferredStorageSvc;
|
||||
import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.api.server.SystemRequestDetails;
|
||||
import org.hl7.fhir.r4.model.CodeSystem;
|
||||
import org.hl7.fhir.r4.model.DateTimeType;
|
||||
import org.hl7.fhir.r4.model.DecimalType;
|
||||
import org.hl7.fhir.r4.model.IntegerType;
|
||||
import org.hl7.fhir.r4.model.ValueSet;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.EnumSource;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
public interface IValueSetExpansionIT {
|
||||
static final String CODE_SYSTEM_CODE = "PRODUCT-MULTI-SOURCE";
|
||||
static final String PROPERTY_NAME = "ACTIVE";
|
||||
|
||||
static final String CODE_SYSTEM_STR_BASE =
|
||||
"""
|
||||
{
|
||||
"resourceType": "CodeSystem",
|
||||
"id": "4fb48e4e-57a4-4844-be74-d93707bdf9a1",
|
||||
"meta": {
|
||||
"versionId": "4",
|
||||
"lastUpdated": "2024-01-16T19:10:18.370+00:00",
|
||||
"source": "#c8957026d46dfab5"
|
||||
},
|
||||
"url": "https://health.gov.on.ca/idms/fhir/CodeSystem/Internal-Product-Types",
|
||||
"version": "1.0.0",
|
||||
"name": "IDMS-Internal-Product-Types",
|
||||
"status": "active",
|
||||
"date": "2024-01-10",
|
||||
"publisher": "IDMS",
|
||||
"description": "This contains a lists of Product Type codes.",
|
||||
"content": "complete",
|
||||
"property": [{
|
||||
"code": "ACTIVE",
|
||||
"type": "boolean"
|
||||
}],
|
||||
"concept": [
|
||||
{
|
||||
"code": "PRODUCT-MULTI-SOURCE",
|
||||
"display": "Multi source drug product streamlined or Multi source drug product non- streamlined",
|
||||
"property": [
|
||||
{
|
||||
"code": "ACTIVE",
|
||||
"valueBoolean": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
""";
|
||||
|
||||
static final String VALUE_SET_STR_BASE =
|
||||
"""
|
||||
{
|
||||
"resourceType": "ValueSet",
|
||||
"id": "e0324e95-6d5c-4b08-8832-d5f5cd00a29a",
|
||||
"meta": {
|
||||
"versionId": "7",
|
||||
"lastUpdated": "2024-01-16T19:03:43.313+00:00",
|
||||
"source": "#1f91b035f91cd290"
|
||||
},
|
||||
"url": "https://health.gov.on.ca/idms/fhir/ValueSet/IDMS-Product-Types",
|
||||
"version": "1.0.0",
|
||||
"name": "IDMS-Product-Types",
|
||||
"title": "IDMS Product Types",
|
||||
"status": "active",
|
||||
"experimental": false,
|
||||
"date": "2024-01-16",
|
||||
"publisher": "IDMS",
|
||||
"description": "List of Product Types",
|
||||
"compose": {
|
||||
"include": [
|
||||
{
|
||||
"system": "https://health.gov.on.ca/idms/fhir/CodeSystem/Internal-Product-Types",
|
||||
"filter": [
|
||||
{
|
||||
"property": "ACTIVE",
|
||||
"op": "=",
|
||||
"value": "true"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
FhirContext getFhirContext();
|
||||
|
||||
ITermDeferredStorageSvc getTerminologyDefferedStorageService();
|
||||
|
||||
ITermReadSvc getTerminologyReadSvc();
|
||||
|
||||
DaoRegistry getDaoRegistry();
|
||||
|
||||
IFhirResourceDaoValueSet<ValueSet> getValueSetDao();
|
||||
|
||||
JpaStorageSettings getJpaStorageSettings();
|
||||
|
||||
@ParameterizedTest
|
||||
@EnumSource(
|
||||
value = ValueSet.FilterOperator.class,
|
||||
mode = EnumSource.Mode.INCLUDE,
|
||||
names = {"EQUAL", "EXISTS", "IN", "NOTIN"})
|
||||
default void expandByIdentifier_withFiltersThatShouldNotMatchInInclude_addsNoNewCodes(
|
||||
ValueSet.FilterOperator theOperator) {
|
||||
// setup
|
||||
IParser parser = getFhirContext().newJsonParser();
|
||||
|
||||
// setup codesystem
|
||||
CodeSystem codeSystem = parser.parseResource(CodeSystem.class, CODE_SYSTEM_STR_BASE);
|
||||
CodeSystem.ConceptDefinitionComponent conceptDefinitionComponent =
|
||||
codeSystem.getConcept().get(0);
|
||||
CodeSystem.ConceptPropertyComponent propertyComponent = new CodeSystem.ConceptPropertyComponent();
|
||||
propertyComponent.setCode(PROPERTY_NAME);
|
||||
propertyComponent.setValue(new IntegerType(1));
|
||||
conceptDefinitionComponent.setProperty(List.of(propertyComponent));
|
||||
|
||||
// setup valueset
|
||||
ValueSet valueSet = parser.parseResource(ValueSet.class, VALUE_SET_STR_BASE);
|
||||
ValueSet.ConceptSetComponent conceptSetComponent =
|
||||
valueSet.getCompose().getInclude().get(0);
|
||||
ValueSet.ConceptSetFilterComponent filterComponent = new ValueSet.ConceptSetFilterComponent();
|
||||
filterComponent.setProperty(PROPERTY_NAME);
|
||||
filterComponent.setOp(theOperator);
|
||||
switch (theOperator) {
|
||||
case EXISTS -> {
|
||||
filterComponent.setProperty(PROPERTY_NAME + "-not");
|
||||
filterComponent.setValue(null);
|
||||
}
|
||||
case IN -> filterComponent.setValue("2,3,4");
|
||||
case NOTIN -> filterComponent.setValue("1,2,3");
|
||||
case EQUAL -> filterComponent.setValue("2");
|
||||
default ->
|
||||
// just in case
|
||||
fail(theOperator.getDisplay() + " is not added for testing");
|
||||
}
|
||||
conceptSetComponent.setFilter(List.of(filterComponent));
|
||||
|
||||
// test
|
||||
boolean preExpand = getJpaStorageSettings().isPreExpandValueSets();
|
||||
getJpaStorageSettings().setPreExpandValueSets(true);
|
||||
try {
|
||||
doFailedValueSetExpansionTest(codeSystem, valueSet);
|
||||
} finally {
|
||||
getJpaStorageSettings().setPreExpandValueSets(preExpand);
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@EnumSource(
|
||||
value = ValueSet.FilterOperator.class,
|
||||
mode = EnumSource.Mode.INCLUDE,
|
||||
names = {"EQUAL", "EXISTS", "IN", "NOTIN"})
|
||||
default void expandByIdentifier_withBooleanFilteredValuesInInclude_addsMatchingValues(
|
||||
ValueSet.FilterOperator theOperator) {
|
||||
// setup
|
||||
IParser parser = getFhirContext().newJsonParser();
|
||||
// setup codesystem (nothing to do - base is already boolean friendly)
|
||||
CodeSystem codeSystem = parser.parseResource(CodeSystem.class, CODE_SYSTEM_STR_BASE);
|
||||
|
||||
// setup valueset
|
||||
ValueSet valueSet = parser.parseResource(ValueSet.class, VALUE_SET_STR_BASE);
|
||||
ValueSet.ConceptSetComponent conceptSetComponent =
|
||||
valueSet.getCompose().getInclude().get(0);
|
||||
ValueSet.ConceptSetFilterComponent filterComponent = new ValueSet.ConceptSetFilterComponent();
|
||||
filterComponent.setProperty(PROPERTY_NAME);
|
||||
filterComponent.setOp(theOperator);
|
||||
switch (theOperator) {
|
||||
case EQUAL, EXISTS, IN -> filterComponent.setValue("true");
|
||||
case NOTIN -> filterComponent.setValue("false");
|
||||
}
|
||||
conceptSetComponent.setFilter(List.of(filterComponent)); // overwrite the filter
|
||||
|
||||
boolean preExpand = getJpaStorageSettings().isPreExpandValueSets();
|
||||
|
||||
getJpaStorageSettings().setPreExpandValueSets(true);
|
||||
try {
|
||||
ValueSet expanded = doSuccessfulValueSetExpansionTest(codeSystem, valueSet);
|
||||
assertTrue(expanded.getExpansion().getContains().stream()
|
||||
.anyMatch(c -> c.getCode().equals(CODE_SYSTEM_CODE)));
|
||||
} finally {
|
||||
getJpaStorageSettings().setPreExpandValueSets(preExpand);
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@EnumSource(
|
||||
value = ValueSet.FilterOperator.class,
|
||||
mode = EnumSource.Mode.INCLUDE,
|
||||
names = {"EQUAL", "EXISTS", "IN", "NOTIN"})
|
||||
default void expandByIdentifier_withIntegerFilteredValuesInInclude_addsMatchingValues(
|
||||
ValueSet.FilterOperator theOperator) {
|
||||
// setup
|
||||
IParser parser = getFhirContext().newJsonParser();
|
||||
|
||||
// setup codesystem
|
||||
CodeSystem codeSystem = parser.parseResource(CodeSystem.class, CODE_SYSTEM_STR_BASE);
|
||||
CodeSystem.ConceptDefinitionComponent conceptDefinitionComponent =
|
||||
codeSystem.getConcept().get(0);
|
||||
CodeSystem.ConceptPropertyComponent propertyComponent = new CodeSystem.ConceptPropertyComponent();
|
||||
propertyComponent.setCode(PROPERTY_NAME);
|
||||
propertyComponent.setValue(new IntegerType(1));
|
||||
conceptDefinitionComponent.setProperty(List.of(propertyComponent));
|
||||
|
||||
// setup valueset
|
||||
ValueSet valueSet = parser.parseResource(ValueSet.class, VALUE_SET_STR_BASE);
|
||||
ValueSet.ConceptSetComponent conceptSetComponent =
|
||||
valueSet.getCompose().getInclude().get(0);
|
||||
ValueSet.ConceptSetFilterComponent filterComponent = new ValueSet.ConceptSetFilterComponent();
|
||||
filterComponent.setProperty(PROPERTY_NAME);
|
||||
filterComponent.setOp(theOperator);
|
||||
switch (theOperator) {
|
||||
case EQUAL, EXISTS, IN -> filterComponent.setValue("1");
|
||||
case NOTIN -> filterComponent.setValue("2,3,4");
|
||||
}
|
||||
conceptSetComponent.setFilter(List.of(filterComponent));
|
||||
|
||||
boolean preExpand = getJpaStorageSettings().isPreExpandValueSets();
|
||||
|
||||
getJpaStorageSettings().setPreExpandValueSets(true);
|
||||
try {
|
||||
ValueSet expanded = doSuccessfulValueSetExpansionTest(codeSystem, valueSet);
|
||||
|
||||
assertTrue(expanded.getExpansion().getContains().stream()
|
||||
.anyMatch(c -> c.getCode().equals(CODE_SYSTEM_CODE)));
|
||||
} finally {
|
||||
getJpaStorageSettings().setPreExpandValueSets(preExpand);
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@EnumSource(
|
||||
value = ValueSet.FilterOperator.class,
|
||||
mode = EnumSource.Mode.INCLUDE,
|
||||
names = {"EQUAL", "EXISTS", "IN", "NOTIN"})
|
||||
default void expandByIdentifier_withDecimalFilteredValuesInInclude_addsMatchingValues(
|
||||
ValueSet.FilterOperator theOperator) {
|
||||
// setup
|
||||
IParser parser = getFhirContext().newJsonParser();
|
||||
|
||||
// setup code system
|
||||
CodeSystem codeSystem = parser.parseResource(CodeSystem.class, CODE_SYSTEM_STR_BASE);
|
||||
CodeSystem.ConceptDefinitionComponent conceptDefinitionComponent =
|
||||
codeSystem.getConcept().get(0);
|
||||
CodeSystem.ConceptPropertyComponent propertyComponent = new CodeSystem.ConceptPropertyComponent();
|
||||
propertyComponent.setCode(PROPERTY_NAME);
|
||||
propertyComponent.setValue(new DecimalType(1.1));
|
||||
conceptDefinitionComponent.setProperty(List.of(propertyComponent));
|
||||
|
||||
// setup valueset
|
||||
ValueSet valueSet = parser.parseResource(ValueSet.class, VALUE_SET_STR_BASE);
|
||||
ValueSet.ConceptSetComponent conceptSetComponent =
|
||||
valueSet.getCompose().getInclude().get(0);
|
||||
ValueSet.ConceptSetFilterComponent filterComponent = new ValueSet.ConceptSetFilterComponent();
|
||||
filterComponent.setProperty(PROPERTY_NAME);
|
||||
filterComponent.setOp(theOperator);
|
||||
switch (theOperator) {
|
||||
case EQUAL, EXISTS, IN -> filterComponent.setValue("1.1");
|
||||
case NOTIN -> filterComponent.setValue("2.1,3.2,4.3");
|
||||
}
|
||||
conceptSetComponent.setFilter(List.of(filterComponent));
|
||||
|
||||
boolean preExpand = getJpaStorageSettings().isPreExpandValueSets();
|
||||
|
||||
getJpaStorageSettings().setPreExpandValueSets(true);
|
||||
try {
|
||||
ValueSet expanded = doSuccessfulValueSetExpansionTest(codeSystem, valueSet);
|
||||
|
||||
assertTrue(expanded.getExpansion().getContains().stream()
|
||||
.anyMatch(c -> c.getCode().equals(CODE_SYSTEM_CODE)));
|
||||
} finally {
|
||||
getJpaStorageSettings().setPreExpandValueSets(preExpand);
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@EnumSource(
|
||||
value = ValueSet.FilterOperator.class,
|
||||
mode = EnumSource.Mode.INCLUDE,
|
||||
names = {"EQUAL", "EXISTS", "IN", "NOTIN"})
|
||||
default void expandByIdentifier_withDateTimeFilteredValuesInInclude_addsMatchingValues(
|
||||
ValueSet.FilterOperator theOperator) {
|
||||
// setup
|
||||
IParser parser = getFhirContext().newJsonParser();
|
||||
Date now = new Date();
|
||||
DateTimeType dt = new DateTimeType(now);
|
||||
|
||||
// setup codesystem
|
||||
CodeSystem codeSystem = parser.parseResource(CodeSystem.class, CODE_SYSTEM_STR_BASE);
|
||||
CodeSystem.ConceptDefinitionComponent conceptDefinitionComponent =
|
||||
codeSystem.getConcept().get(0);
|
||||
CodeSystem.ConceptPropertyComponent propertyComponent = new CodeSystem.ConceptPropertyComponent();
|
||||
propertyComponent.setCode(PROPERTY_NAME);
|
||||
propertyComponent.setValue(dt);
|
||||
conceptDefinitionComponent.setProperty(List.of(propertyComponent));
|
||||
|
||||
// setup valueset
|
||||
ValueSet valueSet = parser.parseResource(ValueSet.class, VALUE_SET_STR_BASE);
|
||||
ValueSet.ConceptSetComponent conceptSetComponent =
|
||||
valueSet.getCompose().getInclude().get(0);
|
||||
ValueSet.ConceptSetFilterComponent filterComponent = new ValueSet.ConceptSetFilterComponent();
|
||||
filterComponent.setProperty(PROPERTY_NAME);
|
||||
filterComponent.setOp(theOperator);
|
||||
|
||||
switch (theOperator) {
|
||||
case EQUAL, EXISTS, IN -> filterComponent.setValue(dt.getValueAsString());
|
||||
case NOTIN -> {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 1; i < 3; i++) {
|
||||
DateTimeType arbitraryDateTime =
|
||||
new DateTimeType(Date.from(Instant.now().minus(i, ChronoUnit.SECONDS)));
|
||||
if (!sb.isEmpty()) {
|
||||
sb.append(",");
|
||||
}
|
||||
sb.append(arbitraryDateTime.getValueAsString());
|
||||
}
|
||||
filterComponent.setValue(sb.toString());
|
||||
}
|
||||
}
|
||||
conceptSetComponent.setFilter(List.of(filterComponent));
|
||||
|
||||
boolean preExpand = getJpaStorageSettings().isPreExpandValueSets();
|
||||
|
||||
getJpaStorageSettings().setPreExpandValueSets(true);
|
||||
try {
|
||||
ValueSet expanded = doSuccessfulValueSetExpansionTest(codeSystem, valueSet);
|
||||
|
||||
assertTrue(expanded.getExpansion().getContains().stream()
|
||||
.anyMatch(c -> c.getCode().equals(CODE_SYSTEM_CODE)));
|
||||
} finally {
|
||||
getJpaStorageSettings().setPreExpandValueSets(preExpand);
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@EnumSource(
|
||||
value = ValueSet.FilterOperator.class,
|
||||
mode = EnumSource.Mode.INCLUDE,
|
||||
names = {"EQUAL", "EXISTS", "IN", "NOTIN"})
|
||||
default void expandByIdentifier_withBooleanFilterInExclude_doesNotAddMatchingCode(
|
||||
ValueSet.FilterOperator theOperator) {
|
||||
// setup
|
||||
IParser parser = getFhirContext().newJsonParser();
|
||||
// setup codesystem (nothing to do - base is already boolean friendly)
|
||||
CodeSystem codeSystem = parser.parseResource(CodeSystem.class, CODE_SYSTEM_STR_BASE);
|
||||
|
||||
// setup valueset
|
||||
ValueSet valueSet = parser.parseResource(ValueSet.class, VALUE_SET_STR_BASE);
|
||||
ValueSet.ValueSetComposeComponent composeComponent = valueSet.getCompose();
|
||||
ValueSet.ConceptSetComponent exclude = composeComponent.getInclude().get(0);
|
||||
ValueSet.ConceptSetFilterComponent filterComponent = new ValueSet.ConceptSetFilterComponent();
|
||||
filterComponent.setProperty(PROPERTY_NAME);
|
||||
filterComponent.setOp(theOperator);
|
||||
switch (theOperator) {
|
||||
case EQUAL, EXISTS, IN -> filterComponent.setValue("true");
|
||||
case NOTIN -> filterComponent.setValue("false");
|
||||
}
|
||||
exclude.setFilter(List.of(filterComponent));
|
||||
composeComponent.setExclude(List.of(exclude));
|
||||
composeComponent.setInclude(null);
|
||||
|
||||
boolean preExpand = getJpaStorageSettings().isPreExpandValueSets();
|
||||
|
||||
getJpaStorageSettings().setPreExpandValueSets(true);
|
||||
try {
|
||||
doFailedValueSetExpansionTest(codeSystem, valueSet);
|
||||
} finally {
|
||||
getJpaStorageSettings().setPreExpandValueSets(preExpand);
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@EnumSource(
|
||||
value = ValueSet.FilterOperator.class,
|
||||
mode = EnumSource.Mode.INCLUDE,
|
||||
names = {"EQUAL", "EXISTS", "IN", "NOTIN"})
|
||||
default void expandByIdentifier_withIntegerFilteredValuesInExclude_doesNotAddMatchingCode(
|
||||
ValueSet.FilterOperator theOperator) {
|
||||
// setup
|
||||
IParser parser = getFhirContext().newJsonParser();
|
||||
|
||||
// setup codesystem
|
||||
CodeSystem codeSystem = parser.parseResource(CodeSystem.class, CODE_SYSTEM_STR_BASE);
|
||||
CodeSystem.ConceptDefinitionComponent conceptDefinitionComponent =
|
||||
codeSystem.getConcept().get(0);
|
||||
CodeSystem.ConceptPropertyComponent propertyComponent = new CodeSystem.ConceptPropertyComponent();
|
||||
propertyComponent.setCode(PROPERTY_NAME);
|
||||
propertyComponent.setValue(new IntegerType(1));
|
||||
conceptDefinitionComponent.setProperty(List.of(propertyComponent));
|
||||
|
||||
// setup valueset
|
||||
ValueSet valueSet = parser.parseResource(ValueSet.class, VALUE_SET_STR_BASE);
|
||||
ValueSet.ConceptSetComponent conceptSetComponent =
|
||||
valueSet.getCompose().getInclude().get(0);
|
||||
ValueSet.ConceptSetFilterComponent filterComponent = new ValueSet.ConceptSetFilterComponent();
|
||||
filterComponent.setProperty(PROPERTY_NAME);
|
||||
filterComponent.setOp(theOperator);
|
||||
switch (theOperator) {
|
||||
case EQUAL, EXISTS, IN -> filterComponent.setValue("1");
|
||||
case NOTIN -> filterComponent.setValue("2,3,4");
|
||||
}
|
||||
conceptSetComponent.setFilter(List.of(filterComponent));
|
||||
valueSet.getCompose().setExclude(List.of(conceptSetComponent));
|
||||
valueSet.getCompose().setInclude(null);
|
||||
|
||||
boolean preExpand = getJpaStorageSettings().isPreExpandValueSets();
|
||||
|
||||
getJpaStorageSettings().setPreExpandValueSets(true);
|
||||
try {
|
||||
doFailedValueSetExpansionTest(codeSystem, valueSet);
|
||||
} finally {
|
||||
getJpaStorageSettings().setPreExpandValueSets(preExpand);
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@EnumSource(
|
||||
value = ValueSet.FilterOperator.class,
|
||||
mode = EnumSource.Mode.INCLUDE,
|
||||
names = {"EQUAL", "EXISTS", "IN", "NOTIN"})
|
||||
default void expandByIdentifier_withDecimalFilteredValuesInExclude_doesNotAddMatchingCode(
|
||||
ValueSet.FilterOperator theOperator) {
|
||||
// setup
|
||||
IParser parser = getFhirContext().newJsonParser();
|
||||
|
||||
// setup code system
|
||||
CodeSystem codeSystem = parser.parseResource(CodeSystem.class, CODE_SYSTEM_STR_BASE);
|
||||
CodeSystem.ConceptDefinitionComponent conceptDefinitionComponent =
|
||||
codeSystem.getConcept().get(0);
|
||||
CodeSystem.ConceptPropertyComponent propertyComponent = new CodeSystem.ConceptPropertyComponent();
|
||||
propertyComponent.setCode(PROPERTY_NAME);
|
||||
propertyComponent.setValue(new DecimalType(1.1));
|
||||
conceptDefinitionComponent.setProperty(List.of(propertyComponent));
|
||||
|
||||
// setup valueset
|
||||
ValueSet valueSet = parser.parseResource(ValueSet.class, VALUE_SET_STR_BASE);
|
||||
ValueSet.ConceptSetComponent conceptSetComponent =
|
||||
valueSet.getCompose().getInclude().get(0);
|
||||
ValueSet.ConceptSetFilterComponent filterComponent = new ValueSet.ConceptSetFilterComponent();
|
||||
filterComponent.setProperty(PROPERTY_NAME);
|
||||
filterComponent.setOp(theOperator);
|
||||
switch (theOperator) {
|
||||
case EQUAL, EXISTS, IN -> filterComponent.setValue("1.1");
|
||||
case NOTIN -> filterComponent.setValue("2.1,3.2,4.3");
|
||||
}
|
||||
conceptSetComponent.setFilter(List.of(filterComponent));
|
||||
valueSet.getCompose().setExclude(List.of(conceptSetComponent));
|
||||
valueSet.getCompose().setInclude(null);
|
||||
|
||||
boolean preExpand = getJpaStorageSettings().isPreExpandValueSets();
|
||||
|
||||
getJpaStorageSettings().setPreExpandValueSets(true);
|
||||
try {
|
||||
doFailedValueSetExpansionTest(codeSystem, valueSet);
|
||||
} finally {
|
||||
getJpaStorageSettings().setPreExpandValueSets(preExpand);
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@EnumSource(
|
||||
value = ValueSet.FilterOperator.class,
|
||||
mode = EnumSource.Mode.INCLUDE,
|
||||
names = {"EQUAL", "EXISTS", "IN", "NOTIN"})
|
||||
default void expandByIdentifier_withDateTimeFilteredValuesInExclude_doesNotAddMatchingCode(
|
||||
ValueSet.FilterOperator theOperator) {
|
||||
// setup
|
||||
IParser parser = getFhirContext().newJsonParser();
|
||||
Date now = new Date();
|
||||
DateTimeType dt = new DateTimeType(now);
|
||||
|
||||
// setup codesystem
|
||||
CodeSystem codeSystem = parser.parseResource(CodeSystem.class, CODE_SYSTEM_STR_BASE);
|
||||
CodeSystem.ConceptDefinitionComponent conceptDefinitionComponent =
|
||||
codeSystem.getConcept().get(0);
|
||||
CodeSystem.ConceptPropertyComponent propertyComponent = new CodeSystem.ConceptPropertyComponent();
|
||||
propertyComponent.setCode(PROPERTY_NAME);
|
||||
propertyComponent.setValue(dt);
|
||||
conceptDefinitionComponent.setProperty(List.of(propertyComponent));
|
||||
|
||||
// setup valueset
|
||||
ValueSet valueSet = parser.parseResource(ValueSet.class, VALUE_SET_STR_BASE);
|
||||
ValueSet.ConceptSetComponent conceptSetComponent =
|
||||
valueSet.getCompose().getInclude().get(0);
|
||||
ValueSet.ConceptSetFilterComponent filterComponent = new ValueSet.ConceptSetFilterComponent();
|
||||
filterComponent.setProperty(PROPERTY_NAME);
|
||||
filterComponent.setOp(theOperator);
|
||||
switch (theOperator) {
|
||||
case EQUAL, EXISTS, IN -> filterComponent.setValue(dt.getValueAsString());
|
||||
case NOTIN -> {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 1; i < 3; i++) {
|
||||
DateTimeType arbitraryDateTime =
|
||||
new DateTimeType(Date.from(Instant.now().minus(i, ChronoUnit.SECONDS)));
|
||||
if (!sb.isEmpty()) {
|
||||
sb.append(",");
|
||||
}
|
||||
sb.append(arbitraryDateTime.getValueAsString());
|
||||
}
|
||||
filterComponent.setValue(sb.toString());
|
||||
}
|
||||
}
|
||||
conceptSetComponent.setFilter(List.of(filterComponent));
|
||||
valueSet.getCompose().setExclude(List.of(conceptSetComponent));
|
||||
valueSet.getCompose().setInclude(null);
|
||||
|
||||
boolean preExpand = getJpaStorageSettings().isPreExpandValueSets();
|
||||
|
||||
getJpaStorageSettings().setPreExpandValueSets(true);
|
||||
try {
|
||||
doFailedValueSetExpansionTest(codeSystem, valueSet);
|
||||
} finally {
|
||||
getJpaStorageSettings().setPreExpandValueSets(preExpand);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the test for value set expansion that will find no new codes to add
|
||||
* @param theCodeSystem the code system to create
|
||||
* @param theValueSet the value set to expand
|
||||
* @return the expanded value set
|
||||
*/
|
||||
private ValueSet doFailedValueSetExpansionTest(CodeSystem theCodeSystem, ValueSet theValueSet) {
|
||||
ValueSet expandedValueSet = createCodeSystemAndValueSetAndReturnExpandedValueSet(theCodeSystem, theValueSet);
|
||||
|
||||
// validate
|
||||
assertNotNull(expandedValueSet);
|
||||
assertNotNull(expandedValueSet.getExpansion());
|
||||
assertTrue(expandedValueSet.getExpansion().getContains().isEmpty());
|
||||
|
||||
// pass back for additional validation
|
||||
return expandedValueSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the test for value set expansion that will find codes to add
|
||||
* @param theCodeSystem the code system to create
|
||||
* @param theValueSet the value set to expand
|
||||
* @return the expanded value set
|
||||
*/
|
||||
private ValueSet doSuccessfulValueSetExpansionTest(CodeSystem theCodeSystem, ValueSet theValueSet) {
|
||||
ValueSet expandedValueSet = createCodeSystemAndValueSetAndReturnExpandedValueSet(theCodeSystem, theValueSet);
|
||||
|
||||
// validate
|
||||
assertNotNull(expandedValueSet);
|
||||
assertNotNull(expandedValueSet.getExpansion());
|
||||
assertFalse(expandedValueSet.getExpansion().getContains().isEmpty());
|
||||
|
||||
// pass back for additional validation
|
||||
return expandedValueSet;
|
||||
}
|
||||
|
||||
private ValueSet createCodeSystemAndValueSetAndReturnExpandedValueSet(
|
||||
CodeSystem theCodeSystem, ValueSet theValueSet) {
|
||||
SystemRequestDetails requestDetails = new SystemRequestDetails();
|
||||
String url = "https://health.gov.on.ca/idms/fhir/ValueSet/IDMS-Product-Types";
|
||||
|
||||
// create the code system
|
||||
{
|
||||
@SuppressWarnings("unchecked")
|
||||
IFhirResourceDao<CodeSystem> codeSystemDao = getDaoRegistry().getResourceDao("CodeSystem");
|
||||
DaoMethodOutcome outcome = codeSystemDao.create(theCodeSystem, requestDetails);
|
||||
theCodeSystem.setId(outcome.getId());
|
||||
getTerminologyDefferedStorageService().saveAllDeferred();
|
||||
}
|
||||
// create the value set
|
||||
{
|
||||
@SuppressWarnings("unchecked")
|
||||
IFhirResourceDao<ValueSet> valueSetDao = getDaoRegistry().getResourceDao("ValueSet");
|
||||
DaoMethodOutcome outcome = valueSetDao.create(theValueSet, requestDetails);
|
||||
theValueSet.setId(outcome.getId());
|
||||
getTerminologyReadSvc().preExpandDeferredValueSetsToTerminologyTables();
|
||||
}
|
||||
|
||||
// test
|
||||
ValueSetExpansionOptions options = new ValueSetExpansionOptions();
|
||||
return getValueSetDao().expandByIdentifier(url, options);
|
||||
}
|
||||
}
|
|
@ -259,7 +259,7 @@ public abstract class BaseJpaTest extends BaseTest {
|
|||
@Autowired
|
||||
private IResourceHistoryTableDao myResourceHistoryTableDao;
|
||||
@Autowired
|
||||
private DaoRegistry myDaoRegistry;
|
||||
protected DaoRegistry myDaoRegistry;
|
||||
@Autowired
|
||||
protected ITermDeferredStorageSvc myTermDeferredStorageSvc;
|
||||
private final List<Object> myRegisteredInterceptors = new ArrayList<>(1);
|
||||
|
|
Loading…
Reference in New Issue