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:
parent
38a975f09d
commit
ce1caee9fa
|
@ -24,6 +24,8 @@ import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.lang3.Validate;
|
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.ConfigurationException;
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
@ -108,4 +110,12 @@ public class CompositeParam<A extends IQueryParameterType, B extends IQueryParam
|
||||||
return myRightType;
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,16 @@
|
||||||
package ca.uhn.fhir.rest.param;
|
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.ConfigurationException;
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
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.rest.param.binder.QueryParameterAndBinder;
|
||||||
import ca.uhn.fhir.util.ReflectionUtil;
|
import ca.uhn.fhir.util.ReflectionUtil;
|
||||||
import ca.uhn.fhir.util.UrlUtil;
|
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
|
* #%L
|
||||||
|
@ -114,11 +115,70 @@ public class ParameterUtil {
|
||||||
* This is a utility method intended provided to help the JPA module.
|
* This is a utility method intended provided to help the JPA module.
|
||||||
*/
|
*/
|
||||||
public static IQueryParameterAnd<?> parseQueryParams(FhirContext theContext, RuntimeSearchParam theParamDef,
|
public static IQueryParameterAnd<?> parseQueryParams(FhirContext theContext, RuntimeSearchParam theParamDef,
|
||||||
String theUnqualifiedParamName, List<QualifiedParamList> theParameters) {
|
String theUnqualifiedParamName, List<QualifiedParamList> theParameters) {
|
||||||
|
|
||||||
RestSearchParameterTypeEnum paramType = theParamDef.getParamType();
|
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
|
* Removes :modifiers and .chains from URL parameter names
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -265,26 +265,37 @@ public class QueryStack {
|
||||||
return new PredicateBuilderCacheLookupResult<>(cacheHit, (T) retVal);
|
return new PredicateBuilderCacheLookupResult<>(cacheHit, (T) retVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Condition createPredicateComposite(@Nullable DbColumn theSourceJoinColumn, String theResourceName, RuntimeSearchParam theParamDef, List<? extends IQueryParameterType> theNextAnd, RequestPartitionId theRequestPartitionId) {
|
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
|
|
||||||
|
|
||||||
IQueryParameterType or = theNextAnd.get(0);
|
Condition orCondidtion = null;
|
||||||
if (!(or instanceof CompositeParam<?, ?>)) {
|
for (IQueryParameterType next : theNextAnd) {
|
||||||
throw new InvalidRequestException("Invalid type for composite param (must be " + CompositeParam.class.getSimpleName() + ": " + or.getClass());
|
|
||||||
|
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;
|
|
||||||
|
return orCondidtion;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private Condition createPredicateCompositePart(@Nullable DbColumn theSourceJoinColumn, String theResourceName, RuntimeSearchParam theParam, IQueryParameterType theParamValue, RequestPartitionId theRequestPartitionId) {
|
private Condition createPredicateCompositePart(@Nullable DbColumn theSourceJoinColumn, String theResourceName, RuntimeSearchParam theParam, IQueryParameterType theParamValue, RequestPartitionId theRequestPartitionId) {
|
||||||
|
|
||||||
switch (theParam.getParamType()) {
|
switch (theParam.getParamType()) {
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue