Feature 2020 10 28 reverse chain (#2160)

* Added test cases for multiple '_has'

* Fixed composite search for the new SearchBuilder

* Added more test cases
This commit is contained in:
Frank Tao 2020-11-05 05:27:11 -05:00 committed by GitHub
parent 38a975f09d
commit ce1caee9fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 719 additions and 28 deletions

View File

@ -24,6 +24,8 @@ import static org.apache.commons.lang3.StringUtils.isBlank;
import java.util.List;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
@ -108,4 +110,12 @@ public class CompositeParam<A extends IQueryParameterType, B extends IQueryParam
return myRightType;
}
@Override
public String toString() {
ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
b.append("myLeftType", getLeftValue());
b.append("myRightType", getRightValue());
return b.toString();
}
}

View File

@ -1,5 +1,16 @@
package ca.uhn.fhir.rest.param;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeSearchParam;
@ -15,16 +26,6 @@ import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
import ca.uhn.fhir.rest.param.binder.QueryParameterAndBinder;
import ca.uhn.fhir.util.ReflectionUtil;
import ca.uhn.fhir.util.UrlUtil;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/*
* #%L
@ -114,11 +115,70 @@ public class ParameterUtil {
* This is a utility method intended provided to help the JPA module.
*/
public static IQueryParameterAnd<?> parseQueryParams(FhirContext theContext, RuntimeSearchParam theParamDef,
String theUnqualifiedParamName, List<QualifiedParamList> theParameters) {
String theUnqualifiedParamName, List<QualifiedParamList> theParameters) {
RestSearchParameterTypeEnum paramType = theParamDef.getParamType();
return parseQueryParams(theContext, paramType, theUnqualifiedParamName, theParameters);
if (paramType == RestSearchParameterTypeEnum.COMPOSITE) {
List<RuntimeSearchParam> theCompositList = theParamDef.getCompositeOf();
if (theCompositList == null) {
throw new ConfigurationException("Search parameter of type " + theUnqualifiedParamName
+ " can be found in parameter annotation, found ");
}
if (theCompositList.size() != 2) {
throw new ConfigurationException("Search parameter of type " + theUnqualifiedParamName
+ " must have 2 composite types declared in parameter annotation, found "
+ theCompositList.size());
}
RuntimeSearchParam left = theCompositList.get(0);
RuntimeSearchParam right = theCompositList.get(1);
@SuppressWarnings({ "unchecked", "rawtypes" })
CompositeAndListParam<IQueryParameterType, IQueryParameterType> cp = new CompositeAndListParam(
getCompositBindingClass(left.getParamType(), left.getName()),
getCompositBindingClass(right.getParamType(), right.getName()));
cp.setValuesAsQueryTokens(theContext, theUnqualifiedParamName, theParameters);
return cp;
} else {
return parseQueryParams(theContext, paramType, theUnqualifiedParamName, theParameters);
}
}
private static Class<?> getCompositBindingClass(RestSearchParameterTypeEnum paramType,
String theUnqualifiedParamName) {
switch (paramType) {
case DATE:
return DateParam.class;
case NUMBER:
return NumberParam.class;
case QUANTITY:
return QuantityParam.class;
case REFERENCE:
return ReferenceParam.class;
case STRING:
return StringParam.class;
case TOKEN:
return TokenParam.class;
case URI:
return UriParam.class;
case HAS:
return HasParam.class;
case SPECIAL:
return SpecialParam.class;
default:
throw new IllegalArgumentException("Parameter '" + theUnqualifiedParamName + "' has type " + paramType
+ " which is currently not supported.");
}
}
/**
* Removes :modifiers and .chains from URL parameter names
*/

View File

@ -265,26 +265,37 @@ public class QueryStack {
return new PredicateBuilderCacheLookupResult<>(cacheHit, (T) retVal);
}
private Condition createPredicateComposite(@Nullable DbColumn theSourceJoinColumn, String theResourceName, RuntimeSearchParam theParamDef, List<? extends IQueryParameterType> theNextAnd, RequestPartitionId theRequestPartitionId) {
// TODO: fail if missing is set for a composite query
private Condition createPredicateComposite(@Nullable DbColumn theSourceJoinColumn, String theResourceName, RuntimeSearchParam theParamDef, List<? extends IQueryParameterType> theNextAnd, RequestPartitionId theRequestPartitionId) {
IQueryParameterType or = theNextAnd.get(0);
if (!(or instanceof CompositeParam<?, ?>)) {
throw new InvalidRequestException("Invalid type for composite param (must be " + CompositeParam.class.getSimpleName() + ": " + or.getClass());
Condition orCondidtion = null;
for (IQueryParameterType next : theNextAnd) {
if (!(next instanceof CompositeParam<?, ?>)) {
throw new InvalidRequestException("Invalid type for composite param (must be " + CompositeParam.class.getSimpleName() + ": " + next.getClass());
}
CompositeParam<?, ?> cp = (CompositeParam<?, ?>) next;
RuntimeSearchParam left = theParamDef.getCompositeOf().get(0);
IQueryParameterType leftValue = cp.getLeftValue();
Condition leftPredicate = createPredicateCompositePart(theSourceJoinColumn, theResourceName, left, leftValue, theRequestPartitionId);
RuntimeSearchParam right = theParamDef.getCompositeOf().get(1);
IQueryParameterType rightValue = cp.getRightValue();
Condition rightPredicate = createPredicateCompositePart(theSourceJoinColumn, theResourceName, right, rightValue, theRequestPartitionId);
Condition andCondition = toAndPredicate(leftPredicate, rightPredicate);
if (orCondidtion == null) {
orCondidtion = toOrPredicate(andCondition);
} else {
orCondidtion = toOrPredicate(orCondidtion, andCondition);
}
}
CompositeParam<?, ?> cp = (CompositeParam<?, ?>) or;
RuntimeSearchParam left = theParamDef.getCompositeOf().get(0);
IQueryParameterType leftValue = cp.getLeftValue();
Condition leftPredicate = createPredicateCompositePart(theSourceJoinColumn, theResourceName, left, leftValue, theRequestPartitionId);
RuntimeSearchParam right = theParamDef.getCompositeOf().get(1);
IQueryParameterType rightValue = cp.getRightValue();
Condition rightPredicate = createPredicateCompositePart(theSourceJoinColumn, theResourceName, right, rightValue, theRequestPartitionId);
return toAndPredicate(leftPredicate, rightPredicate);
return orCondidtion;
}
private Condition createPredicateCompositePart(@Nullable DbColumn theSourceJoinColumn, String theResourceName, RuntimeSearchParam theParam, IQueryParameterType theParamValue, RequestPartitionId theRequestPartitionId) {
switch (theParam.getParamType()) {

View File

@ -0,0 +1,610 @@
package ca.uhn.fhir.jpa.provider.r4;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.contains;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import org.apache.commons.io.IOUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.CodeableConcept;
import org.hl7.fhir.r4.model.DateTimeType;
import org.hl7.fhir.r4.model.Device;
import org.hl7.fhir.r4.model.Encounter;
import org.hl7.fhir.r4.model.Observation;
import org.hl7.fhir.r4.model.Observation.ObservationComponentComponent;
import org.hl7.fhir.r4.model.Patient;
import org.hl7.fhir.r4.model.Period;
import org.hl7.fhir.r4.model.Quantity;
import org.hl7.fhir.r4.model.Reference;
import org.hl7.fhir.r4.model.StringType;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import ca.uhn.fhir.jpa.api.config.DaoConfig;
import ca.uhn.fhir.parser.StrictErrorHandler;
import ca.uhn.fhir.rest.client.interceptor.CapturingInterceptor;
import ca.uhn.fhir.util.UrlUtil;
public class ResourceProviderHasParamR4Test extends BaseResourceProviderR4Test {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceProviderHasParamR4Test.class);
private CapturingInterceptor myCapturingInterceptor = new CapturingInterceptor();
@Override
@AfterEach
public void after() throws Exception {
super.after();
myDaoConfig.setAllowMultipleDelete(new DaoConfig().isAllowMultipleDelete());
myDaoConfig.setAllowExternalReferences(new DaoConfig().isAllowExternalReferences());
myDaoConfig.setReuseCachedSearchResultsForMillis(new DaoConfig().getReuseCachedSearchResultsForMillis());
myDaoConfig.setCountSearchResultsUpTo(new DaoConfig().getCountSearchResultsUpTo());
myDaoConfig.setSearchPreFetchThresholds(new DaoConfig().getSearchPreFetchThresholds());
myDaoConfig.setAllowContainsSearches(new DaoConfig().isAllowContainsSearches());
myDaoConfig.setIndexMissingFields(new DaoConfig().getIndexMissingFields());
myClient.unregisterInterceptor(myCapturingInterceptor);
}
@BeforeEach
@Override
public void before() throws Exception {
super.before();
myFhirCtx.setParserErrorHandler(new StrictErrorHandler());
myDaoConfig.setAllowMultipleDelete(true);
myClient.registerInterceptor(myCapturingInterceptor);
myDaoConfig.setSearchPreFetchThresholds(new DaoConfig().getSearchPreFetchThresholds());
//myDaoConfig.setUseLegacySearchBuilder(true);
}
@BeforeEach
public void beforeDisableResultReuse() {
myDaoConfig.setReuseCachedSearchResultsForMillis(null);
}
@Test
public void testHasParameter() throws Exception {
IIdType pid0;
{
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("001");
patient.addName().setFamily("Tester").addGiven("Joe");
pid0 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
{
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("001");
patient.addName().setFamily("Tester").addGiven("Joe");
myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
{
Observation obs = new Observation();
obs.addIdentifier().setSystem("urn:system").setValue("FOO");
obs.getSubject().setReferenceElement(pid0);
myObservationDao.create(obs, mySrd);
}
{
Device device = new Device();
device.addIdentifier().setValue("DEVICEID");
IIdType devId = myDeviceDao.create(device, mySrd).getId().toUnqualifiedVersionless();
Observation obs = new Observation();
obs.addIdentifier().setSystem("urn:system").setValue("NOLINK");
obs.setDevice(new Reference(devId));
myObservationDao.create(obs, mySrd);
}
String uri = ourServerBase + "/Patient?_has:Observation:subject:identifier=" + UrlUtil.escapeUrlParam("urn:system|FOO");
List<String> ids = searchAndReturnUnqualifiedVersionlessIdValues(uri);
assertThat(ids, contains(pid0.getValue()));
}
@Test
public void testMultipleHasParametersOfSameType() throws Exception {
IIdType pid0;
{
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("001");
patient.addName().setFamily("Tester").addGiven("Joe");
pid0 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
{
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("001");
patient.addName().setFamily("Tester").addGiven("Joe");
myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
{
Observation obs = new Observation();
obs.addIdentifier().setSystem("urn:system").setValue("FOO");
obs.getSubject().setReferenceElement(pid0);
myObservationDao.create(obs, mySrd);
}
{
Device device = new Device();
device.addIdentifier().setValue("DEVICEID");
IIdType devId = myDeviceDao.create(device, mySrd).getId().toUnqualifiedVersionless();
Observation obs = new Observation();
obs.addIdentifier().setSystem("urn:system").setValue("NOLINK");
obs.setDevice(new Reference(devId));
myObservationDao.create(obs, mySrd);
}
{
Encounter encounter = new Encounter();
encounter.addIdentifier().setValue("theEncounter");
encounter.getClass_().setCode("IMP").setSystem("urn:system");
encounter.getPeriod().setStartElement(new DateTimeType("2020-01-01")).setEndElement(new DateTimeType("2020-09-30"));
encounter.setSubject(new Reference(pid0));
myEncounterDao.create(encounter, mySrd);
ourLog.info("Encounter: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(encounter));
}
String uri = ourServerBase + "/Patient?_has:Encounter:subject:class=" + UrlUtil.escapeUrlParam("urn:system|IMP") + "&_has:Encounter:subject:date=gt1950";
ourLog.info("uri = " + uri);
List<String> ids = searchAndReturnUnqualifiedVersionlessIdValues(uri);
System.out.println("ids.size() = " + ids.size());
assertThat(ids, contains(pid0.getValue()));
}
@Test
public void testMultipleHasParametersOfDifferentType() throws Exception {
IIdType pid0;
{
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("001");
patient.addName().setFamily("Tester").addGiven("Joe");
pid0 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
{
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("001");
patient.addName().setFamily("Tester").addGiven("Joe");
myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
{
Observation obs = new Observation();
obs.addIdentifier().setSystem("urn:system").setValue("FOO");
obs.getSubject().setReferenceElement(pid0);
CodeableConcept cc = obs.getCode();
cc.addCoding().setCode("2345-7").setSystem("http://loinc.org");
myObservationDao.create(obs, mySrd);
ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs));
}
{
Device device = new Device();
device.addIdentifier().setValue("DEVICEID");
IIdType devId = myDeviceDao.create(device, mySrd).getId().toUnqualifiedVersionless();
Observation obs = new Observation();
obs.addIdentifier().setSystem("urn:system").setValue("NOLINK");
obs.setDevice(new Reference(devId));
myObservationDao.create(obs, mySrd);
}
{
Encounter encounter = new Encounter();
encounter.addIdentifier().setValue("theEncounter");
encounter.getClass_().setCode("IMP").setSystem("urn:system");
encounter.getPeriod().setStartElement(new DateTimeType("2020-01-01")).setEndElement(new DateTimeType("2020-09-30"));
encounter.setSubject(new Reference(pid0));
myEncounterDao.create(encounter, mySrd);
ourLog.info("Encounter: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(encounter));
}
String uri = ourServerBase + "/Patient?_has:Observation:patient:code=http://" + UrlUtil.escapeUrlParam("loinc.org|2345-7") + "&_has:Encounter:subject:date=gt1950";
ourLog.info("uri = " + uri);
List<String> ids = searchAndReturnUnqualifiedVersionlessIdValues(uri);
assertThat(ids, contains(pid0.getValue()));
}
@Test
public void testHasCompositeParameterCodeValueQuantity() throws Exception {
IIdType pid0;
{
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("001");
patient.addName().setFamily("Tester").addGiven("Joe");
pid0 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
{
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("001");
patient.addName().setFamily("Tester").addGiven("Joe");
myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
{
Observation obs = new Observation();
obs.addIdentifier().setSystem("urn:system").setValue("FOO");
obs.getSubject().setReferenceElement(pid0);
CodeableConcept cc = obs.getCode();
cc.addCoding().setCode("2345-7").setSystem("http://loinc.org");
Quantity q = new Quantity();
q.setValue(200);
obs.setValue(q);
myObservationDao.create(obs, mySrd);
ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs));
}
{
Device device = new Device();
device.addIdentifier().setValue("DEVICEID");
IIdType devId = myDeviceDao.create(device, mySrd).getId().toUnqualifiedVersionless();
Observation obs = new Observation();
obs.addIdentifier().setSystem("urn:system").setValue("NOLINK");
obs.setDevice(new Reference(devId));
myObservationDao.create(obs, mySrd);
}
String uri = ourServerBase + "/Patient?_has:Observation:subject:code-value-quantity=http://" + UrlUtil.escapeUrlParam("loinc.org|2345-7$gt180");
ourLog.info("uri = " + uri);
List<String> ids = searchAndReturnUnqualifiedVersionlessIdValues(uri);
assertThat(ids, contains(pid0.getValue()));
}
@Test
public void testHasCompositeParameterCodeValueDate() throws Exception {
IIdType pid0;
{
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("001");
patient.addName().setFamily("Tester").addGiven("Joe");
pid0 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
{
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("001");
patient.addName().setFamily("Tester").addGiven("Joe");
myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
{
Observation obs = new Observation();
obs.addIdentifier().setSystem("urn:system").setValue("FOO");
obs.getSubject().setReferenceElement(pid0);
CodeableConcept cc = obs.getCode();
cc.addCoding().setCode("2345-7").setSystem("http://loinc.org");
Period period = new Period();
period.setStartElement(new DateTimeType("2020-01-01"));
period.setEndElement(new DateTimeType("2020-09-30"));
obs.setValue(period);
myObservationDao.create(obs, mySrd);
ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs));
}
{
Device device = new Device();
device.addIdentifier().setValue("DEVICEID");
IIdType devId = myDeviceDao.create(device, mySrd).getId().toUnqualifiedVersionless();
Observation obs = new Observation();
obs.addIdentifier().setSystem("urn:system").setValue("NOLINK");
obs.setDevice(new Reference(devId));
myObservationDao.create(obs, mySrd);
}
String uri = ourServerBase + "/Patient?_has:Observation:subject:code-value-date=http://" + UrlUtil.escapeUrlParam("loinc.org|2345-7$gt2019");
ourLog.info("uri = " + uri);
List<String> ids = searchAndReturnUnqualifiedVersionlessIdValues(uri);
assertThat(ids, contains(pid0.getValue()));
}
@Test
public void testHasCompositeParameterCompCodeValueQuantity() throws Exception {
IIdType pid0;
{
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("001");
patient.addName().setFamily("Tester").addGiven("Joe");
pid0 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
{
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("001");
patient.addName().setFamily("Tester").addGiven("Joe");
myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
{
Observation obs = new Observation();
obs.addIdentifier().setSystem("urn:system").setValue("FOO");
obs.getSubject().setReferenceElement(pid0);
CodeableConcept cc = obs.getCode();
cc.addCoding().setCode("2345-7").setSystem("http://loinc.org");
Period period = new Period();
period.setStartElement(new DateTimeType("2020-01-01"));
period.setEndElement(new DateTimeType("2020-09-30"));
obs.setValue(period);
ObservationComponentComponent comp = obs.addComponent();
CodeableConcept compCC = comp.getCode();
compCC.addCoding().setCode("2345-8").setSystem("http://loinc.org");
Quantity q = new Quantity();
q.setValue(200);
comp.setValue(q);
myObservationDao.create(obs, mySrd);
ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs));
}
{
Device device = new Device();
device.addIdentifier().setValue("DEVICEID");
IIdType devId = myDeviceDao.create(device, mySrd).getId().toUnqualifiedVersionless();
Observation obs = new Observation();
obs.addIdentifier().setSystem("urn:system").setValue("NOLINK");
obs.setDevice(new Reference(devId));
myObservationDao.create(obs, mySrd);
}
String uri = ourServerBase + "/Patient?_has:Observation:subject:combo-code-value-quantity=http://" + UrlUtil.escapeUrlParam("loinc.org|2345-8$200");
ourLog.info("uri = " + uri);
List<String> ids = searchAndReturnUnqualifiedVersionlessIdValues(uri);
assertThat(ids, contains(pid0.getValue()));
}
@Test
public void testHasCompositeParameterCodeValueStringOr() throws Exception {
IIdType pid0;
IIdType pid1;
{
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("001");
patient.addName().setFamily("Tester").addGiven("Joe");
pid0 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
{
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("001");
patient.addName().setFamily("Tester").addGiven("Joe");
pid1 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
{
Observation obs = new Observation();
obs.addIdentifier().setSystem("urn:system").setValue("FOO");
obs.getSubject().setReferenceElement(pid0);
CodeableConcept cc = obs.getCode();
cc.addCoding().setCode("2345-7").setSystem("http://loinc.org");
obs.setValue(new StringType("100"));
myObservationDao.create(obs, mySrd);
ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs));
}
{
Observation obs = new Observation();
obs.addIdentifier().setSystem("urn:system").setValue("BAR");
obs.getSubject().setReferenceElement(pid1);
CodeableConcept cc = obs.getCode();
cc.addCoding().setCode("2345-7").setSystem("http://loinc.org");
obs.setValue(new StringType("200"));
myObservationDao.create(obs, mySrd);
ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs));
}
{
Device device = new Device();
device.addIdentifier().setValue("DEVICEID");
IIdType devId = myDeviceDao.create(device, mySrd).getId().toUnqualifiedVersionless();
Observation obs = new Observation();
obs.addIdentifier().setSystem("urn:system").setValue("NOLINK");
obs.setDevice(new Reference(devId));
myObservationDao.create(obs, mySrd);
}
String uri = ourServerBase + "/Patient?_has:Observation:subject:code-value-string=http://" + UrlUtil.escapeUrlParam("loinc.org|2345-7$100,http://loinc.org|2345-7$200");
ourLog.info("uri = " + uri);
List<String> ids = searchAndReturnUnqualifiedVersionlessIdValues(uri);
assertEquals(2, ids.size());
}
@Test
public void testHasCompositeParameterWithNoResult() throws Exception {
IIdType pid0;
{
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("001");
patient.addName().setFamily("Tester").addGiven("Joe");
pid0 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
{
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("001");
patient.addName().setFamily("Tester").addGiven("Joe");
myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
{
Observation obs = new Observation();
obs.addIdentifier().setSystem("urn:system").setValue("FOO");
obs.getSubject().setReferenceElement(pid0);
CodeableConcept cc = obs.getCode();
cc.addCoding().setCode("2345-7").setSystem("http://loinc.org");
Quantity q = new Quantity();
q.setValue(200);
obs.setValue(q);
myObservationDao.create(obs, mySrd);
ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs));
}
{
Device device = new Device();
device.addIdentifier().setValue("DEVICEID");
IIdType devId = myDeviceDao.create(device, mySrd).getId().toUnqualifiedVersionless();
Observation obs = new Observation();
obs.addIdentifier().setSystem("urn:system").setValue("NOLINK");
obs.setDevice(new Reference(devId));
myObservationDao.create(obs, mySrd);
}
String uri = ourServerBase + "/Patient?_has:Observation:subject:code-value-quantity=http://" + UrlUtil.escapeUrlParam("loinc.org|2345-7$lt180");
ourLog.info("uri = " + uri);
List<String> ids = searchAndReturnUnqualifiedVersionlessIdValues(uri);
assertEquals(0, ids.size());
}
@Test
public void testMultipleHasParameterWithCompositeOfSameType() throws Exception {
IIdType pid0;
{
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("001");
patient.addName().setFamily("Tester").addGiven("Joe");
pid0 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
{
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("001");
patient.addName().setFamily("Tester").addGiven("Joe");
myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
{
Observation obs = new Observation();
obs.addIdentifier().setSystem("urn:system").setValue("FOO");
obs.getSubject().setReferenceElement(pid0);
CodeableConcept cc = obs.getCode();
cc.addCoding().setCode("2345-7").setSystem("http://loinc.org");
Quantity q = new Quantity();
q.setValue(200);
obs.setValue(q);
myObservationDao.create(obs, mySrd);
ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs));
}
{
Device device = new Device();
device.addIdentifier().setValue("DEVICEID");
IIdType devId = myDeviceDao.create(device, mySrd).getId().toUnqualifiedVersionless();
Observation obs = new Observation();
obs.addIdentifier().setSystem("urn:system").setValue("NOLINK");
obs.setDevice(new Reference(devId));
myObservationDao.create(obs, mySrd);
}
String uri = ourServerBase + "/Patient?_has:Observation:subject:code-value-quantity=http://" + UrlUtil.escapeUrlParam("loinc.org|2345-7$gt180") + "&_has:Observation:subject:identifier=" + UrlUtil.escapeUrlParam("urn:system|FOO");
ourLog.info("uri = " + uri);
List<String> ids = searchAndReturnUnqualifiedVersionlessIdValues(uri);
assertThat(ids, contains(pid0.getValue()));
}
@Test
public void testMultipleHasParameterWithCompositeOfDifferentType() throws Exception {
IIdType pid0;
{
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("001");
patient.addName().setFamily("Tester").addGiven("Joe");
pid0 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
{
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("001");
patient.addName().setFamily("Tester").addGiven("Joe");
myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
{
Observation obs = new Observation();
obs.addIdentifier().setSystem("urn:system").setValue("FOO");
obs.getSubject().setReferenceElement(pid0);
CodeableConcept cc = obs.getCode();
cc.addCoding().setCode("2345-7").setSystem("http://loinc.org");
Quantity q = new Quantity();
q.setValue(200);
obs.setValue(q);
myObservationDao.create(obs, mySrd);
ourLog.info("Observation: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs));
}
{
Device device = new Device();
device.addIdentifier().setValue("DEVICEID");
IIdType devId = myDeviceDao.create(device, mySrd).getId().toUnqualifiedVersionless();
Observation obs = new Observation();
obs.addIdentifier().setSystem("urn:system").setValue("NOLINK");
obs.setDevice(new Reference(devId));
myObservationDao.create(obs, mySrd);
}
{
Encounter encounter = new Encounter();
encounter.addIdentifier().setValue("theEncounter");
encounter.getClass_().setCode("IMP").setSystem("urn:system");
encounter.getPeriod().setStartElement(new DateTimeType("2020-01-01")).setEndElement(new DateTimeType("2020-09-30"));
encounter.setSubject(new Reference(pid0));
myEncounterDao.create(encounter, mySrd);
ourLog.info("Encounter: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(encounter));
}
String uri = ourServerBase + "/Patient?_has:Observation:subject:code-value-quantity=http://" + UrlUtil.escapeUrlParam("loinc.org|2345-7$gt180") + "&_has:Encounter:subject:date=gt1950" + "&_has:Encounter:subject:class=" + UrlUtil.escapeUrlParam("urn:system|IMP");
ourLog.info("uri = " + uri);
List<String> ids = searchAndReturnUnqualifiedVersionlessIdValues(uri);
assertThat(ids, contains(pid0.getValue()));
}
private List<String> searchAndReturnUnqualifiedVersionlessIdValues(String uri) throws IOException {
List<String> ids;
HttpGet get = new HttpGet(uri);
try (CloseableHttpResponse response = ourHttpClient.execute(get)) {
String resp = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
ourLog.info(resp);
Bundle bundle = myFhirCtx.newXmlParser().parseResource(Bundle.class, resp);
ids = toUnqualifiedVersionlessIdValues(bundle);
}
return ids;
}
}