Tests and fixes to support versioned CodeSystem lookup and subsume operations

This commit is contained in:
ianmarshall 2020-08-26 16:23:17 -04:00
parent 5a0bce9155
commit 92313cd770
13 changed files with 1205 additions and 119 deletions

View File

@ -112,16 +112,17 @@ public class FhirResourceDaoCodeSystemDstu3 extends BaseHapiFhirResourceDao<Code
String code;
String system;
String codeSystemVersion = null;
if (haveCoding) {
code = theCoding.getCode();
system = theCoding.getSystem();
codeSystemVersion = theCoding.getVersion();
} else {
code = theCode.getValue();
system = theSystem.getValue();
}
String codeSystemVersion = null;
if (theVersion != null) {
codeSystemVersion = theVersion.getValue();
if (theVersion != null) {
codeSystemVersion = theVersion.getValue();
}
}
ourLog.debug("Looking up {} / {}, version {}", system, code, codeSystemVersion);
@ -140,7 +141,9 @@ public class FhirResourceDaoCodeSystemDstu3 extends BaseHapiFhirResourceDao<Code
@Override
public SubsumesResult subsumes(IPrimitiveType<String> theCodeA, IPrimitiveType<String> theCodeB, IPrimitiveType<String> theSystem, Coding theCodingA, Coding theCodingB, IPrimitiveType<String> theVersion, RequestDetails theRequestDetails) {
return myTerminologySvc.subsumes(theCodeA, theCodeB, theSystem, theCodingA, theCodingB, theVersion);
String codingBVersion = theCodingB != null ? theCodingB.getVersion() : null;
String codingAVersion = theCodingA != null ? theCodingA.getVersion() : null;
return myTerminologySvc.subsumes(theCodeA, theCodeB, theSystem, theCodingA, theCodingB, theVersion, codingAVersion, codingBVersion);
}
@Override

View File

@ -107,16 +107,17 @@ public class FhirResourceDaoCodeSystemR4 extends BaseHapiFhirResourceDao<CodeSys
String code;
String system;
String codeSystemVersion = null;
if (haveCoding) {
code = theCoding.getCode();
system = theCoding.getSystem();
codeSystemVersion = theCoding.getVersion();
} else {
code = theCode.getValue();
system = theSystem.getValue();
}
String codeSystemVersion = null;
if (theVersion != null) {
codeSystemVersion = theVersion.getValue();
if (theVersion != null) {
codeSystemVersion = theVersion.getValue();
}
}
ourLog.debug("Looking up {} / {}, version {}", system, code, codeSystemVersion);
@ -138,7 +139,9 @@ public class FhirResourceDaoCodeSystemR4 extends BaseHapiFhirResourceDao<CodeSys
@Override
public SubsumesResult subsumes(IPrimitiveType<String> theCodeA, IPrimitiveType<String> theCodeB, IPrimitiveType<String> theSystem, Coding theCodingA, Coding theCodingB, IPrimitiveType<String> theVersion, RequestDetails theRequestDetails) {
return myTerminologySvc.subsumes(theCodeA, theCodeB, theSystem, theCodingA, theCodingB, theVersion);
String codingBVersion = theCodingB != null ? theCodingB.getVersion() : null;
String codingAVersion = theCodingA != null ? theCodingA.getVersion() : null;
return myTerminologySvc.subsumes(theCodeA, theCodeB, theSystem, theCodingA, theCodingB, theVersion, codingAVersion, codingBVersion);
}
@Override

View File

@ -109,16 +109,17 @@ public class FhirResourceDaoCodeSystemR5 extends BaseHapiFhirResourceDao<CodeSys
String code;
String system;
String codeSystemVersion = null;
if (haveCoding) {
code = theCoding.getCode();
system = theCoding.getSystem();
codeSystemVersion = theCoding.getVersion();
} else {
code = theCode.getValue();
system = theSystem.getValue();
}
String codeSystemVersion = null;
if (theVersion != null) {
codeSystemVersion = theVersion.getValue();
if (theVersion != null) {
codeSystemVersion = theVersion.getValue();
}
}
ourLog.debug("Looking up {} / {}, version {}", system, code, codeSystemVersion);
@ -140,7 +141,9 @@ public class FhirResourceDaoCodeSystemR5 extends BaseHapiFhirResourceDao<CodeSys
@Override
public SubsumesResult subsumes(IPrimitiveType<String> theCodeA, IPrimitiveType<String> theCodeB, IPrimitiveType<String> theSystem, Coding theCodingA, Coding theCodingB, IPrimitiveType<String> theVersion, RequestDetails theRequestDetails) {
return myTerminologySvc.subsumes(theCodeA, theCodeB, theSystem, theCodingA, theCodingB, theVersion);
String codingBVersion = theCodingB != null ? theCodingB.getVersion() : null;
String codingAVersion = theCodingA != null ? theCodingA.getVersion() : null;
return myTerminologySvc.subsumes(theCodeA, theCodeB, theSystem, theCodingA, theCodingB, theVersion, codingAVersion, codingBVersion);
}
@Override

View File

@ -1380,7 +1380,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
return txTemplate.execute(t -> {
TermCodeSystemVersion csv = getCurrentCodeSystemVersionForVersion(theCodeSystem, theVersion);
if (csv == null) {
return null;
return Optional.empty();
}
return myConceptDao.findByCodeSystemAndCode(csv, theCode);
});
@ -1392,9 +1392,9 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
if (theVersion != null) {
key.append("_").append(theVersion);
}
TermCodeSystemVersion retVal = myCodeSystemCurrentVersionCache.get(key.toString(), uri -> myTxTemplate.execute(tx -> {
TermCodeSystemVersion retVal = myCodeSystemCurrentVersionCache.get(key.toString(), t -> myTxTemplate.execute(tx -> {
TermCodeSystemVersion csv = null;
TermCodeSystem cs = myCodeSystemDao.findByCodeSystemUri(uri);
TermCodeSystem cs = myCodeSystemDao.findByCodeSystemUri(theUri);
if (cs != null) {
if (theVersion != null) {
csv = myCodeSystemVersionDao.findByCodeSystemPidAndVersion(cs.getPid(), theVersion);
@ -1819,28 +1819,32 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
}
@Override
public IFhirResourceDaoCodeSystem.SubsumesResult subsumes(IPrimitiveType<String> theCodeA, IPrimitiveType<String> theCodeB, IPrimitiveType<String> theSystem, IBaseCoding theCodingA, IBaseCoding theCodingB) {
return subsumes(theCodeA, theCodeB, theSystem, theCodingA, theCodingB, null);
public IFhirResourceDaoCodeSystem.SubsumesResult subsumes(IPrimitiveType<String> theCodeA, IPrimitiveType<String> theCodeB,
IPrimitiveType<String> theSystem, IBaseCoding theCodingA, IBaseCoding theCodingB) {
return subsumes(theCodeA, theCodeB, theSystem, theCodingA, theCodingB, null, null, null);
}
@Override
@Transactional
public IFhirResourceDaoCodeSystem.SubsumesResult subsumes(IPrimitiveType<String> theCodeA, IPrimitiveType<String> theCodeB, IPrimitiveType<String> theSystem, IBaseCoding theCodingA, IBaseCoding theCodingB, IPrimitiveType<String> theSystemVersion) {
VersionIndependentConcept conceptA = toConcept(theCodeA, theSystem, theCodingA);
VersionIndependentConcept conceptB = toConcept(theCodeB, theSystem, theCodingB);
String systemVersion = null;
if (theSystemVersion != null) {
systemVersion = theSystemVersion.getValue();
}
public IFhirResourceDaoCodeSystem.SubsumesResult subsumes(IPrimitiveType<String> theCodeA, IPrimitiveType<String> theCodeB,
IPrimitiveType<String> theSystem, IBaseCoding theCodingA, IBaseCoding theCodingB,
IPrimitiveType<String> theSystemVersion, String theCodingAVersion,
String theCodingBVersion) {
VersionIndependentConceptWithSystemVersion conceptA = toConcept(theCodeA, theSystem, theCodingA, theSystemVersion, theCodingAVersion);
VersionIndependentConceptWithSystemVersion conceptB = toConcept(theCodeB, theSystem, theCodingB, theSystemVersion, theCodingBVersion);
if (!StringUtils.equals(conceptA.getSystem(), conceptB.getSystem())) {
throw new InvalidRequestException("Unable to test subsumption across different code systems");
}
TermConcept codeA = findCode(conceptA.getSystem(), conceptA.getCode(), systemVersion)
if (!StringUtils.equals(conceptA.getCodeSystemVersion(), conceptB.getCodeSystemVersion())) {
throw new InvalidRequestException("Unable to test subsumption across different code system versions");
}
TermConcept codeA = findCode(conceptA.getSystem(), conceptA.getCode(), conceptA.getCodeSystemVersion())
.orElseThrow(() -> new InvalidRequestException("Unknown code: " + conceptA));
TermConcept codeB = findCode(conceptB.getSystem(), conceptB.getCode(), systemVersion)
TermConcept codeB = findCode(conceptB.getSystem(), conceptB.getCode(), conceptB.getCodeSystemVersion())
.orElseThrow(() -> new InvalidRequestException("Unknown code: " + conceptB));
FullTextEntityManager em = org.hibernate.search.jpa.Search.getFullTextEntityManager(myEntityManager);
@ -2411,14 +2415,33 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
}
@NotNull
private static VersionIndependentConcept toConcept(IPrimitiveType<String> theCodeType, IPrimitiveType<String> theSystemType, IBaseCoding theCodingType) {
private VersionIndependentConceptWithSystemVersion toConcept(IPrimitiveType<String> theCodeType, IPrimitiveType<String> theSystemType,
IBaseCoding theCodingType, IPrimitiveType<String> theSystemVersionType,
String theCodingVersionType) {
String code = theCodeType != null ? theCodeType.getValueAsString() : null;
String system = theSystemType != null ? theSystemType.getValueAsString() : null;
String systemVersion = theSystemVersionType != null ? theSystemVersionType.getValueAsString() : null;
if (theCodingType != null) {
code = theCodingType.getCode();
system = theCodingType.getSystem();
systemVersion = theCodingVersionType;
}
return new VersionIndependentConcept(system, code);
return new VersionIndependentConceptWithSystemVersion(system, code, systemVersion);
}
private static class VersionIndependentConceptWithSystemVersion extends VersionIndependentConcept {
String myCodeSystemVersion;
public VersionIndependentConceptWithSystemVersion(String theSystem, String theCode, String theSystemVersion) {
super(theSystem, theCode);
myCodeSystemVersion = theSystemVersion;
}
public String getCodeSystemVersion() {
return myCodeSystemVersion;
}
}
/**

View File

@ -234,9 +234,19 @@ public class TermCodeSystemStorageSvcImpl implements ITermCodeSystemStorageSvc {
@Override
@Transactional(propagation = Propagation.NEVER)
public void deleteCodeSystemVersion(TermCodeSystemVersion theCodeSystemVersion) {
ourLog.info(" * Deleting code system version {}", theCodeSystemVersion.getPid());
TermCodeSystem termCodeSystem = theCodeSystemVersion.getCodeSystem();
ourLog.info(" * Deleting code system version {}", theCodeSystemVersion.getCodeSystemVersionId());
deleteCodeSystemVersion(theCodeSystemVersion.getPid());
TransactionTemplate txTemplate = new TransactionTemplate(myTransactionManager);
txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
txTemplate.executeWithoutResult(t -> {
if (myCodeSystemVersionDao.findByCodeSystemPid(termCodeSystem.getPid()).size() == 0) {
ourLog.info(" * Deleting code system {}", termCodeSystem.getPid());
deleteCodeSystem(termCodeSystem);
}
});
}
/**

View File

@ -105,7 +105,7 @@ public interface ITermReadSvc extends IValidationSupport {
IFhirResourceDaoCodeSystem.SubsumesResult subsumes(IPrimitiveType<String> theCodeA, IPrimitiveType<String> theCodeB, IPrimitiveType<String> theSystem, IBaseCoding theCodingA, IBaseCoding theCodingB);
IFhirResourceDaoCodeSystem.SubsumesResult subsumes(IPrimitiveType<String> theCodeA, IPrimitiveType<String> theCodeB, IPrimitiveType<String> theSystem, IBaseCoding theCodingA, IBaseCoding theCodingB, IPrimitiveType<String> theSystemVersion);
IFhirResourceDaoCodeSystem.SubsumesResult subsumes(IPrimitiveType<String> theCodeA, IPrimitiveType<String> theCodeB, IPrimitiveType<String> theSystem, IBaseCoding theCodingA, IBaseCoding theCodingB, IPrimitiveType<String> theSystemVersion, String theCodingAVersion, String theCodingBVersion);
void preExpandDeferredValueSetsToTerminologyTables();

View File

@ -1,5 +1,6 @@
package ca.uhn.fhir.jpa.dao.r4;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.term.TermReindexingSvcImpl;
import org.apache.commons.io.IOUtils;
import org.hl7.fhir.instance.model.api.IIdType;
@ -8,11 +9,14 @@ import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Test;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class FhirResourceDaoR4CodeSystemTest extends BaseJpaR4Test {
@ -35,15 +39,7 @@ public class FhirResourceDaoR4CodeSystemTest extends BaseJpaR4Test {
@Test
public void testDeleteLargeCompleteCodeSystem() {
CodeSystem cs = new CodeSystem();
cs.setContent(CodeSystem.CodeSystemContentMode.COMPLETE);
cs.setUrl("http://foo");
for (int i = 0; i < 222; i++) {
cs.addConcept().setCode("CODE" + i);
}
IIdType id = myCodeSystemDao.create(cs).getId().toUnqualifiedVersionless();
myTerminologyDeferredStorageSvc.saveDeferred();
myTerminologyDeferredStorageSvc.saveDeferred();
IIdType id = createLargeCodeSystem(null);
runInTransaction(() -> {
assertEquals(1, myTermCodeSystemDao.count());
@ -72,6 +68,122 @@ public class FhirResourceDaoR4CodeSystemTest extends BaseJpaR4Test {
}
@Test
public void testDeleteCodeSystemVersion() {
// Create code system with two versions.
IIdType id_first = createLargeCodeSystem("1");
runInTransaction(() -> {
assertEquals(1, myTermCodeSystemDao.count());
assertNotNull(myTermCodeSystemDao.findByCodeSystemUri("http://foo"));
assertEquals(1, myTermCodeSystemVersionDao.count());
List<ResourceTable> resourceList = myResourceTableDao.findAll();
assertEquals(222, myTermConceptDao.count());
assertEquals(1, resourceList.size());
assertNull(resourceList.get(0).getDeleted());
});
IIdType id_second = createLargeCodeSystem("2");
runInTransaction(() -> {
assertEquals(1, myTermCodeSystemDao.count());
assertNotNull(myTermCodeSystemDao.findByCodeSystemUri("http://foo"));
assertEquals(2, myTermCodeSystemVersionDao.count());
assertEquals(444, myTermConceptDao.count());
List<ResourceTable> resourceList = myResourceTableDao.findAll();
assertEquals(2, resourceList.size());
long active = resourceList
.stream()
.filter(t -> t.getDeleted() == null).count();
assertEquals(2, active);
});
// Attempt to delete first version
myCodeSystemDao.delete(id_first, mySrd);
// Only the resource will be deleted initially
runInTransaction(() -> {
assertEquals(1, myTermCodeSystemDao.count());
assertNotNull(myTermCodeSystemDao.findByCodeSystemUri("http://foo"));
assertEquals(2, myTermCodeSystemVersionDao.count());
assertEquals(444, myTermConceptDao.count());
List<ResourceTable> resourceList = myResourceTableDao.findAll();
assertEquals(2, resourceList.size());
long active = resourceList
.stream()
.filter(t -> t.getDeleted() == null).count();
assertEquals(1, active);
});
// Now the background scheduler will do its thing
myTerminologyDeferredStorageSvc.saveDeferred();
// Entities for first resource should be gone now.
runInTransaction(() -> {
assertEquals(1, myTermCodeSystemDao.count());
assertNotNull(myTermCodeSystemDao.findByCodeSystemUri("http://foo"));
assertEquals(1, myTermCodeSystemVersionDao.count());
assertEquals(222, myTermConceptDao.count());
List<ResourceTable> resourceList = myResourceTableDao.findAll();
assertEquals(2, resourceList.size());
long active = resourceList
.stream()
.filter(t -> t.getDeleted() == null).count();
assertEquals(1, active);
});
// Attempt to delete second version
myCodeSystemDao.delete(id_second, mySrd);
// Only the resource will be deleted initially
runInTransaction(() -> {
assertEquals(1, myTermCodeSystemDao.count());
assertNotNull(myTermCodeSystemDao.findByCodeSystemUri("http://foo"));
assertEquals(1, myTermCodeSystemVersionDao.count());
assertEquals(222, myTermConceptDao.count());
List<ResourceTable> resourceList = myResourceTableDao.findAll();
assertEquals(2, resourceList.size());
long active = resourceList
.stream()
.filter(t -> t.getDeleted() == null).count();
assertEquals(0, active);
});
// Now the background scheduler will do its thing
myTerminologyDeferredStorageSvc.saveDeferred();
// The remaining versions and Code System entities should be gone now.
runInTransaction(() -> {
assertEquals(0, myTermCodeSystemDao.count());
assertNull(myTermCodeSystemDao.findByCodeSystemUri("http://foo"));
assertEquals(0, myTermCodeSystemVersionDao.count());
List<ResourceTable> resourceList = myResourceTableDao.findAll();
assertEquals(2, resourceList.size());
long active = resourceList
.stream()
.filter(t -> t.getDeleted() == null).count();
assertEquals(0, active);
});
}
private IIdType createLargeCodeSystem(String theVersion) {
CodeSystem cs = new CodeSystem();
cs.setContent(CodeSystem.CodeSystemContentMode.COMPLETE);
cs.setUrl("http://foo");
if (theVersion != null) {
cs.setVersion(theVersion);
}
for (int i = 0; i < 222; i++) {
cs.addConcept().setCode("CODE" + i);
}
IIdType id = myCodeSystemDao.create(cs).getId().toUnqualifiedVersionless();
myTerminologyDeferredStorageSvc.saveDeferred();
myTerminologyDeferredStorageSvc.saveDeferred();
return id;
}
@AfterAll
public static void afterClassClearContext() {
TermReindexingSvcImpl.setForceSaveDeferredAlwaysForUnitTest(false);

View File

@ -325,6 +325,7 @@ public class ResourceProviderR4CodeSystemTest extends BaseResourceProviderR4Test
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("FOO"))
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentB"))
.execute();
fail();
} catch (InvalidRequestException e) {
assertEquals("HTTP 400 Bad Request: Unknown code: [http://parentchild|FOO]", e.getMessage());
}
@ -340,6 +341,7 @@ public class ResourceProviderR4CodeSystemTest extends BaseResourceProviderR4Test
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentB"))
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("FOO"))
.execute();
fail();
} catch (InvalidRequestException e) {
assertEquals("HTTP 400 Bad Request: Unknown code: [http://parentchild|FOO]", e.getMessage());
}
@ -355,6 +357,7 @@ public class ResourceProviderR4CodeSystemTest extends BaseResourceProviderR4Test
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD + "A").setCode("ChildAA"))
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD + "B").setCode("ParentA"))
.execute();
fail();
} catch (InvalidRequestException e) {
assertEquals("HTTP 400 Bad Request: Unable to test subsumption across different code systems", e.getMessage());
}

View File

@ -0,0 +1,769 @@
package ca.uhn.fhir.jpa.provider.r4;
import ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoR4TerminologyTest;
import ca.uhn.fhir.jpa.model.util.JpaConstants;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import org.hl7.fhir.r4.model.BooleanType;
import org.hl7.fhir.r4.model.CodeSystem;
import org.hl7.fhir.r4.model.CodeType;
import org.hl7.fhir.r4.model.Coding;
import org.hl7.fhir.r4.model.Enumerations;
import org.hl7.fhir.r4.model.Parameters;
import org.hl7.fhir.r4.model.StringType;
import org.hl7.fhir.r4.model.UriType;
import org.hl7.fhir.r4.model.ValueSet;
import org.hl7.fhir.r4.model.codesystems.ConceptSubsumptionOutcome;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
public class ResourceProviderR4CodeSystemVersionedTest extends BaseResourceProviderR4Test {
private static final String SYSTEM_PARENTCHILD = "http://parentchild";
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceProviderR4CodeSystemVersionedTest.class);
@BeforeEach
@Transactional
public void before02() throws IOException {
CodeSystem cs = loadResourceFromClasspath(CodeSystem.class, "/extensional-case-3-cs-v1.xml");
myCodeSystemDao.create(cs, mySrd);
cs = loadResourceFromClasspath(CodeSystem.class, "/extensional-case-3-cs-v2.xml");
myCodeSystemDao.create(cs, mySrd);
ValueSet upload = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml");
myValueSetDao.create(upload, mySrd).getId().toUnqualifiedVersionless();
CodeSystem parentChildCs = new CodeSystem();
parentChildCs.setUrl(SYSTEM_PARENTCHILD);
parentChildCs.setVersion("1");
parentChildCs.setStatus(Enumerations.PublicationStatus.ACTIVE);
parentChildCs.setContent(CodeSystem.CodeSystemContentMode.COMPLETE);
parentChildCs.setHierarchyMeaning(CodeSystem.CodeSystemHierarchyMeaning.ISA);
CodeSystem.ConceptDefinitionComponent parentA = parentChildCs.addConcept().setCode("ParentA").setDisplay("Parent A");
parentA.addConcept().setCode("ChildAA").setDisplay("Child AA");
parentA.addConcept().setCode("ParentC").setDisplay("Parent C");
parentChildCs.addConcept().setCode("ParentB").setDisplay("Parent B");
myCodeSystemDao.create(parentChildCs);
parentChildCs = new CodeSystem();
parentChildCs.setVersion("2");
parentChildCs.setUrl(SYSTEM_PARENTCHILD);
parentChildCs.setStatus(Enumerations.PublicationStatus.ACTIVE);
parentChildCs.setContent(CodeSystem.CodeSystemContentMode.COMPLETE);
parentChildCs.setHierarchyMeaning(CodeSystem.CodeSystemHierarchyMeaning.ISA);
parentA = parentChildCs.addConcept().setCode("ParentA").setDisplay("Parent A v2");
parentA.addConcept().setCode("ChildAA").setDisplay("Child AA v2");
parentA.addConcept().setCode("ParentB").setDisplay("Parent B v2");
parentChildCs.addConcept().setCode("ParentC").setDisplay("Parent C v2");
myCodeSystemDao.create(parentChildCs);
}
@Test
public void testLookupOnExternalCodeMultiVersion() {
ResourceProviderR4ValueSetTest.createExternalCs(myCodeSystemDao, myResourceTableDao, myTermCodeSystemStorageSvc, mySrd, "1");
ResourceProviderR4ValueSetTest.createExternalCs(myCodeSystemDao, myResourceTableDao, myTermCodeSystemStorageSvc, mySrd, "2");
// First test with no version specified (should return from last version created)
Parameters respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("ParentA"))
.andParameter("system", new UriType(FhirResourceDaoR4TerminologyTest.URL_MY_CODE_SYSTEM))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals("SYSTEM NAME", ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("2", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals("Parent A2", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
// With HTTP GET
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("ParentA"))
.andParameter("system", new UriType(FhirResourceDaoR4TerminologyTest.URL_MY_CODE_SYSTEM))
.useHttpGet()
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(("SYSTEM NAME"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals(("2"), ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals("Parent A2", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
// Test with version 1 specified.
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("ParentA"))
.andParameter("system", new UriType(FhirResourceDaoR4TerminologyTest.URL_MY_CODE_SYSTEM))
.andParameter("version", new StringType("1"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals("SYSTEM NAME", ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("1", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals("Parent A1", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
// With HTTP GET
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("ParentA"))
.andParameter("system", new UriType(FhirResourceDaoR4TerminologyTest.URL_MY_CODE_SYSTEM))
.andParameter("version", new StringType("1"))
.useHttpGet()
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(("SYSTEM NAME"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals(("1"), ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals("Parent A1", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
// Test with version 2 specified.
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("ParentA"))
.andParameter("system", new UriType(FhirResourceDaoR4TerminologyTest.URL_MY_CODE_SYSTEM))
.andParameter("version", new StringType("2"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals("SYSTEM NAME", ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("2", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals("Parent A2", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
// With HTTP GET
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("ParentA"))
.andParameter("system", new UriType(FhirResourceDaoR4TerminologyTest.URL_MY_CODE_SYSTEM))
.andParameter("version", new StringType("2"))
.useHttpGet()
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(("SYSTEM NAME"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals(("2"), ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals("Parent A2", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
}
@Test
public void testLookupOperationByCodeAndSystemBuiltInCode() {
// First test with no version specified (should return the one and only version defined).
Parameters respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("ACSN"))
.andParameter("system", new UriType("http://terminology.hl7.org/CodeSystem/v2-0203"))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals("v2.0203", ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("2.9", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals("Accession ID", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
// Repeat with version specified.
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("ACSN"))
.andParameter("system", new UriType("http://terminology.hl7.org/CodeSystem/v2-0203"))
.andParameter("version", new StringType("2.9"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals("v2.0203", ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("2.9", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals("Accession ID", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
}
@Test
public void testLookupOperationByCodeAndSystemBuiltInNonexistentVersion() {
try {
myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("ACSN"))
.andParameter("system", new UriType("http://hl7.org/fhir/v2/0203"))
.andParameter("version", new StringType("2.8"))
.execute();
fail();
} catch (ResourceNotFoundException e) {
ourLog.info("Lookup failed as expected");
}
}
@Test
public void testLookupOperationByCodeAndSystemUserDefinedCode() {
// First test with no version specified (should return from last version created)
Parameters respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("8450-9"))
.andParameter("system", new UriType("http://acme.org"))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(("ACME Codes"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("2", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals(("Systolic blood pressure--expiration v2"), ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
// Test with version 1 specified.
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("8450-9"))
.andParameter("system", new UriType("http://acme.org"))
.andParameter("version", new StringType("1"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(("ACME Codes"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("1", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals(("Systolic blood pressure--expiration"), ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
// Test with version 2 specified
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("8450-9"))
.andParameter("system", new UriType("http://acme.org"))
.andParameter("version", new StringType("2"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(("ACME Codes"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("2", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals(("Systolic blood pressure--expiration v2"), ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
}
@Test
public void testLookupOperationByCodeAndSystemUserDefinedNonExistentVersion() {
try {
myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("8450-9"))
.andParameter("system", new UriType("http://acme.org"))
.andParameter("version", new StringType("3"))
.execute();
fail();
} catch (ResourceNotFoundException e) {
ourLog.info("Lookup failed as expected");
}
}
@Test
public void testLookupOperationByCoding() {
// First test with no version specified (should return from last version created)
Parameters respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "coding", new Coding().setSystem("http://acme.org").setCode("8450-9"))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(("ACME Codes"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("2", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals(("Systolic blood pressure--expiration v2"), ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
// Test with version set to 1
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "coding", new Coding().setSystem("http://acme.org").setCode("8450-9").setVersion("1"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(("ACME Codes"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("1", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals(("Systolic blood pressure--expiration"), ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
// Test with version set to 2
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "coding", new Coding().setSystem("http://acme.org").setCode("8450-9").setVersion("2"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(("ACME Codes"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("2", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals(("Systolic blood pressure--expiration v2"), ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
}
@Test
public void testSubsumesOnCodes_Subsumes() {
// First test with no version specified (should return result for last version created).
Parameters respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codeA", new CodeType("ParentB"))
.andParameter("codeB", new CodeType("ParentA"))
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.SUBSUMES.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 1.
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codeA", new CodeType("ParentC"))
.andParameter("codeB", new CodeType("ParentA"))
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
.andParameter("version", new StringType("1"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.SUBSUMES.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 2.
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codeA", new CodeType("ParentB"))
.andParameter("codeB", new CodeType("ParentA"))
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
.andParameter("version", new StringType("2"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.SUBSUMES.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
}
@Test
public void testSubsumesOnCodes_Subsumedby() {
// First test with no version specified (should return result for last version created).
Parameters respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codeA", new CodeType("ParentA"))
.andParameter("codeB", new CodeType("ParentB"))
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.SUBSUMEDBY.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 1.
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codeA", new CodeType("ParentA"))
.andParameter("codeB", new CodeType("ParentC"))
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
.andParameter("version", new StringType("1"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.SUBSUMEDBY.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 2.
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codeA", new CodeType("ParentA"))
.andParameter("codeB", new CodeType("ParentB"))
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
.andParameter("version", new StringType("2"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.SUBSUMEDBY.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
}
@Test
public void testSubsumesOnCodes_Disjoint() {
// First test with no version specified (should return result for last version created).
Parameters respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codeA", new CodeType("ParentA"))
.andParameter("codeB", new CodeType("ParentC"))
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.NOTSUBSUMED.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 1
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codeA", new CodeType("ParentA"))
.andParameter("codeB", new CodeType("ParentB"))
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
.andParameter("version", new StringType("1"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.NOTSUBSUMED.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 2
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codeA", new CodeType("ParentA"))
.andParameter("codeB", new CodeType("ParentC"))
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
.andParameter("version", new StringType("2"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.NOTSUBSUMED.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
}
@Test
public void testSubsumesOnCodings_MismatchedCsVersions() {
try {
myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ChildAA").setVersion("1"))
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA").setVersion("2"))
.execute();
fail();
} catch (InvalidRequestException e) {
assertEquals("HTTP 400 Bad Request: Unable to test subsumption across different code system versions", e.getMessage());
}
}
@Test
public void testSubsumesOnCodings_Subsumes() {
// First test with no version specified (should return result for last version created).
Parameters respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentB"))
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA"))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.SUBSUMES.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 1.
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentC").setVersion("1"))
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA").setVersion("1"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.SUBSUMES.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 2.
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentB").setVersion("2"))
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA").setVersion("2"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.SUBSUMES.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
}
@Test
public void testSubsumesOnCodings_Subsumedby() {
// First test with no version specified (should return result for last version created).
Parameters respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA"))
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentB"))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.SUBSUMEDBY.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 1.
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA").setVersion("1"))
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentC").setVersion("1"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.SUBSUMEDBY.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 2.
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA").setVersion("2"))
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentB").setVersion("2"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.SUBSUMEDBY.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
}
@Test
public void testSubsumesOnCodings_Disjoint() {
// First test with no version specified (should return result for last version created).
Parameters respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA"))
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentC"))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.NOTSUBSUMED.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 1
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA").setVersion("1"))
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentB").setVersion("1"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.NOTSUBSUMED.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 2
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA").setVersion("2"))
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentC").setVersion("2"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.NOTSUBSUMED.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
}
}

View File

@ -1135,4 +1135,38 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
return codeSystem;
}
public static CodeSystem createExternalCs(IFhirResourceDao<CodeSystem> theCodeSystemDao, IResourceTableDao theResourceTableDao, ITermCodeSystemStorageSvc theTermCodeSystemStorageSvc, ServletRequestDetails theRequestDetails, String theCodeSystemVersion) {
CodeSystem codeSystem = new CodeSystem();
codeSystem.setUrl(URL_MY_CODE_SYSTEM);
codeSystem.setContent(CodeSystemContentMode.NOTPRESENT);
codeSystem.setVersion(theCodeSystemVersion);
IIdType id = theCodeSystemDao.create(codeSystem, theRequestDetails).getId().toUnqualified();
ResourceTable table = theResourceTableDao.findById(id.getIdPartAsLong()).orElseThrow(IllegalStateException::new);
TermCodeSystemVersion cs = new TermCodeSystemVersion();
cs.setResource(table);
TermConcept parentA = new TermConcept(cs, "ParentA").setDisplay("Parent A" + theCodeSystemVersion);
cs.getConcepts().add(parentA);
TermConcept childAA = new TermConcept(cs, "childAA").setDisplay("Child AA" + theCodeSystemVersion);
parentA.addChild(childAA, RelationshipTypeEnum.ISA);
TermConcept childAAA = new TermConcept(cs, "childAAA").setDisplay("Child AAA" + theCodeSystemVersion);
childAA.addChild(childAAA, RelationshipTypeEnum.ISA);
TermConcept childAAB = new TermConcept(cs, "childAAB").setDisplay("Child AAB" + theCodeSystemVersion);
childAA.addChild(childAAB, RelationshipTypeEnum.ISA);
TermConcept childAB = new TermConcept(cs, "childAB").setDisplay("Child AB" + theCodeSystemVersion);
parentA.addChild(childAB, RelationshipTypeEnum.ISA);
TermConcept parentB = new TermConcept(cs, "ParentB").setDisplay("Parent B" + theCodeSystemVersion);
cs.getConcepts().add(parentB);
theTermCodeSystemStorageSvc.storeNewCodeSystemVersion(new ResourcePersistentId(table.getId()), URL_MY_CODE_SYSTEM, "SYSTEM NAME", theCodeSystemVersion, cs, table);
return codeSystem;
}
}

View File

@ -12,8 +12,6 @@ import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import static org.junit.jupiter.api.Assertions.fail;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class TermCodeSystemStorageSvcTest extends BaseJpaR4Test {
@ -80,67 +78,6 @@ public class TermCodeSystemStorageSvcTest extends BaseJpaR4Test {
}
@Test
public void testDeleteCodeSystem() {
CodeSystem codeSystemToDelete = createSmallCodeSystem();
// Create CodeSystem resource and entity
ResourceTable codeSystemResourceEntity = (ResourceTable)myCodeSystemDao.create(codeSystemToDelete, mySrd).getEntity();
validateCodeSystemUpdates(10);
runInTransaction(() -> {
assertEquals(1, myTermCodeSystemDao.count());
assertEquals(1, myTermCodeSystemVersionDao.count());
});
// Attempt to delete
myCodeSystemDao.delete(codeSystemResourceEntity.getIdDt(), mySrd);
validateCodeSystemUpdates(0);
runInTransaction(() -> {
assertEquals(0, myTermCodeSystemDao.count());
assertEquals(0, myTermCodeSystemVersionDao.count());
});
}
@Test
public void testDeleteCodeSystemVersion() {
CodeSystem firstCodeSystemVersion = createSmallCodeSystem();
firstCodeSystemVersion.setVersion("1");
// Create first CodeSystem resource and entity
ResourceTable codeSystemResourceEntity = (ResourceTable)myCodeSystemDao.create(firstCodeSystemVersion, mySrd).getEntity();
validateCodeSystemUpdates(10);
runInTransaction(() -> {
assertEquals(1, myTermCodeSystemDao.count());
assertEquals(1, myTermCodeSystemVersionDao.count());
});
CodeSystem secondCodeSystemVersion = createSmallCodeSystem();
secondCodeSystemVersion.setVersion("2");
// Create CodeSystem resource and entity
myCodeSystemDao.create(secondCodeSystemVersion, mySrd);
validateCodeSystemUpdates(20);
runInTransaction(() -> {
assertEquals(1, myTermCodeSystemDao.count());
assertEquals(2, myTermCodeSystemVersionDao.count());
});
// Attempt to delete first version
myCodeSystemDao.delete(codeSystemResourceEntity.getIdDt(), mySrd);
validateCodeSystemUpdates(10);
runInTransaction(() -> {
assertEquals(1, myTermCodeSystemDao.count());
assertEquals(1, myTermCodeSystemVersionDao.count());
});
}
private CodeSystem createCodeSystemWithMoreThan100Concepts() {
CodeSystem codeSystem = new CodeSystem();
codeSystem.setUrl(URL_MY_CODE_SYSTEM);
@ -154,19 +91,6 @@ public class TermCodeSystemStorageSvcTest extends BaseJpaR4Test {
}
private CodeSystem createSmallCodeSystem() {
CodeSystem codeSystem = new CodeSystem();
codeSystem.setUrl(URL_MY_CODE_SYSTEM);
for (int i = 0; i < 10; i++) {
codeSystem.addConcept(new CodeSystem.ConceptDefinitionComponent(new CodeType("codeA " + i)));
}
codeSystem.setContent(CodeSystem.CodeSystemContentMode.COMPLETE);
return codeSystem;
}
private void testCreatingAndUpdatingCodeSystemEntity(CodeSystem theUpload, CodeSystem theDuplicate, int expectedCnt, String theDuplicateErrorBaseMsg) {
// Create CodeSystem resource

View File

@ -0,0 +1,101 @@
<CodeSystem xmlns="http://hl7.org/fhir">
<url value="http://acme.org" />
<version value="1"/>
<name value="ACME Codes" />
<concept>
<code value="8450-9" />
<display value="Systolic blood pressure--expiration" />
</concept>
<concept>
<code value="11378-7" />
<display value="Systolic blood pressure at First encounter" />
</concept>
<concept>
<code value="8493-9" />
<display value="Systolic blood pressure 10 hour minimum" />
</concept>
<concept>
<code value="8494-7" />
<display value="Systolic blood pressure 12 hour minimum" />
</concept>
<concept>
<code value="8495-4" />
<display value="Systolic blood pressure 24 hour minimum" />
</concept>
<concept>
<code value="8451-7" />
<display value="Systolic blood pressure--inspiration" />
</concept>
<concept>
<code value="8452-5" />
<display value="Systolic blood pressure.inspiration - expiration" />
</concept>
<concept>
<code value="8459-0" />
<display value="Systolic blood pressure--sitting" />
</concept>
<concept>
<code value="8460-8" />
<display value="Systolic blood pressure--standing" />
</concept>
<concept>
<code value="8461-6" />
<display value="Systolic blood pressure--supine" />
</concept>
<concept>
<code value="8479-8" />
<display value="Systolic blood pressure by palpation" />
</concept>
<concept>
<code value="8480-6" />
<display value="Systolic blood pressure" />
</concept>
<concept>
<code value="8481-4" />
<display value="Systolic blood pressure 1 hour maximum" />
</concept>
<concept>
<code value="8482-2" />
<display value="Systolic blood pressure 8 hour maximum" />
</concept>
<concept>
<code value="8483-0" />
<display value="Systolic blood pressure 10 hour maximum" />
</concept>
<concept>
<code value="8484-8" />
<display value="Systolic blood pressure 12 hour maximum" />
</concept>
<concept>
<code value="8485-5" />
<display value="Systolic blood pressure 24 hour maximum" />
</concept>
<concept>
<code value="8486-3" />
<display value="Systolic blood pressure 1 hour mean" />
</concept>
<concept>
<code value="8487-1" />
<display value="Systolic blood pressure 8 hour mean" />
</concept>
<concept>
<code value="8488-9" />
<display value="Systolic blood pressure 10 hour mean" />
</concept>
<concept>
<code value="8489-7" />
<display value="Systolic blood pressure 12 hour mean" />
</concept>
<concept>
<code value="8490-5" />
<display value="Systolic blood pressure 24 hour mean" />
</concept>
<concept>
<code value="8491-3" />
<display value="Systolic blood pressure 1 hour minimum" />
</concept>
<concept>
<code value="8492-1" />
<display value="Systolic blood pressure 8 hour minimum" />
</concept>
</CodeSystem>

View File

@ -0,0 +1,101 @@
<CodeSystem xmlns="http://hl7.org/fhir">
<url value="http://acme.org" />
<version value="2"/>
<name value="ACME Codes" />
<concept>
<code value="8450-9" />
<display value="Systolic blood pressure--expiration v2" />
</concept>
<concept>
<code value="11378-7" />
<display value="Systolic blood pressure at First encounter v2" />
</concept>
<concept>
<code value="8493-9" />
<display value="Systolic blood pressure 10 hour minimum v2" />
</concept>
<concept>
<code value="8494-7" />
<display value="Systolic blood pressure 12 hour minimum v2" />
</concept>
<concept>
<code value="8495-4" />
<display value="Systolic blood pressure 24 hour minimum v2" />
</concept>
<concept>
<code value="8451-7" />
<display value="Systolic blood pressure--inspiration v2" />
</concept>
<concept>
<code value="8452-5" />
<display value="Systolic blood pressure.inspiration - expiration v2" />
</concept>
<concept>
<code value="8459-0" />
<display value="Systolic blood pressure--sitting v2" />
</concept>
<concept>
<code value="8460-8" />
<display value="Systolic blood pressure--standing v2" />
</concept>
<concept>
<code value="8461-6" />
<display value="Systolic blood pressure--supine v2" />
</concept>
<concept>
<code value="8479-8" />
<display value="Systolic blood pressure by palpation v2" />
</concept>
<concept>
<code value="8480-6" />
<display value="Systolic blood pressure v2" />
</concept>
<concept>
<code value="8481-4" />
<display value="Systolic blood pressure 1 hour maximum v2" />
</concept>
<concept>
<code value="8482-2" />
<display value="Systolic blood pressure 8 hour maximum v2" />
</concept>
<concept>
<code value="8483-0" />
<display value="Systolic blood pressure 10 hour maximum v2" />
</concept>
<concept>
<code value="8484-8" />
<display value="Systolic blood pressure 12 hour maximum v2" />
</concept>
<concept>
<code value="8485-5" />
<display value="Systolic blood pressure 24 hour maximum v2" />
</concept>
<concept>
<code value="8486-3" />
<display value="Systolic blood pressure 1 hour mean v2" />
</concept>
<concept>
<code value="8487-1" />
<display value="Systolic blood pressure 8 hour mean v2" />
</concept>
<concept>
<code value="8488-9" />
<display value="Systolic blood pressure 10 hour mean v2" />
</concept>
<concept>
<code value="8489-7" />
<display value="Systolic blood pressure 12 hour mean v2" />
</concept>
<concept>
<code value="8490-5" />
<display value="Systolic blood pressure 24 hour mean v2" />
</concept>
<concept>
<code value="8491-3" />
<display value="Systolic blood pressure 1 hour minimum v2" />
</concept>
<concept>
<code value="8492-1" />
<display value="Systolic blood pressure 8 hour minimum v2" />
</concept>
</CodeSystem>