mirror of
https://github.com/hapifhir/hapi-fhir.git
synced 2025-02-16 09:55:09 +00:00
Fix handling of filters on valueset expansions
This commit is contained in:
parent
12e047b931
commit
f1828d1ca8
@ -10,7 +10,7 @@ package ca.uhn.fhir.jpa.dao.dstu3;
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@ -33,6 +33,7 @@ import org.hl7.fhir.dstu3.model.CodeSystem;
|
|||||||
import org.hl7.fhir.dstu3.model.CodeableConcept;
|
import org.hl7.fhir.dstu3.model.CodeableConcept;
|
||||||
import org.hl7.fhir.dstu3.model.Coding;
|
import org.hl7.fhir.dstu3.model.Coding;
|
||||||
import org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus;
|
import org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus;
|
||||||
|
import org.hl7.fhir.dstu3.model.IntegerType;
|
||||||
import org.hl7.fhir.dstu3.model.UriType;
|
import org.hl7.fhir.dstu3.model.UriType;
|
||||||
import org.hl7.fhir.dstu3.model.ValueSet;
|
import org.hl7.fhir.dstu3.model.ValueSet;
|
||||||
import org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent;
|
import org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent;
|
||||||
@ -82,12 +83,12 @@ public class FhirResourceDaoValueSetDstu3 extends FhirResourceDaoDstu3<ValueSet>
|
|||||||
|
|
||||||
return retVal;
|
return retVal;
|
||||||
|
|
||||||
// ValueSetExpansionComponent expansion = outcome.getValueset().getExpansion();
|
// ValueSetExpansionComponent expansion = outcome.getValueset().getExpansion();
|
||||||
//
|
//
|
||||||
// ValueSet retVal = new ValueSet();
|
// ValueSet retVal = new ValueSet();
|
||||||
// retVal.getMeta().setLastUpdated(new Date());
|
// retVal.getMeta().setLastUpdated(new Date());
|
||||||
// retVal.setExpansion(expansion);
|
// retVal.setExpansion(expansion);
|
||||||
// return retVal;
|
// return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateIncludes(String name, List<ConceptSetComponent> listToValidate) {
|
private void validateIncludes(String name, List<ConceptSetComponent> listToValidate) {
|
||||||
@ -137,11 +138,11 @@ public class FhirResourceDaoValueSetDstu3 extends FhirResourceDaoDstu3<ValueSet>
|
|||||||
public ValueSet expand(ValueSet source, String theFilter) {
|
public ValueSet expand(ValueSet source, String theFilter) {
|
||||||
ValueSet toExpand = new ValueSet();
|
ValueSet toExpand = new ValueSet();
|
||||||
|
|
||||||
// for (UriType next : source.getCompose().getInclude()) {
|
// for (UriType next : source.getCompose().getInclude()) {
|
||||||
// ConceptSetComponent include = toExpand.getCompose().addInclude();
|
// ConceptSetComponent include = toExpand.getCompose().addInclude();
|
||||||
// include.setSystem(next.getValue());
|
// include.setSystem(next.getValue());
|
||||||
// addFilterIfPresent(theFilter, include);
|
// addFilterIfPresent(theFilter, include);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
for (ConceptSetComponent next : source.getCompose().getInclude()) {
|
for (ConceptSetComponent next : source.getCompose().getInclude()) {
|
||||||
toExpand.getCompose().addInclude(next);
|
toExpand.getCompose().addInclude(next);
|
||||||
@ -155,18 +156,41 @@ public class FhirResourceDaoValueSetDstu3 extends FhirResourceDaoDstu3<ValueSet>
|
|||||||
toExpand.getCompose().getExclude().addAll(source.getCompose().getExclude());
|
toExpand.getCompose().getExclude().addAll(source.getCompose().getExclude());
|
||||||
|
|
||||||
ValueSet retVal = doExpand(toExpand);
|
ValueSet retVal = doExpand(toExpand);
|
||||||
|
|
||||||
|
if (isNotBlank(theFilter)) {
|
||||||
|
applyFilter(retVal.getExpansion().getTotalElement(), retVal.getExpansion().getContains(), theFilter);
|
||||||
|
}
|
||||||
|
|
||||||
return retVal;
|
return retVal;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void applyFilter(IntegerType theTotalElement, List<ValueSetExpansionContainsComponent> theContains, String theFilter) {
|
||||||
|
|
||||||
|
for (int idx = 0; idx < theContains.size(); idx++) {
|
||||||
|
ValueSetExpansionContainsComponent next = theContains.get(idx);
|
||||||
|
if (isBlank(next.getDisplay()) || !org.apache.commons.lang3.StringUtils.containsIgnoreCase(next.getDisplay(), theFilter)) {
|
||||||
|
theContains.remove(idx);
|
||||||
|
idx--;
|
||||||
|
if (theTotalElement.getValue() != null) {
|
||||||
|
theTotalElement.setValue(theTotalElement.getValue() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
applyFilter(theTotalElement, next.getContains(), theFilter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void addFilterIfPresent(String theFilter, ConceptSetComponent include) {
|
private void addFilterIfPresent(String theFilter, ConceptSetComponent include) {
|
||||||
if (isNotBlank(theFilter)) {
|
if (ElementUtil.isEmpty(include.getConcept())) {
|
||||||
include.addFilter().setProperty("display").setOp(FilterOperator.EQUAL).setValue(theFilter);
|
if (isNotBlank(theFilter)) {
|
||||||
|
include.addFilter().setProperty("display").setOp(FilterOperator.EQUAL).setValue(theFilter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult validateCode(IPrimitiveType<String> theValueSetIdentifier, IIdType theId, IPrimitiveType<String> theCode, IPrimitiveType<String> theSystem, IPrimitiveType<String> theDisplay, Coding theCoding,
|
public ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult validateCode(IPrimitiveType<String> theValueSetIdentifier, IIdType theId, IPrimitiveType<String> theCode,
|
||||||
|
IPrimitiveType<String> theSystem, IPrimitiveType<String> theDisplay, Coding theCoding,
|
||||||
CodeableConcept theCodeableConcept, RequestDetails theRequestDetails) {
|
CodeableConcept theCodeableConcept, RequestDetails theRequestDetails) {
|
||||||
|
|
||||||
List<IIdType> valueSetIds = Collections.emptyList();
|
List<IIdType> valueSetIds = Collections.emptyList();
|
||||||
@ -226,7 +250,8 @@ public class FhirResourceDaoValueSetDstu3 extends FhirResourceDaoDstu3<ValueSet>
|
|||||||
return thePrimitive != null ? thePrimitive.getValue() : null;
|
return thePrimitive != null ? thePrimitive.getValue() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult validateCodeIsInContains(List<ValueSetExpansionContainsComponent> contains, String theSystem, String theCode, Coding theCoding, CodeableConcept theCodeableConcept) {
|
private ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult validateCodeIsInContains(List<ValueSetExpansionContainsComponent> contains, String theSystem, String theCode,
|
||||||
|
Coding theCoding, CodeableConcept theCodeableConcept) {
|
||||||
for (ValueSetExpansionContainsComponent nextCode : contains) {
|
for (ValueSetExpansionContainsComponent nextCode : contains) {
|
||||||
ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult result = validateCodeIsInContains(nextCode.getContains(), theSystem, theCode, theCoding, theCodeableConcept);
|
ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult result = validateCodeIsInContains(nextCode.getContains(), theSystem, theCode, theCoding, theCodeableConcept);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
|
@ -16,6 +16,7 @@ import org.hl7.fhir.dstu3.model.AllergyIntolerance.AllergyIntoleranceCategory;
|
|||||||
import org.hl7.fhir.dstu3.model.AllergyIntolerance.AllergyIntoleranceClinicalStatus;
|
import org.hl7.fhir.dstu3.model.AllergyIntolerance.AllergyIntoleranceClinicalStatus;
|
||||||
import org.hl7.fhir.dstu3.model.CodeSystem.CodeSystemContentMode;
|
import org.hl7.fhir.dstu3.model.CodeSystem.CodeSystemContentMode;
|
||||||
import org.hl7.fhir.dstu3.model.CodeSystem.ConceptDefinitionComponent;
|
import org.hl7.fhir.dstu3.model.CodeSystem.ConceptDefinitionComponent;
|
||||||
|
import org.hl7.fhir.dstu3.model.ValueSet.ConceptReferenceComponent;
|
||||||
import org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent;
|
import org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent;
|
||||||
import org.hl7.fhir.dstu3.model.ValueSet.FilterOperator;
|
import org.hl7.fhir.dstu3.model.ValueSet.FilterOperator;
|
||||||
import org.hl7.fhir.dstu3.model.ValueSet.ValueSetComposeComponent;
|
import org.hl7.fhir.dstu3.model.ValueSet.ValueSetComposeComponent;
|
||||||
@ -53,6 +54,9 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||||||
public static final String URL_MY_CODE_SYSTEM = "http://example.com/my_code_system";
|
public static final String URL_MY_CODE_SYSTEM = "http://example.com/my_code_system";
|
||||||
public static final String URL_MY_VALUE_SET = "http://example.com/my_value_set";
|
public static final String URL_MY_VALUE_SET = "http://example.com/my_value_set";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IHapiTerminologySvc myHapiTerminologySvc;
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void after() {
|
public void after() {
|
||||||
myDaoConfig.setDeferIndexingForCodesystemsOfSize(new DaoConfig().getDeferIndexingForCodesystemsOfSize());
|
myDaoConfig.setDeferIndexingForCodesystemsOfSize(new DaoConfig().getDeferIndexingForCodesystemsOfSize());
|
||||||
@ -116,6 +120,37 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||||||
createLocalVs(codeSystem);
|
createLocalVs(codeSystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private CodeSystem createExternalCsDogs() {
|
||||||
|
CodeSystem codeSystem = new CodeSystem();
|
||||||
|
codeSystem.setUrl(URL_MY_CODE_SYSTEM);
|
||||||
|
codeSystem.setContent(CodeSystemContentMode.NOTPRESENT);
|
||||||
|
IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();
|
||||||
|
|
||||||
|
ResourceTable table = myResourceTableDao.findOne(id.getIdPartAsLong());
|
||||||
|
|
||||||
|
TermCodeSystemVersion cs = new TermCodeSystemVersion();
|
||||||
|
cs.setResource(table);
|
||||||
|
cs.setResourceVersionId(table.getVersion());
|
||||||
|
|
||||||
|
TermConcept hello = new TermConcept(cs, "hello").setDisplay("Hello");
|
||||||
|
cs.getConcepts().add(hello);
|
||||||
|
|
||||||
|
TermConcept goodbye = new TermConcept(cs, "goodbye").setDisplay("Goodbye");
|
||||||
|
cs.getConcepts().add(goodbye);
|
||||||
|
|
||||||
|
TermConcept dogs = new TermConcept(cs, "dogs").setDisplay("Dogs");
|
||||||
|
cs.getConcepts().add(dogs);
|
||||||
|
|
||||||
|
TermConcept labrador = new TermConcept(cs, "labrador").setDisplay("Labrador");
|
||||||
|
dogs.addChild(labrador, RelationshipTypeEnum.ISA);
|
||||||
|
|
||||||
|
TermConcept beagle = new TermConcept(cs, "beagle").setDisplay("Beagle");
|
||||||
|
dogs.addChild(beagle, RelationshipTypeEnum.ISA);
|
||||||
|
|
||||||
|
myTermSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM, cs);
|
||||||
|
return codeSystem;
|
||||||
|
}
|
||||||
|
|
||||||
private void createLocalCsAndVs() {
|
private void createLocalCsAndVs() {
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
CodeSystem codeSystem = new CodeSystem();
|
CodeSystem codeSystem = new CodeSystem();
|
||||||
@ -144,6 +179,22 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||||||
myValueSetDao.create(valueSet, mySrd);
|
myValueSetDao.create(valueSet, mySrd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void logAndValidateValueSet(ValueSet theResult) {
|
||||||
|
IParser parser = myFhirCtx.newXmlParser().setPrettyPrint(true);
|
||||||
|
String encoded = parser.encodeResourceToString(theResult);
|
||||||
|
ourLog.info(encoded);
|
||||||
|
|
||||||
|
FhirValidator validator = myFhirCtx.newValidator();
|
||||||
|
validator.setValidateAgainstStandardSchema(true);
|
||||||
|
validator.setValidateAgainstStandardSchematron(true);
|
||||||
|
ValidationResult result = validator.validateWithResult(theResult);
|
||||||
|
|
||||||
|
if (!result.isSuccessful()) {
|
||||||
|
ourLog.info(parser.encodeResourceToString(result.toOperationOutcome()));
|
||||||
|
fail(parser.encodeResourceToString(result.toOperationOutcome()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCodeSystemCreateDuplicateFails() {
|
public void testCodeSystemCreateDuplicateFails() {
|
||||||
CodeSystem codeSystem = new CodeSystem();
|
CodeSystem codeSystem = new CodeSystem();
|
||||||
@ -162,28 +213,6 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLookupSnomed() {
|
|
||||||
CodeSystem codeSystem = new CodeSystem();
|
|
||||||
codeSystem.setUrl("http://snomed.info/sct");
|
|
||||||
codeSystem.setContent(CodeSystemContentMode.NOTPRESENT);
|
|
||||||
IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();
|
|
||||||
|
|
||||||
ResourceTable table = myResourceTableDao.findOne(id.getIdPartAsLong());
|
|
||||||
|
|
||||||
TermCodeSystemVersion cs = new TermCodeSystemVersion();
|
|
||||||
cs.setResource(table);
|
|
||||||
cs.setResourceVersionId(table.getVersion());
|
|
||||||
TermConcept parentA = new TermConcept(cs, "ParentA").setDisplay("Parent A");
|
|
||||||
cs.getConcepts().add(parentA);
|
|
||||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), "http://snomed.info/sct", cs);
|
|
||||||
|
|
||||||
StringType code = new StringType("ParentA");
|
|
||||||
StringType system = new StringType("http://snomed.info/sct");
|
|
||||||
LookupCodeResult outcome = myCodeSystemDao.lookupCode(code, system, null, mySrd);
|
|
||||||
assertEquals(true, outcome.isFound());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCodeSystemWithDefinedCodes() {
|
public void testCodeSystemWithDefinedCodes() {
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
@ -207,170 +236,6 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testExpandWithExcludeInExternalValueSet() {
|
|
||||||
createExternalCsAndLocalVs();
|
|
||||||
|
|
||||||
ValueSet vs = new ValueSet();
|
|
||||||
ConceptSetComponent include = vs.getCompose().addInclude();
|
|
||||||
include.setSystem(URL_MY_CODE_SYSTEM);
|
|
||||||
|
|
||||||
ConceptSetComponent exclude = vs.getCompose().addExclude();
|
|
||||||
exclude.setSystem(URL_MY_CODE_SYSTEM);
|
|
||||||
exclude.addConcept().setCode("childAA");
|
|
||||||
exclude.addConcept().setCode("childAAA");
|
|
||||||
|
|
||||||
ValueSet result = myValueSetDao.expand(vs, null);
|
|
||||||
logAndValidateValueSet(result);
|
|
||||||
|
|
||||||
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
|
||||||
assertThat(codes, containsInAnyOrder("ParentA", "ParentB", "childAB", "childAAB", "ParentC", "childBA", "childCA"));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void logAndValidateValueSet(ValueSet theResult) {
|
|
||||||
IParser parser = myFhirCtx.newXmlParser().setPrettyPrint(true);
|
|
||||||
String encoded = parser.encodeResourceToString(theResult);
|
|
||||||
ourLog.info(encoded);
|
|
||||||
|
|
||||||
FhirValidator validator = myFhirCtx.newValidator();
|
|
||||||
validator.setValidateAgainstStandardSchema(true);
|
|
||||||
validator.setValidateAgainstStandardSchematron(true);
|
|
||||||
ValidationResult result = validator.validateWithResult(theResult);
|
|
||||||
|
|
||||||
if (!result.isSuccessful()) {
|
|
||||||
ourLog.info(parser.encodeResourceToString(result.toOperationOutcome()));
|
|
||||||
fail(parser.encodeResourceToString(result.toOperationOutcome()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testExpandWithInvalidExclude() {
|
|
||||||
createExternalCsAndLocalVs();
|
|
||||||
|
|
||||||
ValueSet vs = new ValueSet();
|
|
||||||
ConceptSetComponent include = vs.getCompose().addInclude();
|
|
||||||
include.setSystem(URL_MY_CODE_SYSTEM);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* No system set on exclude
|
|
||||||
*/
|
|
||||||
ConceptSetComponent exclude = vs.getCompose().addExclude();
|
|
||||||
exclude.addConcept().setCode("childAA");
|
|
||||||
exclude.addConcept().setCode("childAAA");
|
|
||||||
try {
|
|
||||||
myValueSetDao.expand(vs, null);
|
|
||||||
fail();
|
|
||||||
} catch (InvalidRequestException e) {
|
|
||||||
assertEquals("ValueSet contains exclude criteria with no system defined", e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testExpandWithNoResultsInLocalValueSet1() {
|
|
||||||
createLocalCsAndVs();
|
|
||||||
|
|
||||||
ValueSet vs = new ValueSet();
|
|
||||||
ConceptSetComponent include = vs.getCompose().addInclude();
|
|
||||||
include.setSystem(URL_MY_CODE_SYSTEM);
|
|
||||||
include.addConcept().setCode("ZZZZ");
|
|
||||||
|
|
||||||
try {
|
|
||||||
myValueSetDao.expand(vs, null);
|
|
||||||
fail();
|
|
||||||
} catch (InvalidRequestException e) {
|
|
||||||
assertEquals("Unable to find code 'ZZZZ' in code system http://example.com/my_code_system", e.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testReindex() {
|
|
||||||
createLocalCsAndVs();
|
|
||||||
|
|
||||||
ValueSet vs = new ValueSet();
|
|
||||||
ConceptSetComponent include = vs.getCompose().addInclude();
|
|
||||||
include.setSystem(URL_MY_CODE_SYSTEM);
|
|
||||||
include.addConcept().setCode("ZZZZ");
|
|
||||||
|
|
||||||
mySystemDao.markAllResourcesForReindexing();
|
|
||||||
mySystemDao.performReindexingPass(null);
|
|
||||||
myTermSvc.saveDeferred();
|
|
||||||
mySystemDao.performReindexingPass(null);
|
|
||||||
myTermSvc.saveDeferred();
|
|
||||||
|
|
||||||
// Again
|
|
||||||
mySystemDao.markAllResourcesForReindexing();
|
|
||||||
mySystemDao.performReindexingPass(null);
|
|
||||||
myTermSvc.saveDeferred();
|
|
||||||
mySystemDao.performReindexingPass(null);
|
|
||||||
myTermSvc.saveDeferred();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testExpandWithNoResultsInLocalValueSet2() {
|
|
||||||
createLocalCsAndVs();
|
|
||||||
|
|
||||||
ValueSet vs = new ValueSet();
|
|
||||||
ConceptSetComponent include = vs.getCompose().addInclude();
|
|
||||||
include.setSystem(URL_MY_CODE_SYSTEM + "AA");
|
|
||||||
include.addConcept().setCode("A");
|
|
||||||
|
|
||||||
try {
|
|
||||||
myValueSetDao.expand(vs, null);
|
|
||||||
fail();
|
|
||||||
} catch (InvalidRequestException e) {
|
|
||||||
assertEquals("unable to find code system http://example.com/my_code_systemAA", e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testExpandWithIsAInExternalValueSet() {
|
|
||||||
createExternalCsAndLocalVs();
|
|
||||||
|
|
||||||
ValueSet vs = new ValueSet();
|
|
||||||
ConceptSetComponent include = vs.getCompose().addInclude();
|
|
||||||
include.setSystem(URL_MY_CODE_SYSTEM);
|
|
||||||
include.addFilter().setOp(FilterOperator.ISA).setValue("childAA").setProperty("concept");
|
|
||||||
|
|
||||||
ValueSet result = myValueSetDao.expand(vs, null);
|
|
||||||
logAndValidateValueSet(result);
|
|
||||||
|
|
||||||
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
|
||||||
assertThat(codes, containsInAnyOrder("childAAA", "childAAB"));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IHapiTerminologySvc myHapiTerminologySvc;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testExpandWithIsAInExternalValueSetReindex() {
|
|
||||||
BaseHapiTerminologySvc.setForceSaveDeferredAlwaysForUnitTest(true);
|
|
||||||
|
|
||||||
createExternalCsAndLocalVs();
|
|
||||||
|
|
||||||
mySystemDao.markAllResourcesForReindexing();
|
|
||||||
|
|
||||||
mySystemDao.performReindexingPass(100);
|
|
||||||
mySystemDao.performReindexingPass(100);
|
|
||||||
myHapiTerminologySvc.saveDeferred();
|
|
||||||
myHapiTerminologySvc.saveDeferred();
|
|
||||||
myHapiTerminologySvc.saveDeferred();
|
|
||||||
|
|
||||||
ValueSet vs = new ValueSet();
|
|
||||||
ConceptSetComponent include = vs.getCompose().addInclude();
|
|
||||||
include.setSystem(URL_MY_CODE_SYSTEM);
|
|
||||||
include.addFilter().setOp(FilterOperator.ISA).setValue("childAA").setProperty("concept");
|
|
||||||
|
|
||||||
ValueSet result = myValueSetDao.expand(vs, null);
|
|
||||||
logAndValidateValueSet(result);
|
|
||||||
|
|
||||||
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
|
||||||
assertThat(codes, containsInAnyOrder("childAAA", "childAAB"));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExpandInvalid() {
|
public void testExpandInvalid() {
|
||||||
createExternalCsAndLocalVs();
|
createExternalCsAndLocalVs();
|
||||||
@ -390,43 +255,110 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExpandWithSystemAndCodesInExternalValueSet() {
|
public void testExpandWithCodesAndDisplayFilterBlank() {
|
||||||
createExternalCsAndLocalVs();
|
CodeSystem codeSystem = createExternalCsDogs();
|
||||||
|
|
||||||
ValueSet vs = new ValueSet();
|
ValueSet valueSet = new ValueSet();
|
||||||
ConceptSetComponent include = vs.getCompose().addInclude();
|
valueSet.setUrl(URL_MY_VALUE_SET);
|
||||||
include.setSystem(URL_MY_CODE_SYSTEM);
|
valueSet.getCompose()
|
||||||
include.addConcept().setCode("ParentA");
|
.addInclude()
|
||||||
include.addConcept().setCode("childAA");
|
.setSystem(codeSystem.getUrl())
|
||||||
include.addConcept().setCode("childAAA");
|
.addConcept(new ConceptReferenceComponent().setCode("hello"))
|
||||||
|
.addConcept(new ConceptReferenceComponent().setCode("goodbye"));
|
||||||
|
valueSet.getCompose()
|
||||||
|
.addInclude()
|
||||||
|
.setSystem(codeSystem.getUrl())
|
||||||
|
.addFilter()
|
||||||
|
.setProperty("concept")
|
||||||
|
.setOp(FilterOperator.ISA)
|
||||||
|
.setValue("dogs");
|
||||||
|
|
||||||
|
myValueSetDao.create(valueSet, mySrd);
|
||||||
|
|
||||||
ValueSet result = myValueSetDao.expand(vs, null);
|
ValueSet result = myValueSetDao.expand(valueSet, "");
|
||||||
logAndValidateValueSet(result);
|
logAndValidateValueSet(result);
|
||||||
|
|
||||||
|
assertEquals(4, result.getExpansion().getTotal());
|
||||||
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
||||||
assertThat(codes, containsInAnyOrder("ParentA", "childAA", "childAAA"));
|
assertThat(codes, containsInAnyOrder("hello", "goodbye", "labrador", "beagle"));
|
||||||
|
|
||||||
int idx = codes.indexOf("childAA");
|
|
||||||
assertEquals("childAA", result.getExpansion().getContains().get(idx).getCode());
|
|
||||||
assertEquals("Child AA", result.getExpansion().getContains().get(idx).getDisplay());
|
|
||||||
assertEquals(URL_MY_CODE_SYSTEM, result.getExpansion().getContains().get(idx).getSystem());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExpandWithSystemAndFilterInExternalValueSet() {
|
public void testExpandWithCodesAndDisplayFilterPartialOnFilter() {
|
||||||
createExternalCsAndLocalVs();
|
CodeSystem codeSystem = createExternalCsDogs();
|
||||||
|
|
||||||
ValueSet vs = new ValueSet();
|
ValueSet valueSet = new ValueSet();
|
||||||
ConceptSetComponent include = vs.getCompose().addInclude();
|
valueSet.setUrl(URL_MY_VALUE_SET);
|
||||||
include.setSystem(URL_MY_CODE_SYSTEM);
|
valueSet.getCompose()
|
||||||
|
.addInclude()
|
||||||
|
.setSystem(codeSystem.getUrl())
|
||||||
|
.addConcept(new ConceptReferenceComponent().setCode("hello"))
|
||||||
|
.addConcept(new ConceptReferenceComponent().setCode("goodbye"));
|
||||||
|
valueSet.getCompose()
|
||||||
|
.addInclude()
|
||||||
|
.setSystem(codeSystem.getUrl())
|
||||||
|
.addFilter()
|
||||||
|
.setProperty("concept")
|
||||||
|
.setOp(FilterOperator.ISA)
|
||||||
|
.setValue("dogs");
|
||||||
|
|
||||||
|
myValueSetDao.create(valueSet, mySrd);
|
||||||
|
|
||||||
include.addFilter().setProperty("display").setOp(FilterOperator.EQUAL).setValue("Parent B");
|
ValueSet result = myValueSetDao.expand(valueSet, "lab");
|
||||||
|
|
||||||
ValueSet result = myValueSetDao.expand(vs, null);
|
|
||||||
logAndValidateValueSet(result);
|
logAndValidateValueSet(result);
|
||||||
|
|
||||||
|
assertEquals(1, result.getExpansion().getTotal());
|
||||||
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
||||||
assertThat(codes, containsInAnyOrder("ParentB"));
|
assertThat(codes, containsInAnyOrder("labrador"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExpandWithCodesAndDisplayFilterPartialOnCodes() {
|
||||||
|
CodeSystem codeSystem = createExternalCsDogs();
|
||||||
|
|
||||||
|
ValueSet valueSet = new ValueSet();
|
||||||
|
valueSet.setUrl(URL_MY_VALUE_SET);
|
||||||
|
valueSet.getCompose()
|
||||||
|
.addInclude()
|
||||||
|
.setSystem(codeSystem.getUrl())
|
||||||
|
.addConcept(new ConceptReferenceComponent().setCode("hello"))
|
||||||
|
.addConcept(new ConceptReferenceComponent().setCode("goodbye"));
|
||||||
|
valueSet.getCompose()
|
||||||
|
.addInclude()
|
||||||
|
.setSystem(codeSystem.getUrl())
|
||||||
|
.addFilter()
|
||||||
|
.setProperty("concept")
|
||||||
|
.setOp(FilterOperator.ISA)
|
||||||
|
.setValue("dogs");
|
||||||
|
|
||||||
|
myValueSetDao.create(valueSet, mySrd);
|
||||||
|
|
||||||
|
ValueSet result = myValueSetDao.expand(valueSet, "hel");
|
||||||
|
logAndValidateValueSet(result);
|
||||||
|
|
||||||
|
assertEquals(1, result.getExpansion().getTotal());
|
||||||
|
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
||||||
|
assertThat(codes, containsInAnyOrder("hello"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExpandWithCodesAndDisplayFilterPartialOnExpansion() {
|
||||||
|
CodeSystem codeSystem = createExternalCsDogs();
|
||||||
|
|
||||||
|
ValueSet valueSet = new ValueSet();
|
||||||
|
valueSet.setUrl(URL_MY_VALUE_SET);
|
||||||
|
valueSet.getCompose().addInclude().setSystem(codeSystem.getUrl());
|
||||||
|
myValueSetDao.create(valueSet, mySrd);
|
||||||
|
|
||||||
|
ValueSet result = myValueSetDao.expand(valueSet, "lab");
|
||||||
|
logAndValidateValueSet(result);
|
||||||
|
|
||||||
|
assertEquals(1, result.getExpansion().getTotal());
|
||||||
|
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
||||||
|
assertThat(codes, containsInAnyOrder("labrador"));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -463,6 +395,127 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExpandWithExcludeInExternalValueSet() {
|
||||||
|
createExternalCsAndLocalVs();
|
||||||
|
|
||||||
|
ValueSet vs = new ValueSet();
|
||||||
|
ConceptSetComponent include = vs.getCompose().addInclude();
|
||||||
|
include.setSystem(URL_MY_CODE_SYSTEM);
|
||||||
|
|
||||||
|
ConceptSetComponent exclude = vs.getCompose().addExclude();
|
||||||
|
exclude.setSystem(URL_MY_CODE_SYSTEM);
|
||||||
|
exclude.addConcept().setCode("childAA");
|
||||||
|
exclude.addConcept().setCode("childAAA");
|
||||||
|
|
||||||
|
ValueSet result = myValueSetDao.expand(vs, null);
|
||||||
|
logAndValidateValueSet(result);
|
||||||
|
|
||||||
|
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
||||||
|
assertThat(codes, containsInAnyOrder("ParentA", "ParentB", "childAB", "childAAB", "ParentC", "childBA", "childCA"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExpandWithInvalidExclude() {
|
||||||
|
createExternalCsAndLocalVs();
|
||||||
|
|
||||||
|
ValueSet vs = new ValueSet();
|
||||||
|
ConceptSetComponent include = vs.getCompose().addInclude();
|
||||||
|
include.setSystem(URL_MY_CODE_SYSTEM);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* No system set on exclude
|
||||||
|
*/
|
||||||
|
ConceptSetComponent exclude = vs.getCompose().addExclude();
|
||||||
|
exclude.addConcept().setCode("childAA");
|
||||||
|
exclude.addConcept().setCode("childAAA");
|
||||||
|
try {
|
||||||
|
myValueSetDao.expand(vs, null);
|
||||||
|
fail();
|
||||||
|
} catch (InvalidRequestException e) {
|
||||||
|
assertEquals("ValueSet contains exclude criteria with no system defined", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExpandWithIsAInExternalValueSet() {
|
||||||
|
createExternalCsAndLocalVs();
|
||||||
|
|
||||||
|
ValueSet vs = new ValueSet();
|
||||||
|
ConceptSetComponent include = vs.getCompose().addInclude();
|
||||||
|
include.setSystem(URL_MY_CODE_SYSTEM);
|
||||||
|
include.addFilter().setOp(FilterOperator.ISA).setValue("childAA").setProperty("concept");
|
||||||
|
|
||||||
|
ValueSet result = myValueSetDao.expand(vs, null);
|
||||||
|
logAndValidateValueSet(result);
|
||||||
|
|
||||||
|
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
||||||
|
assertThat(codes, containsInAnyOrder("childAAA", "childAAB"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExpandWithIsAInExternalValueSetReindex() {
|
||||||
|
BaseHapiTerminologySvc.setForceSaveDeferredAlwaysForUnitTest(true);
|
||||||
|
|
||||||
|
createExternalCsAndLocalVs();
|
||||||
|
|
||||||
|
mySystemDao.markAllResourcesForReindexing();
|
||||||
|
|
||||||
|
mySystemDao.performReindexingPass(100);
|
||||||
|
mySystemDao.performReindexingPass(100);
|
||||||
|
myHapiTerminologySvc.saveDeferred();
|
||||||
|
myHapiTerminologySvc.saveDeferred();
|
||||||
|
myHapiTerminologySvc.saveDeferred();
|
||||||
|
|
||||||
|
ValueSet vs = new ValueSet();
|
||||||
|
ConceptSetComponent include = vs.getCompose().addInclude();
|
||||||
|
include.setSystem(URL_MY_CODE_SYSTEM);
|
||||||
|
include.addFilter().setOp(FilterOperator.ISA).setValue("childAA").setProperty("concept");
|
||||||
|
|
||||||
|
ValueSet result = myValueSetDao.expand(vs, null);
|
||||||
|
logAndValidateValueSet(result);
|
||||||
|
|
||||||
|
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
||||||
|
assertThat(codes, containsInAnyOrder("childAAA", "childAAB"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExpandWithNoResultsInLocalValueSet1() {
|
||||||
|
createLocalCsAndVs();
|
||||||
|
|
||||||
|
ValueSet vs = new ValueSet();
|
||||||
|
ConceptSetComponent include = vs.getCompose().addInclude();
|
||||||
|
include.setSystem(URL_MY_CODE_SYSTEM);
|
||||||
|
include.addConcept().setCode("ZZZZ");
|
||||||
|
|
||||||
|
try {
|
||||||
|
myValueSetDao.expand(vs, null);
|
||||||
|
fail();
|
||||||
|
} catch (InvalidRequestException e) {
|
||||||
|
assertEquals("Unable to find code 'ZZZZ' in code system http://example.com/my_code_system", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExpandWithNoResultsInLocalValueSet2() {
|
||||||
|
createLocalCsAndVs();
|
||||||
|
|
||||||
|
ValueSet vs = new ValueSet();
|
||||||
|
ConceptSetComponent include = vs.getCompose().addInclude();
|
||||||
|
include.setSystem(URL_MY_CODE_SYSTEM + "AA");
|
||||||
|
include.addConcept().setCode("A");
|
||||||
|
|
||||||
|
try {
|
||||||
|
myValueSetDao.expand(vs, null);
|
||||||
|
fail();
|
||||||
|
} catch (InvalidRequestException e) {
|
||||||
|
assertEquals("unable to find code system http://example.com/my_code_systemAA", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExpandWithSystemAndCodesAndFilterKeywordInLocalValueSet() {
|
public void testExpandWithSystemAndCodesAndFilterKeywordInLocalValueSet() {
|
||||||
createLocalCsAndVs();
|
createLocalCsAndVs();
|
||||||
@ -493,6 +546,29 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExpandWithSystemAndCodesInExternalValueSet() {
|
||||||
|
createExternalCsAndLocalVs();
|
||||||
|
|
||||||
|
ValueSet vs = new ValueSet();
|
||||||
|
ConceptSetComponent include = vs.getCompose().addInclude();
|
||||||
|
include.setSystem(URL_MY_CODE_SYSTEM);
|
||||||
|
include.addConcept().setCode("ParentA");
|
||||||
|
include.addConcept().setCode("childAA");
|
||||||
|
include.addConcept().setCode("childAAA");
|
||||||
|
|
||||||
|
ValueSet result = myValueSetDao.expand(vs, null);
|
||||||
|
logAndValidateValueSet(result);
|
||||||
|
|
||||||
|
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
||||||
|
assertThat(codes, containsInAnyOrder("ParentA", "childAA", "childAAA"));
|
||||||
|
|
||||||
|
int idx = codes.indexOf("childAA");
|
||||||
|
assertEquals("childAA", result.getExpansion().getContains().get(idx).getCode());
|
||||||
|
assertEquals("Child AA", result.getExpansion().getContains().get(idx).getDisplay());
|
||||||
|
assertEquals(URL_MY_CODE_SYSTEM, result.getExpansion().getContains().get(idx).getSystem());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExpandWithSystemAndCodesInLocalValueSet() {
|
public void testExpandWithSystemAndCodesInLocalValueSet() {
|
||||||
createLocalCsAndVs();
|
createLocalCsAndVs();
|
||||||
@ -520,6 +596,43 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExpandWithSystemAndDisplayFilterBlank() {
|
||||||
|
CodeSystem codeSystem = createExternalCsDogs();
|
||||||
|
|
||||||
|
ValueSet valueSet = new ValueSet();
|
||||||
|
valueSet.setUrl(URL_MY_VALUE_SET);
|
||||||
|
valueSet.getCompose()
|
||||||
|
.addInclude()
|
||||||
|
.setSystem(codeSystem.getUrl());
|
||||||
|
|
||||||
|
ValueSet result = myValueSetDao.expand(valueSet, "");
|
||||||
|
logAndValidateValueSet(result);
|
||||||
|
|
||||||
|
assertEquals(5, result.getExpansion().getTotal());
|
||||||
|
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
||||||
|
assertThat(codes, containsInAnyOrder("hello", "goodbye", "dogs", "labrador", "beagle"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExpandWithSystemAndFilterInExternalValueSet() {
|
||||||
|
createExternalCsAndLocalVs();
|
||||||
|
|
||||||
|
ValueSet vs = new ValueSet();
|
||||||
|
ConceptSetComponent include = vs.getCompose().addInclude();
|
||||||
|
include.setSystem(URL_MY_CODE_SYSTEM);
|
||||||
|
|
||||||
|
include.addFilter().setProperty("display").setOp(FilterOperator.EQUAL).setValue("Parent B");
|
||||||
|
|
||||||
|
ValueSet result = myValueSetDao.expand(vs, null);
|
||||||
|
logAndValidateValueSet(result);
|
||||||
|
|
||||||
|
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
||||||
|
assertThat(codes, containsInAnyOrder("ParentB"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testIndexingIsDeferredForLargeCodeSystems() {
|
public void testIndexingIsDeferredForLargeCodeSystems() {
|
||||||
myDaoConfig.setDeferIndexingForCodesystemsOfSize(1);
|
myDaoConfig.setDeferIndexingForCodesystemsOfSize(1);
|
||||||
@ -560,6 +673,28 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||||||
assertThat(encoded, containsStringIgnoringCase("<code value=\"childAAB\"/>"));
|
assertThat(encoded, containsStringIgnoringCase("<code value=\"childAAB\"/>"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLookupSnomed() {
|
||||||
|
CodeSystem codeSystem = new CodeSystem();
|
||||||
|
codeSystem.setUrl("http://snomed.info/sct");
|
||||||
|
codeSystem.setContent(CodeSystemContentMode.NOTPRESENT);
|
||||||
|
IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();
|
||||||
|
|
||||||
|
ResourceTable table = myResourceTableDao.findOne(id.getIdPartAsLong());
|
||||||
|
|
||||||
|
TermCodeSystemVersion cs = new TermCodeSystemVersion();
|
||||||
|
cs.setResource(table);
|
||||||
|
cs.setResourceVersionId(table.getVersion());
|
||||||
|
TermConcept parentA = new TermConcept(cs, "ParentA").setDisplay("Parent A");
|
||||||
|
cs.getConcepts().add(parentA);
|
||||||
|
myTermSvc.storeNewCodeSystemVersion(table.getId(), "http://snomed.info/sct", cs);
|
||||||
|
|
||||||
|
StringType code = new StringType("ParentA");
|
||||||
|
StringType system = new StringType("http://snomed.info/sct");
|
||||||
|
LookupCodeResult outcome = myCodeSystemDao.lookupCode(code, system, null, mySrd);
|
||||||
|
assertEquals(true, outcome.isFound());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Can't currently abort costly
|
* Can't currently abort costly
|
||||||
*/
|
*/
|
||||||
@ -594,6 +729,30 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReindex() {
|
||||||
|
createLocalCsAndVs();
|
||||||
|
|
||||||
|
ValueSet vs = new ValueSet();
|
||||||
|
ConceptSetComponent include = vs.getCompose().addInclude();
|
||||||
|
include.setSystem(URL_MY_CODE_SYSTEM);
|
||||||
|
include.addConcept().setCode("ZZZZ");
|
||||||
|
|
||||||
|
mySystemDao.markAllResourcesForReindexing();
|
||||||
|
mySystemDao.performReindexingPass(null);
|
||||||
|
myTermSvc.saveDeferred();
|
||||||
|
mySystemDao.performReindexingPass(null);
|
||||||
|
myTermSvc.saveDeferred();
|
||||||
|
|
||||||
|
// Again
|
||||||
|
mySystemDao.markAllResourcesForReindexing();
|
||||||
|
mySystemDao.performReindexingPass(null);
|
||||||
|
myTermSvc.saveDeferred();
|
||||||
|
mySystemDao.performReindexingPass(null);
|
||||||
|
myTermSvc.saveDeferred();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchCodeAboveLocalCodesystem() {
|
public void testSearchCodeAboveLocalCodesystem() {
|
||||||
createLocalCsAndVs();
|
createLocalCsAndVs();
|
||||||
@ -636,107 +795,6 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSearchCodeBelowLocalCodesystem() {
|
|
||||||
createLocalCsAndVs();
|
|
||||||
|
|
||||||
Observation obsAA = new Observation();
|
|
||||||
obsAA.getCode().addCoding().setSystem(URL_MY_CODE_SYSTEM).setCode("AA");
|
|
||||||
IIdType idAA = myObservationDao.create(obsAA, mySrd).getId().toUnqualifiedVersionless();
|
|
||||||
|
|
||||||
Observation obsBA = new Observation();
|
|
||||||
obsBA.getCode().addCoding().setSystem(URL_MY_CODE_SYSTEM).setCode("BA");
|
|
||||||
IIdType idBA = myObservationDao.create(obsBA, mySrd).getId().toUnqualifiedVersionless();
|
|
||||||
|
|
||||||
Observation obsCA = new Observation();
|
|
||||||
obsCA.getCode().addCoding().setSystem(URL_MY_CODE_SYSTEM).setCode("CA");
|
|
||||||
IIdType idCA = myObservationDao.create(obsCA, mySrd).getId().toUnqualifiedVersionless();
|
|
||||||
|
|
||||||
SearchParameterMap params = new SearchParameterMap();
|
|
||||||
params.add(Observation.SP_CODE, new TokenParam(URL_MY_CODE_SYSTEM, "A").setModifier(TokenParamModifier.BELOW));
|
|
||||||
assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), containsInAnyOrder(idAA.getValue()));
|
|
||||||
|
|
||||||
params = new SearchParameterMap();
|
|
||||||
params.add(Observation.SP_CODE, new TokenParam(URL_MY_CODE_SYSTEM, "AAA").setModifier(TokenParamModifier.BELOW));
|
|
||||||
assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), empty());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSearchCodeInBuiltInValueSet() {
|
|
||||||
AllergyIntolerance ai1 = new AllergyIntolerance();
|
|
||||||
ai1.setClinicalStatus(AllergyIntoleranceClinicalStatus.ACTIVE);
|
|
||||||
String id1 = myAllergyIntoleranceDao.create(ai1, mySrd).getId().toUnqualifiedVersionless().getValue();
|
|
||||||
|
|
||||||
AllergyIntolerance ai2 = new AllergyIntolerance();
|
|
||||||
ai2.setClinicalStatus(AllergyIntoleranceClinicalStatus.RESOLVED);
|
|
||||||
String id2 = myAllergyIntoleranceDao.create(ai2, mySrd).getId().toUnqualifiedVersionless().getValue();
|
|
||||||
|
|
||||||
AllergyIntolerance ai3 = new AllergyIntolerance();
|
|
||||||
ai3.setClinicalStatus(AllergyIntoleranceClinicalStatus.INACTIVE);
|
|
||||||
String id3 = myAllergyIntoleranceDao.create(ai3, mySrd).getId().toUnqualifiedVersionless().getValue();
|
|
||||||
|
|
||||||
SearchParameterMap params;
|
|
||||||
params = new SearchParameterMap();
|
|
||||||
params.add(AllergyIntolerance.SP_CLINICAL_STATUS, new TokenParam(null, "http://hl7.org/fhir/ValueSet/allergy-clinical-status").setModifier(TokenParamModifier.IN));
|
|
||||||
assertThat(toUnqualifiedVersionlessIdValues(myAllergyIntoleranceDao.search(params)), containsInAnyOrder(id1, id2, id3));
|
|
||||||
|
|
||||||
// No codes in this one
|
|
||||||
params = new SearchParameterMap();
|
|
||||||
params.add(AllergyIntolerance.SP_CLINICAL_STATUS, new TokenParam(null, "http://hl7.org/fhir/ValueSet/allergy-intolerance-criticality").setModifier(TokenParamModifier.IN));
|
|
||||||
assertThat(toUnqualifiedVersionlessIdValues(myAllergyIntoleranceDao.search(params)), empty());
|
|
||||||
|
|
||||||
// Invalid VS
|
|
||||||
params = new SearchParameterMap();
|
|
||||||
params.add(AllergyIntolerance.SP_CLINICAL_STATUS, new TokenParam(null, "http://hl7.org/fhir/ValueSet/FOO").setModifier(TokenParamModifier.IN));
|
|
||||||
try {
|
|
||||||
myAllergyIntoleranceDao.search(params);
|
|
||||||
} catch (InvalidRequestException e) {
|
|
||||||
assertEquals("Unable to find imported value set http://hl7.org/fhir/ValueSet/FOO", e.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Todo: not yet implemented
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
@Ignore
|
|
||||||
public void testSearchCodeNotInBuiltInValueSet() {
|
|
||||||
AllergyIntolerance ai1 = new AllergyIntolerance();
|
|
||||||
ai1.setClinicalStatus(AllergyIntoleranceClinicalStatus.ACTIVE);
|
|
||||||
String id1 = myAllergyIntoleranceDao.create(ai1, mySrd).getId().toUnqualifiedVersionless().getValue();
|
|
||||||
|
|
||||||
AllergyIntolerance ai2 = new AllergyIntolerance();
|
|
||||||
ai2.setClinicalStatus(AllergyIntoleranceClinicalStatus.RESOLVED);
|
|
||||||
String id2 = myAllergyIntoleranceDao.create(ai2, mySrd).getId().toUnqualifiedVersionless().getValue();
|
|
||||||
|
|
||||||
AllergyIntolerance ai3 = new AllergyIntolerance();
|
|
||||||
ai3.setClinicalStatus(AllergyIntoleranceClinicalStatus.INACTIVE);
|
|
||||||
String id3 = myAllergyIntoleranceDao.create(ai3, mySrd).getId().toUnqualifiedVersionless().getValue();
|
|
||||||
|
|
||||||
SearchParameterMap params;
|
|
||||||
params = new SearchParameterMap();
|
|
||||||
params.add(AllergyIntolerance.SP_CLINICAL_STATUS, new TokenParam(null, "http://hl7.org/fhir/ValueSet/allergy-intolerance-status").setModifier(TokenParamModifier.NOT_IN));
|
|
||||||
assertThat(toUnqualifiedVersionlessIdValues(myAllergyIntoleranceDao.search(params)), empty());
|
|
||||||
|
|
||||||
// No codes in this one
|
|
||||||
params = new SearchParameterMap();
|
|
||||||
params.add(AllergyIntolerance.SP_CLINICAL_STATUS, new TokenParam(null, "http://hl7.org/fhir/ValueSet/allergy-intolerance-criticality").setModifier(TokenParamModifier.NOT_IN));
|
|
||||||
assertThat(toUnqualifiedVersionlessIdValues(myAllergyIntoleranceDao.search(params)), containsInAnyOrder(id1, id2, id3));
|
|
||||||
|
|
||||||
// Invalid VS
|
|
||||||
params = new SearchParameterMap();
|
|
||||||
params.add(AllergyIntolerance.SP_CLINICAL_STATUS, new TokenParam(null, "http://hl7.org/fhir/ValueSet/FOO").setModifier(TokenParamModifier.NOT_IN));
|
|
||||||
try {
|
|
||||||
myAllergyIntoleranceDao.search(params);
|
|
||||||
} catch (InvalidRequestException e) {
|
|
||||||
assertEquals("Unable to find imported value set http://hl7.org/fhir/ValueSet/FOO", e.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchCodeBelowBuiltInCodesystem() {
|
public void testSearchCodeBelowBuiltInCodesystem() {
|
||||||
AllergyIntolerance ai1 = new AllergyIntolerance();
|
AllergyIntolerance ai1 = new AllergyIntolerance();
|
||||||
@ -824,6 +882,68 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchCodeBelowLocalCodesystem() {
|
||||||
|
createLocalCsAndVs();
|
||||||
|
|
||||||
|
Observation obsAA = new Observation();
|
||||||
|
obsAA.getCode().addCoding().setSystem(URL_MY_CODE_SYSTEM).setCode("AA");
|
||||||
|
IIdType idAA = myObservationDao.create(obsAA, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
Observation obsBA = new Observation();
|
||||||
|
obsBA.getCode().addCoding().setSystem(URL_MY_CODE_SYSTEM).setCode("BA");
|
||||||
|
IIdType idBA = myObservationDao.create(obsBA, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
Observation obsCA = new Observation();
|
||||||
|
obsCA.getCode().addCoding().setSystem(URL_MY_CODE_SYSTEM).setCode("CA");
|
||||||
|
IIdType idCA = myObservationDao.create(obsCA, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
SearchParameterMap params = new SearchParameterMap();
|
||||||
|
params.add(Observation.SP_CODE, new TokenParam(URL_MY_CODE_SYSTEM, "A").setModifier(TokenParamModifier.BELOW));
|
||||||
|
assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), containsInAnyOrder(idAA.getValue()));
|
||||||
|
|
||||||
|
params = new SearchParameterMap();
|
||||||
|
params.add(Observation.SP_CODE, new TokenParam(URL_MY_CODE_SYSTEM, "AAA").setModifier(TokenParamModifier.BELOW));
|
||||||
|
assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), empty());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchCodeInBuiltInValueSet() {
|
||||||
|
AllergyIntolerance ai1 = new AllergyIntolerance();
|
||||||
|
ai1.setClinicalStatus(AllergyIntoleranceClinicalStatus.ACTIVE);
|
||||||
|
String id1 = myAllergyIntoleranceDao.create(ai1, mySrd).getId().toUnqualifiedVersionless().getValue();
|
||||||
|
|
||||||
|
AllergyIntolerance ai2 = new AllergyIntolerance();
|
||||||
|
ai2.setClinicalStatus(AllergyIntoleranceClinicalStatus.RESOLVED);
|
||||||
|
String id2 = myAllergyIntoleranceDao.create(ai2, mySrd).getId().toUnqualifiedVersionless().getValue();
|
||||||
|
|
||||||
|
AllergyIntolerance ai3 = new AllergyIntolerance();
|
||||||
|
ai3.setClinicalStatus(AllergyIntoleranceClinicalStatus.INACTIVE);
|
||||||
|
String id3 = myAllergyIntoleranceDao.create(ai3, mySrd).getId().toUnqualifiedVersionless().getValue();
|
||||||
|
|
||||||
|
SearchParameterMap params;
|
||||||
|
params = new SearchParameterMap();
|
||||||
|
params.add(AllergyIntolerance.SP_CLINICAL_STATUS, new TokenParam(null, "http://hl7.org/fhir/ValueSet/allergy-clinical-status").setModifier(TokenParamModifier.IN));
|
||||||
|
assertThat(toUnqualifiedVersionlessIdValues(myAllergyIntoleranceDao.search(params)), containsInAnyOrder(id1, id2, id3));
|
||||||
|
|
||||||
|
// No codes in this one
|
||||||
|
params = new SearchParameterMap();
|
||||||
|
params.add(AllergyIntolerance.SP_CLINICAL_STATUS, new TokenParam(null, "http://hl7.org/fhir/ValueSet/allergy-intolerance-criticality").setModifier(TokenParamModifier.IN));
|
||||||
|
assertThat(toUnqualifiedVersionlessIdValues(myAllergyIntoleranceDao.search(params)), empty());
|
||||||
|
|
||||||
|
// Invalid VS
|
||||||
|
params = new SearchParameterMap();
|
||||||
|
params.add(AllergyIntolerance.SP_CLINICAL_STATUS, new TokenParam(null, "http://hl7.org/fhir/ValueSet/FOO").setModifier(TokenParamModifier.IN));
|
||||||
|
try {
|
||||||
|
myAllergyIntoleranceDao.search(params);
|
||||||
|
} catch (InvalidRequestException e) {
|
||||||
|
assertEquals("Unable to find imported value set http://hl7.org/fhir/ValueSet/FOO", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchCodeInEmptyValueSet() {
|
public void testSearchCodeInEmptyValueSet() {
|
||||||
ValueSet valueSet = new ValueSet();
|
ValueSet valueSet = new ValueSet();
|
||||||
@ -848,40 +968,6 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||||||
ourLog.info("testSearchCodeInEmptyValueSet done");
|
ourLog.info("testSearchCodeInEmptyValueSet done");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSearchCodeInValueSetThatImportsInvalidCodeSystem() {
|
|
||||||
ValueSet valueSet = new ValueSet();
|
|
||||||
valueSet.getCompose().addInclude().addValueSet("http://non_existant_VS");
|
|
||||||
valueSet.setUrl(URL_MY_VALUE_SET);
|
|
||||||
IIdType vsid = myValueSetDao.create(valueSet, mySrd).getId().toUnqualifiedVersionless();
|
|
||||||
|
|
||||||
SearchParameterMap params;
|
|
||||||
|
|
||||||
ourLog.info("testSearchCodeInEmptyValueSet without status");
|
|
||||||
|
|
||||||
params = new SearchParameterMap();
|
|
||||||
params.add(Observation.SP_CODE, new TokenParam(null, URL_MY_VALUE_SET).setModifier(TokenParamModifier.IN));
|
|
||||||
try {
|
|
||||||
myObservationDao.search(params);
|
|
||||||
} catch(InvalidRequestException e) {
|
|
||||||
assertEquals("Unable to expand imported value set: Unable to find imported value set http://non_existant_VS", e.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now let's update
|
|
||||||
valueSet = new ValueSet();
|
|
||||||
valueSet.setId(vsid);
|
|
||||||
valueSet.getCompose().addInclude().setSystem("http://hl7.org/fhir/v3/MaritalStatus").addConcept().setCode("A");
|
|
||||||
valueSet.setUrl(URL_MY_VALUE_SET);
|
|
||||||
myValueSetDao.update(valueSet, mySrd).getId().toUnqualifiedVersionless();
|
|
||||||
|
|
||||||
params = new SearchParameterMap();
|
|
||||||
params.add(Observation.SP_CODE, new TokenParam(null, URL_MY_VALUE_SET).setModifier(TokenParamModifier.IN));
|
|
||||||
params.add(Observation.SP_STATUS, new TokenParam(null, "final"));
|
|
||||||
assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), empty());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchCodeInExternalCodesystem() {
|
public void testSearchCodeInExternalCodesystem() {
|
||||||
createExternalCsAndLocalVs();
|
createExternalCsAndLocalVs();
|
||||||
@ -941,6 +1027,7 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||||||
assertThat(toUnqualifiedVersionlessIdValues(myAuditEventDao.search(params)), empty());
|
assertThat(toUnqualifiedVersionlessIdValues(myAuditEventDao.search(params)), empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchCodeInLocalCodesystem() {
|
public void testSearchCodeInLocalCodesystem() {
|
||||||
createLocalCsAndVs();
|
createLocalCsAndVs();
|
||||||
@ -963,6 +1050,78 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchCodeInValueSetThatImportsInvalidCodeSystem() {
|
||||||
|
ValueSet valueSet = new ValueSet();
|
||||||
|
valueSet.getCompose().addInclude().addValueSet("http://non_existant_VS");
|
||||||
|
valueSet.setUrl(URL_MY_VALUE_SET);
|
||||||
|
IIdType vsid = myValueSetDao.create(valueSet, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
SearchParameterMap params;
|
||||||
|
|
||||||
|
ourLog.info("testSearchCodeInEmptyValueSet without status");
|
||||||
|
|
||||||
|
params = new SearchParameterMap();
|
||||||
|
params.add(Observation.SP_CODE, new TokenParam(null, URL_MY_VALUE_SET).setModifier(TokenParamModifier.IN));
|
||||||
|
try {
|
||||||
|
myObservationDao.search(params);
|
||||||
|
} catch(InvalidRequestException e) {
|
||||||
|
assertEquals("Unable to expand imported value set: Unable to find imported value set http://non_existant_VS", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now let's update
|
||||||
|
valueSet = new ValueSet();
|
||||||
|
valueSet.setId(vsid);
|
||||||
|
valueSet.getCompose().addInclude().setSystem("http://hl7.org/fhir/v3/MaritalStatus").addConcept().setCode("A");
|
||||||
|
valueSet.setUrl(URL_MY_VALUE_SET);
|
||||||
|
myValueSetDao.update(valueSet, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
params = new SearchParameterMap();
|
||||||
|
params.add(Observation.SP_CODE, new TokenParam(null, URL_MY_VALUE_SET).setModifier(TokenParamModifier.IN));
|
||||||
|
params.add(Observation.SP_STATUS, new TokenParam(null, "final"));
|
||||||
|
assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), empty());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Todo: not yet implemented
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
@Ignore
|
||||||
|
public void testSearchCodeNotInBuiltInValueSet() {
|
||||||
|
AllergyIntolerance ai1 = new AllergyIntolerance();
|
||||||
|
ai1.setClinicalStatus(AllergyIntoleranceClinicalStatus.ACTIVE);
|
||||||
|
String id1 = myAllergyIntoleranceDao.create(ai1, mySrd).getId().toUnqualifiedVersionless().getValue();
|
||||||
|
|
||||||
|
AllergyIntolerance ai2 = new AllergyIntolerance();
|
||||||
|
ai2.setClinicalStatus(AllergyIntoleranceClinicalStatus.RESOLVED);
|
||||||
|
String id2 = myAllergyIntoleranceDao.create(ai2, mySrd).getId().toUnqualifiedVersionless().getValue();
|
||||||
|
|
||||||
|
AllergyIntolerance ai3 = new AllergyIntolerance();
|
||||||
|
ai3.setClinicalStatus(AllergyIntoleranceClinicalStatus.INACTIVE);
|
||||||
|
String id3 = myAllergyIntoleranceDao.create(ai3, mySrd).getId().toUnqualifiedVersionless().getValue();
|
||||||
|
|
||||||
|
SearchParameterMap params;
|
||||||
|
params = new SearchParameterMap();
|
||||||
|
params.add(AllergyIntolerance.SP_CLINICAL_STATUS, new TokenParam(null, "http://hl7.org/fhir/ValueSet/allergy-intolerance-status").setModifier(TokenParamModifier.NOT_IN));
|
||||||
|
assertThat(toUnqualifiedVersionlessIdValues(myAllergyIntoleranceDao.search(params)), empty());
|
||||||
|
|
||||||
|
// No codes in this one
|
||||||
|
params = new SearchParameterMap();
|
||||||
|
params.add(AllergyIntolerance.SP_CLINICAL_STATUS, new TokenParam(null, "http://hl7.org/fhir/ValueSet/allergy-intolerance-criticality").setModifier(TokenParamModifier.NOT_IN));
|
||||||
|
assertThat(toUnqualifiedVersionlessIdValues(myAllergyIntoleranceDao.search(params)), containsInAnyOrder(id1, id2, id3));
|
||||||
|
|
||||||
|
// Invalid VS
|
||||||
|
params = new SearchParameterMap();
|
||||||
|
params.add(AllergyIntolerance.SP_CLINICAL_STATUS, new TokenParam(null, "http://hl7.org/fhir/ValueSet/FOO").setModifier(TokenParamModifier.NOT_IN));
|
||||||
|
try {
|
||||||
|
myAllergyIntoleranceDao.search(params);
|
||||||
|
} catch (InvalidRequestException e) {
|
||||||
|
assertEquals("Unable to find imported value set http://hl7.org/fhir/ValueSet/FOO", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private ArrayList<String> toCodesContains(List<ValueSetExpansionContainsComponent> theContains) {
|
private ArrayList<String> toCodesContains(List<ValueSetExpansionContainsComponent> theContains) {
|
||||||
ArrayList<String> retVal = new ArrayList<String>();
|
ArrayList<String> retVal = new ArrayList<String>();
|
||||||
for (ValueSetExpansionContainsComponent next : theContains) {
|
for (ValueSetExpansionContainsComponent next : theContains) {
|
||||||
|
5
hapi-fhir-structures-dstu3/.editorconfig
Normal file
5
hapi-fhir-structures-dstu3/.editorconfig
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
[*.java]
|
||||||
|
charset = utf-8
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
@ -6,33 +6,33 @@ import java.io.FileNotFoundException;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2011+, HL7, Inc
|
* Copyright (c) 2011+, HL7, Inc
|
||||||
All rights reserved.
|
* All rights reserved.
|
||||||
|
*
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
are permitted provided that the following conditions are met:
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
* Redistributions of source code must retain the above copyright notice, this
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
list of conditions and the following disclaimer.
|
* list of conditions and the following disclaimer.
|
||||||
* Redistributions in binary form must reproduce the above copyright notice,
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
this list of conditions and the following disclaimer in the documentation
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
and/or other materials provided with the distribution.
|
* and/or other materials provided with the distribution.
|
||||||
* Neither the name of HL7 nor the names of its contributors may be used to
|
* Neither the name of HL7 nor the names of its contributors may be used to
|
||||||
endorse or promote products derived from this software without specific
|
* endorse or promote products derived from this software without specific
|
||||||
prior written permission.
|
* prior written permission.
|
||||||
|
*
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -72,66 +72,67 @@ import org.hl7.fhir.utilities.Utilities;
|
|||||||
|
|
||||||
public class ValueSetExpanderSimple implements ValueSetExpander {
|
public class ValueSetExpanderSimple implements ValueSetExpander {
|
||||||
|
|
||||||
private List<ValueSetExpansionContainsComponent> codes = new ArrayList<ValueSet.ValueSetExpansionContainsComponent>();
|
private List<ValueSetExpansionContainsComponent> codes = new ArrayList<ValueSet.ValueSetExpansionContainsComponent>();
|
||||||
private List<ValueSetExpansionContainsComponent> roots = new ArrayList<ValueSet.ValueSetExpansionContainsComponent>();
|
private List<ValueSetExpansionContainsComponent> roots = new ArrayList<ValueSet.ValueSetExpansionContainsComponent>();
|
||||||
private Map<String, ValueSetExpansionContainsComponent> map = new HashMap<String, ValueSet.ValueSetExpansionContainsComponent>();
|
private Map<String, ValueSetExpansionContainsComponent> map = new HashMap<String, ValueSet.ValueSetExpansionContainsComponent>();
|
||||||
private IWorkerContext context;
|
private IWorkerContext context;
|
||||||
private boolean canBeHeirarchy = true;
|
private boolean canBeHeirarchy = true;
|
||||||
private Set<String> excludeKeys = new HashSet<String>();
|
private Set<String> excludeKeys = new HashSet<String>();
|
||||||
private Set<String> excludeSystems = new HashSet<String>();
|
private Set<String> excludeSystems = new HashSet<String>();
|
||||||
private ValueSetExpanderFactory factory;
|
private ValueSetExpanderFactory factory;
|
||||||
private ValueSet focus;
|
private ValueSet focus;
|
||||||
private int maxExpansionSize = 500;
|
private int maxExpansionSize = 500;
|
||||||
|
|
||||||
private int total;
|
private int total;
|
||||||
|
|
||||||
public ValueSetExpanderSimple(IWorkerContext context, ValueSetExpanderFactory factory) {
|
public ValueSetExpanderSimple(IWorkerContext context, ValueSetExpanderFactory factory) {
|
||||||
super();
|
super();
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.factory = factory;
|
this.factory = factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMaxExpansionSize(int theMaxExpansionSize) {
|
public void setMaxExpansionSize(int theMaxExpansionSize) {
|
||||||
maxExpansionSize = theMaxExpansionSize;
|
maxExpansionSize = theMaxExpansionSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ValueSetExpansionContainsComponent addCode(String system, String code, String display, ValueSetExpansionContainsComponent parent, List<ConceptDefinitionDesignationComponent> designations,
|
||||||
private ValueSetExpansionContainsComponent addCode(String system, String code, String display, ValueSetExpansionContainsComponent parent, List<ConceptDefinitionDesignationComponent> designations, ExpansionProfile profile, boolean isAbstract, boolean inactive, List<ValueSet> filters) {
|
ExpansionProfile profile, boolean isAbstract, boolean inactive, List<ValueSet> filters) {
|
||||||
if (filters != null && !filters.isEmpty() && !filterContainsCode(filters, system, code))
|
if (filters != null && !filters.isEmpty() && !filterContainsCode(filters, system, code))
|
||||||
return null;
|
return null;
|
||||||
ValueSetExpansionContainsComponent n = new ValueSet.ValueSetExpansionContainsComponent();
|
ValueSetExpansionContainsComponent n = new ValueSet.ValueSetExpansionContainsComponent();
|
||||||
n.setSystem(system);
|
n.setSystem(system);
|
||||||
n.setCode(code);
|
n.setCode(code);
|
||||||
if (isAbstract)
|
if (isAbstract)
|
||||||
n.setAbstract(true);
|
n.setAbstract(true);
|
||||||
if (inactive)
|
if (inactive)
|
||||||
n.setInactive(true);
|
n.setInactive(true);
|
||||||
|
|
||||||
if (profile.getIncludeDesignations() && designations != null) {
|
if (profile.getIncludeDesignations() && designations != null) {
|
||||||
for (ConceptDefinitionDesignationComponent t : designations) {
|
for (ConceptDefinitionDesignationComponent t : designations) {
|
||||||
ToolingExtensions.addLanguageTranslation(n, t.getLanguage(), t.getValue());
|
ToolingExtensions.addLanguageTranslation(n, t.getLanguage(), t.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ConceptDefinitionDesignationComponent t = profile.hasLanguage() ? getMatchingLang(designations, profile.getLanguage()) : null;
|
ConceptDefinitionDesignationComponent t = profile.hasLanguage() ? getMatchingLang(designations, profile.getLanguage()) : null;
|
||||||
if (t == null)
|
if (t == null)
|
||||||
n.setDisplay(display);
|
n.setDisplay(display);
|
||||||
else
|
else
|
||||||
n.setDisplay(t.getValue());
|
n.setDisplay(t.getValue());
|
||||||
|
|
||||||
String s = key(n);
|
String s = key(n);
|
||||||
if (map.containsKey(s) || excludeKeys.contains(s)) {
|
if (map.containsKey(s) || excludeKeys.contains(s)) {
|
||||||
canBeHeirarchy = false;
|
canBeHeirarchy = false;
|
||||||
} else {
|
} else {
|
||||||
codes.add(n);
|
codes.add(n);
|
||||||
map.put(s, n);
|
map.put(s, n);
|
||||||
}
|
total++;
|
||||||
if (canBeHeirarchy && parent != null) {
|
}
|
||||||
parent.getContains().add(n);
|
if (canBeHeirarchy && parent != null) {
|
||||||
} else {
|
parent.getContains().add(n);
|
||||||
roots.add(n);
|
} else {
|
||||||
}
|
roots.add(n);
|
||||||
return n;
|
}
|
||||||
}
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean filterContainsCode(List<ValueSet> filters, String system, String code) {
|
private boolean filterContainsCode(List<ValueSet> filters, String system, String code) {
|
||||||
for (ValueSet vse : filters)
|
for (ValueSet vse : filters)
|
||||||
@ -160,93 +161,92 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addCodeAndDescendents(CodeSystem cs, String system, ConceptDefinitionComponent def, ValueSetExpansionContainsComponent parent, ExpansionProfile profile, List<ValueSet> filters) throws FHIRException {
|
private void addCodeAndDescendents(CodeSystem cs, String system, ConceptDefinitionComponent def, ValueSetExpansionContainsComponent parent, ExpansionProfile profile, List<ValueSet> filters)
|
||||||
if (!CodeSystemUtilities.isDeprecated(cs, def)) {
|
throws FHIRException {
|
||||||
ValueSetExpansionContainsComponent np = null;
|
if (!CodeSystemUtilities.isDeprecated(cs, def)) {
|
||||||
|
ValueSetExpansionContainsComponent np = null;
|
||||||
boolean abs = CodeSystemUtilities.isNotSelectable(cs, def);
|
boolean abs = CodeSystemUtilities.isNotSelectable(cs, def);
|
||||||
boolean inc = CodeSystemUtilities.isInactive(cs, def);
|
boolean inc = CodeSystemUtilities.isInactive(cs, def);
|
||||||
if (canBeHeirarchy || !abs)
|
if (canBeHeirarchy || !abs)
|
||||||
np = addCode(system, def.getCode(), def.getDisplay(), parent, def.getDesignation(), profile, abs, inc, filters);
|
np = addCode(system, def.getCode(), def.getDisplay(), parent, def.getDesignation(), profile, abs, inc, filters);
|
||||||
for (ConceptDefinitionComponent c : def.getConcept())
|
for (ConceptDefinitionComponent c : def.getConcept())
|
||||||
addCodeAndDescendents(cs, system, c, np, profile, filters);
|
addCodeAndDescendents(cs, system, c, np, profile, filters);
|
||||||
} else
|
} else
|
||||||
for (ConceptDefinitionComponent c : def.getConcept())
|
for (ConceptDefinitionComponent c : def.getConcept())
|
||||||
addCodeAndDescendents(cs, system, c, null, profile, filters);
|
addCodeAndDescendents(cs, system, c, null, profile, filters);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addCodes(ValueSetExpansionComponent expand, List<ValueSetExpansionParameterComponent> params, ExpansionProfile profile, List<ValueSet> filters) throws ETooCostly {
|
private void addCodes(ValueSetExpansionComponent expand, List<ValueSetExpansionParameterComponent> params, ExpansionProfile profile, List<ValueSet> filters) throws ETooCostly {
|
||||||
if (expand.getContains().size() > maxExpansionSize)
|
if (expand.getContains().size() > maxExpansionSize)
|
||||||
throw new ETooCostly("Too many codes to display (>" + Integer.toString(expand.getContains().size()) + ")");
|
throw new ETooCostly("Too many codes to display (>" + Integer.toString(expand.getContains().size()) + ")");
|
||||||
for (ValueSetExpansionParameterComponent p : expand.getParameter()) {
|
for (ValueSetExpansionParameterComponent p : expand.getParameter()) {
|
||||||
if (!existsInParams(params, p.getName(), p.getValue()))
|
if (!existsInParams(params, p.getName(), p.getValue()))
|
||||||
params.add(p);
|
params.add(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
copyImportContains(expand.getContains(), null, profile, filters);
|
copyImportContains(expand.getContains(), null, profile, filters);
|
||||||
|
}
|
||||||
total = expand.getTotal();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void excludeCode(String theSystem, String theCode) {
|
private void excludeCode(String theSystem, String theCode) {
|
||||||
ValueSetExpansionContainsComponent n = new ValueSet.ValueSetExpansionContainsComponent();
|
ValueSetExpansionContainsComponent n = new ValueSet.ValueSetExpansionContainsComponent();
|
||||||
n.setSystem(theSystem);
|
n.setSystem(theSystem);
|
||||||
n.setCode(theCode);
|
n.setCode(theCode);
|
||||||
String s = key(n);
|
String s = key(n);
|
||||||
excludeKeys.add(s);
|
excludeKeys.add(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void excludeCodes(ConceptSetComponent exc, List<ValueSetExpansionParameterComponent> params) throws TerminologyServiceException {
|
private void excludeCodes(ConceptSetComponent exc, List<ValueSetExpansionParameterComponent> params) throws TerminologyServiceException {
|
||||||
if (exc.hasSystem() && exc.getConcept().size() == 0 && exc.getFilter().size() == 0) {
|
if (exc.hasSystem() && exc.getConcept().size() == 0 && exc.getFilter().size() == 0) {
|
||||||
excludeSystems.add(exc.getSystem());
|
excludeSystems.add(exc.getSystem());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exc.hasValueSet())
|
if (exc.hasValueSet())
|
||||||
throw new Error("Processing Value set references in exclude is not yet done");
|
throw new Error("Processing Value set references in exclude is not yet done");
|
||||||
// importValueSet(imp.getValue(), params, profile);
|
// importValueSet(imp.getValue(), params, profile);
|
||||||
|
|
||||||
CodeSystem cs = context.fetchCodeSystem(exc.getSystem());
|
CodeSystem cs = context.fetchCodeSystem(exc.getSystem());
|
||||||
if ((cs == null || cs.getContent() != CodeSystemContentMode.COMPLETE) && context.supportsSystem(exc.getSystem())) {
|
if ((cs == null || cs.getContent() != CodeSystemContentMode.COMPLETE) && context.supportsSystem(exc.getSystem())) {
|
||||||
excludeCodes(context.expandVS(exc, false), params);
|
excludeCodes(context.expandVS(exc, false), params);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ConceptReferenceComponent c : exc.getConcept()) {
|
for (ConceptReferenceComponent c : exc.getConcept()) {
|
||||||
excludeCode(exc.getSystem(), c.getCode());
|
excludeCode(exc.getSystem(), c.getCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exc.getFilter().size() > 0)
|
|
||||||
throw new NotImplementedException("not done yet");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void excludeCodes(ValueSetExpansionComponent expand, List<ValueSetExpansionParameterComponent> params) {
|
if (exc.getFilter().size() > 0)
|
||||||
for (ValueSetExpansionContainsComponent c : expand.getContains()) {
|
throw new NotImplementedException("not done yet");
|
||||||
excludeCode(c.getSystem(), c.getCode());
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean existsInParams(List<ValueSetExpansionParameterComponent> params, String name, Type value) {
|
private void excludeCodes(ValueSetExpansionComponent expand, List<ValueSetExpansionParameterComponent> params) {
|
||||||
for (ValueSetExpansionParameterComponent p : params) {
|
for (ValueSetExpansionContainsComponent c : expand.getContains()) {
|
||||||
if (p.getName().equals(name) && PrimitiveType.compareDeep(p.getValue(), value, false))
|
excludeCode(c.getSystem(), c.getCode());
|
||||||
return true;
|
}
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
private boolean existsInParams(List<ValueSetExpansionParameterComponent> params, String name, Type value) {
|
||||||
|
for (ValueSetExpansionParameterComponent p : params) {
|
||||||
|
if (p.getName().equals(name) && PrimitiveType.compareDeep(p.getValue(), value, false))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public ValueSetExpansionOutcome expand(ValueSet source, ExpansionProfile profile) {
|
public ValueSetExpansionOutcome expand(ValueSet source, ExpansionProfile profile) {
|
||||||
|
|
||||||
if (profile == null)
|
if (profile == null)
|
||||||
profile = makeDefaultExpansion();
|
profile = makeDefaultExpansion();
|
||||||
try {
|
try {
|
||||||
focus = source.copy();
|
focus = source.copy();
|
||||||
focus.setExpansion(new ValueSet.ValueSetExpansionComponent());
|
focus.setExpansion(new ValueSet.ValueSetExpansionComponent());
|
||||||
focus.getExpansion().setTimestampElement(DateTimeType.now());
|
focus.getExpansion().setTimestampElement(DateTimeType.now());
|
||||||
focus.getExpansion().setIdentifier(Factory.createUUID());
|
focus.getExpansion().setIdentifier(Factory.createUUID());
|
||||||
if (!profile.getUrl().startsWith("urn:uuid:"))
|
if (!profile.getUrl().startsWith("urn:uuid:"))
|
||||||
focus.getExpansion().addParameter().setName("profile").setValue(new UriType(profile.getUrl()));
|
focus.getExpansion().addParameter().setName("profile").setValue(new UriType(profile.getUrl()));
|
||||||
|
|
||||||
if (source.hasCompose())
|
if (source.hasCompose())
|
||||||
handleCompose(source.getCompose(), focus.getExpansion().getParameter(), profile);
|
handleCompose(source.getCompose(), focus.getExpansion().getParameter(), profile);
|
||||||
|
|
||||||
if (canBeHeirarchy) {
|
if (canBeHeirarchy) {
|
||||||
@ -254,38 +254,38 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
|
|||||||
focus.getExpansion().getContains().add(c);
|
focus.getExpansion().getContains().add(c);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (ValueSetExpansionContainsComponent c : codes) {
|
for (ValueSetExpansionContainsComponent c : codes) {
|
||||||
if (map.containsKey(key(c)) && !c.getAbstract()) { // we may have added abstract codes earlier while we still thought it might be heirarchical, but later we gave up, so now ignore them
|
if (map.containsKey(key(c)) && !c.getAbstract()) { // we may have added abstract codes earlier while we still thought it might be heirarchical, but later we gave up, so now ignore them
|
||||||
focus.getExpansion().getContains().add(c);
|
focus.getExpansion().getContains().add(c);
|
||||||
c.getContains().clear(); // make sure any heirarchy is wiped
|
c.getContains().clear(); // make sure any heirarchy is wiped
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (total > 0) {
|
if (total > 0) {
|
||||||
focus.getExpansion().setTotal(total);
|
focus.getExpansion().setTotal(total);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ValueSetExpansionOutcome(focus);
|
return new ValueSetExpansionOutcome(focus);
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
// TODO: we should put something more specific instead of just Exception below, since
|
// TODO: we should put something more specific instead of just Exception below, since
|
||||||
// it swallows bugs.. what would be expected to be caught there?
|
// it swallows bugs.. what would be expected to be caught there?
|
||||||
throw e;
|
throw e;
|
||||||
} catch (NoTerminologyServiceException e) {
|
} catch (NoTerminologyServiceException e) {
|
||||||
// well, we couldn't expand, so we'll return an interface to a checker that can check membership of the set
|
// well, we couldn't expand, so we'll return an interface to a checker that can check membership of the set
|
||||||
// that might fail too, but it might not, later.
|
// that might fail too, but it might not, later.
|
||||||
return new ValueSetExpansionOutcome(new ValueSetCheckerSimple(source, factory, context), e.getMessage(), TerminologyServiceErrorClass.NOSERVICE);
|
return new ValueSetExpansionOutcome(new ValueSetCheckerSimple(source, factory, context), e.getMessage(), TerminologyServiceErrorClass.NOSERVICE);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// well, we couldn't expand, so we'll return an interface to a checker that can check membership of the set
|
// well, we couldn't expand, so we'll return an interface to a checker that can check membership of the set
|
||||||
// that might fail too, but it might not, later.
|
// that might fail too, but it might not, later.
|
||||||
return new ValueSetExpansionOutcome(new ValueSetCheckerSimple(source, factory, context), e.getMessage(), TerminologyServiceErrorClass.UNKNOWN);
|
return new ValueSetExpansionOutcome(new ValueSetCheckerSimple(source, factory, context), e.getMessage(), TerminologyServiceErrorClass.UNKNOWN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ExpansionProfile makeDefaultExpansion() {
|
private ExpansionProfile makeDefaultExpansion() {
|
||||||
ExpansionProfile res = new ExpansionProfile();
|
ExpansionProfile res = new ExpansionProfile();
|
||||||
res.setUrl("urn:uuid:"+UUID.randomUUID().toString().toLowerCase());
|
res.setUrl("urn:uuid:" + UUID.randomUUID().toString().toLowerCase());
|
||||||
res.setExcludeNested(true);
|
res.setExcludeNested(true);
|
||||||
res.setIncludeDesignations(false);
|
res.setIncludeDesignations(false);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -296,68 +296,70 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getCodeDisplay(CodeSystem cs, String code) throws TerminologyServiceException {
|
private String getCodeDisplay(CodeSystem cs, String code) throws TerminologyServiceException {
|
||||||
ConceptDefinitionComponent def = getConceptForCode(cs.getConcept(), code);
|
ConceptDefinitionComponent def = getConceptForCode(cs.getConcept(), code);
|
||||||
if (def == null)
|
if (def == null)
|
||||||
throw new TerminologyServiceException("Unable to find code '" + code + "' in code system " + cs.getUrl());
|
throw new TerminologyServiceException("Unable to find code '" + code + "' in code system " + cs.getUrl());
|
||||||
return def.getDisplay();
|
return def.getDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConceptDefinitionComponent getConceptForCode(List<ConceptDefinitionComponent> clist, String code) {
|
private ConceptDefinitionComponent getConceptForCode(List<ConceptDefinitionComponent> clist, String code) {
|
||||||
for (ConceptDefinitionComponent c : clist) {
|
for (ConceptDefinitionComponent c : clist) {
|
||||||
if (code.equals(c.getCode()))
|
if (code.equals(c.getCode()))
|
||||||
return c;
|
return c;
|
||||||
ConceptDefinitionComponent v = getConceptForCode(c.getConcept(), code);
|
ConceptDefinitionComponent v = getConceptForCode(c.getConcept(), code);
|
||||||
if (v != null)
|
if (v != null)
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleCompose(ValueSetComposeComponent compose, List<ValueSetExpansionParameterComponent> params, ExpansionProfile profile) throws ETooCostly, FileNotFoundException, IOException, FHIRException {
|
private void handleCompose(ValueSetComposeComponent compose, List<ValueSetExpansionParameterComponent> params, ExpansionProfile profile)
|
||||||
// Exclude comes first because we build up a map of things to exclude
|
throws ETooCostly, FileNotFoundException, IOException, FHIRException {
|
||||||
for (ConceptSetComponent inc : compose.getExclude())
|
// Exclude comes first because we build up a map of things to exclude
|
||||||
excludeCodes(inc, params);
|
for (ConceptSetComponent inc : compose.getExclude())
|
||||||
|
excludeCodes(inc, params);
|
||||||
canBeHeirarchy = !profile.getExcludeNested() && excludeKeys.isEmpty() && excludeSystems.isEmpty();
|
canBeHeirarchy = !profile.getExcludeNested() && excludeKeys.isEmpty() && excludeSystems.isEmpty();
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
for (ConceptSetComponent inc : compose.getInclude()) {
|
for (ConceptSetComponent inc : compose.getInclude()) {
|
||||||
if (first == true)
|
if (first == true)
|
||||||
first = false;
|
first = false;
|
||||||
else
|
else
|
||||||
canBeHeirarchy = false;
|
canBeHeirarchy = false;
|
||||||
includeCodes(inc, params, profile);
|
includeCodes(inc, params, profile);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ValueSet importValueSet(String value, List<ValueSetExpansionParameterComponent> params, ExpansionProfile profile) throws ETooCostly, TerminologyServiceException, FileNotFoundException, IOException {
|
private ValueSet importValueSet(String value, List<ValueSetExpansionParameterComponent> params, ExpansionProfile profile)
|
||||||
if (value == null)
|
throws ETooCostly, TerminologyServiceException, FileNotFoundException, IOException {
|
||||||
throw new TerminologyServiceException("unable to find value set with no identity");
|
if (value == null)
|
||||||
ValueSet vs = context.fetchResource(ValueSet.class, value);
|
throw new TerminologyServiceException("unable to find value set with no identity");
|
||||||
if (vs == null)
|
ValueSet vs = context.fetchResource(ValueSet.class, value);
|
||||||
throw new TerminologyServiceException("Unable to find imported value set " + value);
|
if (vs == null)
|
||||||
ValueSetExpansionOutcome vso = factory.getExpander().expand(vs, profile);
|
throw new TerminologyServiceException("Unable to find imported value set " + value);
|
||||||
|
ValueSetExpansionOutcome vso = factory.getExpander().expand(vs, profile);
|
||||||
if (vso.getError() != null)
|
if (vso.getError() != null)
|
||||||
throw new TerminologyServiceException("Unable to expand imported value set: "+vso.getError());
|
throw new TerminologyServiceException("Unable to expand imported value set: " + vso.getError());
|
||||||
if (vso.getService() != null)
|
if (vso.getService() != null)
|
||||||
throw new TerminologyServiceException("Unable to expand imported value set "+value);
|
throw new TerminologyServiceException("Unable to expand imported value set " + value);
|
||||||
if (vs.hasVersion())
|
if (vs.hasVersion())
|
||||||
if (!existsInParams(params, "version", new UriType(vs.getUrl()+"|"+vs.getVersion())))
|
if (!existsInParams(params, "version", new UriType(vs.getUrl() + "|" + vs.getVersion())))
|
||||||
params.add(new ValueSetExpansionParameterComponent().setName("version").setValue(new UriType(vs.getUrl()+"|"+vs.getVersion())));
|
params.add(new ValueSetExpansionParameterComponent().setName("version").setValue(new UriType(vs.getUrl() + "|" + vs.getVersion())));
|
||||||
for (ValueSetExpansionParameterComponent p : vso.getValueset().getExpansion().getParameter()) {
|
for (ValueSetExpansionParameterComponent p : vso.getValueset().getExpansion().getParameter()) {
|
||||||
if (!existsInParams(params, p.getName(), p.getValue()))
|
if (!existsInParams(params, p.getName(), p.getValue()))
|
||||||
params.add(p);
|
params.add(p);
|
||||||
}
|
}
|
||||||
canBeHeirarchy = false; // if we're importing a value set, we have to be combining, so we won't try for a heirarchy
|
canBeHeirarchy = false; // if we're importing a value set, we have to be combining, so we won't try for a heirarchy
|
||||||
return vso.getValueset();
|
return vso.getValueset();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void copyImportContains(List<ValueSetExpansionContainsComponent> list, ValueSetExpansionContainsComponent parent, ExpansionProfile profile, List<ValueSet> filter) {
|
private void copyImportContains(List<ValueSetExpansionContainsComponent> list, ValueSetExpansionContainsComponent parent, ExpansionProfile profile, List<ValueSet> filter) {
|
||||||
for (ValueSetExpansionContainsComponent c : list) {
|
for (ValueSetExpansionContainsComponent c : list) {
|
||||||
ValueSetExpansionContainsComponent np = addCode(c.getSystem(), c.getCode(), c.getDisplay(), parent, null, profile, c.getAbstract(), c.getInactive(), filter);
|
ValueSetExpansionContainsComponent np = addCode(c.getSystem(), c.getCode(), c.getDisplay(), parent, null, profile, c.getAbstract(), c.getInactive(), filter);
|
||||||
copyImportContains(c.getContains(), np, profile, filter);
|
copyImportContains(c.getContains(), np, profile, filter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void includeCodes(ConceptSetComponent inc, List<ValueSetExpansionParameterComponent> params, ExpansionProfile profile) throws ETooCostly, FileNotFoundException, IOException, FHIRException {
|
private void includeCodes(ConceptSetComponent inc, List<ValueSetExpansionParameterComponent> params, ExpansionProfile profile) throws ETooCostly, FileNotFoundException, IOException, FHIRException {
|
||||||
List<ValueSet> imports = new ArrayList<ValueSet>();
|
List<ValueSet> imports = new ArrayList<ValueSet>();
|
||||||
@ -367,9 +369,9 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
|
|||||||
if (!inc.hasSystem()) {
|
if (!inc.hasSystem()) {
|
||||||
if (imports.isEmpty()) // though this is not supposed to be the case
|
if (imports.isEmpty()) // though this is not supposed to be the case
|
||||||
return;
|
return;
|
||||||
ValueSet base = imports.get(0);
|
ValueSet base = imports.get(0);
|
||||||
imports.remove(0);
|
imports.remove(0);
|
||||||
copyImportContains(base.getExpansion().getContains(), null, profile, imports);
|
copyImportContains(base.getExpansion().getContains(), null, profile, imports);
|
||||||
} else {
|
} else {
|
||||||
CodeSystem cs = context.fetchCodeSystem(inc.getSystem());
|
CodeSystem cs = context.fetchCodeSystem(inc.getSystem());
|
||||||
if ((cs == null || cs.getContent() != CodeSystemContentMode.COMPLETE) && context.supportsSystem(inc.getSystem())) {
|
if ((cs == null || cs.getContent() != CodeSystemContentMode.COMPLETE) && context.supportsSystem(inc.getSystem())) {
|
||||||
@ -379,15 +381,15 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
|
|||||||
|
|
||||||
if (cs == null) {
|
if (cs == null) {
|
||||||
if (context.isNoTerminologyServer())
|
if (context.isNoTerminologyServer())
|
||||||
throw new NoTerminologyServiceException("unable to find code system "+inc.getSystem().toString());
|
throw new NoTerminologyServiceException("unable to find code system " + inc.getSystem().toString());
|
||||||
else
|
else
|
||||||
throw new TerminologyServiceException("unable to find code system "+inc.getSystem().toString());
|
throw new TerminologyServiceException("unable to find code system " + inc.getSystem().toString());
|
||||||
}
|
}
|
||||||
if (cs.getContent() != CodeSystemContentMode.COMPLETE)
|
if (cs.getContent() != CodeSystemContentMode.COMPLETE)
|
||||||
throw new TerminologyServiceException("Code system "+inc.getSystem().toString()+" is incomplete");
|
throw new TerminologyServiceException("Code system " + inc.getSystem().toString() + " is incomplete");
|
||||||
if (cs.hasVersion())
|
if (cs.hasVersion())
|
||||||
if (!existsInParams(params, "version", new UriType(cs.getUrl()+"|"+cs.getVersion())))
|
if (!existsInParams(params, "version", new UriType(cs.getUrl() + "|" + cs.getVersion())))
|
||||||
params.add(new ValueSetExpansionParameterComponent().setName("version").setValue(new UriType(cs.getUrl()+"|"+cs.getVersion())));
|
params.add(new ValueSetExpansionParameterComponent().setName("version").setValue(new UriType(cs.getUrl() + "|" + cs.getVersion())));
|
||||||
|
|
||||||
if (inc.getConcept().size() == 0 && inc.getFilter().size() == 0) {
|
if (inc.getConcept().size() == 0 && inc.getFilter().size() == 0) {
|
||||||
// special case - add all the code system
|
// special case - add all the code system
|
||||||
@ -399,7 +401,8 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
|
|||||||
if (!inc.getConcept().isEmpty()) {
|
if (!inc.getConcept().isEmpty()) {
|
||||||
canBeHeirarchy = false;
|
canBeHeirarchy = false;
|
||||||
for (ConceptReferenceComponent c : inc.getConcept()) {
|
for (ConceptReferenceComponent c : inc.getConcept()) {
|
||||||
addCode(inc.getSystem(), c.getCode(), Utilities.noString(c.getDisplay()) ? getCodeDisplay(cs, c.getCode()) : c.getDisplay(), null, convertDesignations(c.getDesignation()), profile, false, CodeSystemUtilities.isInactive(cs, c.getCode()), imports);
|
addCode(inc.getSystem(), c.getCode(), Utilities.noString(c.getDisplay()) ? getCodeDisplay(cs, c.getCode()) : c.getDisplay(), null, convertDesignations(c.getDesignation()), profile, false,
|
||||||
|
CodeSystemUtilities.isInactive(cs, c.getCode()), imports);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (inc.getFilter().size() > 1) {
|
if (inc.getFilter().size() > 1) {
|
||||||
@ -412,13 +415,13 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
|
|||||||
// special: all codes in the target code system under the value
|
// special: all codes in the target code system under the value
|
||||||
ConceptDefinitionComponent def = getConceptForCode(cs.getConcept(), fc.getValue());
|
ConceptDefinitionComponent def = getConceptForCode(cs.getConcept(), fc.getValue());
|
||||||
if (def == null)
|
if (def == null)
|
||||||
throw new TerminologyServiceException("Code '"+fc.getValue()+"' not found in system '"+inc.getSystem()+"'");
|
throw new TerminologyServiceException("Code '" + fc.getValue() + "' not found in system '" + inc.getSystem() + "'");
|
||||||
addCodeAndDescendents(cs, inc.getSystem(), def, null, profile, imports);
|
addCodeAndDescendents(cs, inc.getSystem(), def, null, profile, imports);
|
||||||
} else if ("concept".equals(fc.getProperty()) && fc.getOp() == FilterOperator.DESCENDENTOF) {
|
} else if ("concept".equals(fc.getProperty()) && fc.getOp() == FilterOperator.DESCENDENTOF) {
|
||||||
// special: all codes in the target code system under the value
|
// special: all codes in the target code system under the value
|
||||||
ConceptDefinitionComponent def = getConceptForCode(cs.getConcept(), fc.getValue());
|
ConceptDefinitionComponent def = getConceptForCode(cs.getConcept(), fc.getValue());
|
||||||
if (def == null)
|
if (def == null)
|
||||||
throw new TerminologyServiceException("Code '"+fc.getValue()+"' not found in system '"+inc.getSystem()+"'");
|
throw new TerminologyServiceException("Code '" + fc.getValue() + "' not found in system '" + inc.getSystem() + "'");
|
||||||
for (ConceptDefinitionComponent c : def.getConcept())
|
for (ConceptDefinitionComponent c : def.getConcept())
|
||||||
addCodeAndDescendents(cs, inc.getSystem(), c, null, profile, imports);
|
addCodeAndDescendents(cs, inc.getSystem(), c, null, profile, imports);
|
||||||
} else if ("display".equals(fc.getProperty()) && fc.getOp() == FilterOperator.EQUAL) {
|
} else if ("display".equals(fc.getProperty()) && fc.getOp() == FilterOperator.EQUAL) {
|
||||||
@ -428,7 +431,8 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
|
|||||||
if (def != null) {
|
if (def != null) {
|
||||||
if (isNotBlank(def.getDisplay()) && isNotBlank(fc.getValue())) {
|
if (isNotBlank(def.getDisplay()) && isNotBlank(fc.getValue())) {
|
||||||
if (def.getDisplay().contains(fc.getValue())) {
|
if (def.getDisplay().contains(fc.getValue())) {
|
||||||
addCode(inc.getSystem(), def.getCode(), def.getDisplay(), null, def.getDesignation(), profile, CodeSystemUtilities.isNotSelectable(cs, def), CodeSystemUtilities.isInactive(cs, def), imports);
|
addCode(inc.getSystem(), def.getCode(), def.getDisplay(), null, def.getDesignation(), profile, CodeSystemUtilities.isNotSelectable(cs, def), CodeSystemUtilities.isInactive(cs, def),
|
||||||
|
imports);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -449,12 +453,12 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String key(String uri, String code) {
|
private String key(String uri, String code) {
|
||||||
return "{" + uri + "}" + code;
|
return "{" + uri + "}" + code;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String key(ValueSetExpansionContainsComponent c) {
|
private String key(ValueSetExpansionContainsComponent c) {
|
||||||
return key(c.getSystem(), c.getCode());
|
return key(c.getSystem(), c.getCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -145,6 +145,12 @@
|
|||||||
<![CDATA[<code>IBundleProvider</code> called <code>getUuid()</code>]]>. This
|
<![CDATA[<code>IBundleProvider</code> called <code>getUuid()</code>]]>. This
|
||||||
method may return <![CDATA[<code>null</code>]]> in any current cases.
|
method may return <![CDATA[<code>null</code>]]> in any current cases.
|
||||||
</action>
|
</action>
|
||||||
|
<action type="fix">
|
||||||
|
Expanding a ValueSet in JPA server did not correctly apply
|
||||||
|
<![CDATA[<code>?filter=</code>]]> parameter when the ValueSet
|
||||||
|
being expanded had codes included explicitly (i.e. not by
|
||||||
|
is-a relationship). Thanks to David Hay for reporting!
|
||||||
|
</action>
|
||||||
</release>
|
</release>
|
||||||
<release version="2.2" date="2016-12-20">
|
<release version="2.2" date="2016-12-20">
|
||||||
<action type="add">
|
<action type="add">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user