This commit is contained in:
James Agnew 2016-11-11 10:45:53 -05:00
parent 01afc49863
commit 846aecfe89
5 changed files with 1904 additions and 1758 deletions

View File

@ -26,9 +26,12 @@ import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@ -1900,7 +1903,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
private List<Include> myInclude = new ArrayList<Include>();
private DateRangeParam myLastUpdated;
private Integer myParamLimit;
private List<String> myProfile = new ArrayList<String>();
private List<Collection<String>> myProfiles = new ArrayList<Collection<String>>();
private String myResourceId;
private String myResourceName;
private Class<? extends IBaseResource> myResourceType;
@ -1981,8 +1984,15 @@ public class GenericClient extends BaseClient implements IGenericClient {
addParam(params, Constants.PARAM_SECURITY, next.getValueAsQueryToken(myContext));
}
for (String next : myProfile) {
addParam(params, Constants.PARAM_PROFILE, next);
for (Collection<String> profileUris : myProfiles) {
StringBuilder builder = new StringBuilder();
for (Iterator<String> profileItr = profileUris.iterator(); profileItr.hasNext(); ) {
builder.append(profileItr.next());
if (profileItr.hasNext()) {
builder.append(',');
}
}
addParam(params, Constants.PARAM_PROFILE, builder.toString());
}
for (Include next : myInclude) {
@ -2144,7 +2154,14 @@ public class GenericClient extends BaseClient implements IGenericClient {
@Override
public IQuery<Object> withProfile(String theProfileUri) {
Validate.notBlank(theProfileUri, "theProfileUri must not be null or empty");
myProfile.add(theProfileUri);
myProfiles.add(Collections.singletonList(theProfileUri));
return this;
}
@Override
public IQuery<Object> withAnyProfile(Collection<String> theProfileUris) {
Validate.notEmpty(theProfileUris, "theProfileUris must not be null or empty");
myProfiles.add(theProfileUris);
return this;
}
@ -2365,6 +2382,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
return this;
}
// TODO: This is not longer used.. Deprecate it or just remove it?
@Override
public IPatchTyped conditionalByUrl(String theSearchUrl) {
mySearchUrl = validateAndEscapeConditionalUrl(theSearchUrl);

View File

@ -27,6 +27,7 @@ import java.util.Date;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
import ca.uhn.fhir.model.primitive.DateTimeDt;
import ca.uhn.fhir.rest.gclient.DateClientParam.IDateSpecifier;
import ca.uhn.fhir.rest.param.ParamPrefixEnum;
/**
@ -65,10 +66,11 @@ public class DateClientParam extends BaseClientParam implements IParam {
return new DateWithPrefix(ParamPrefixEnum.EQUAL);
}
private class Criterion implements ICriterion<DateClientParam>, ICriterionInternal {
private class Criterion implements IDateCriterion, ICriterionInternal {
private String myValue;
private ParamPrefixEnum myPrefix;
private Criterion orCriterion;
public Criterion(ParamPrefixEnum thePrefix, String theValue) {
myPrefix = thePrefix;
@ -83,7 +85,16 @@ public class DateClientParam extends BaseClientParam implements IParam {
@Override
public String getParameterValue(FhirContext theContext) {
StringBuilder b = new StringBuilder();
if (orCriterion != null) {
String orValue = orCriterion.getParameterValue(theContext);
if (isNotBlank(orValue)) {
b.append(orValue);
}
}
if (isNotBlank(myValue)) {
if (b.length() > 0) {
b.append(',');
}
if (myPrefix != null && myPrefix != ParamPrefixEnum.EQUAL) {
b.append(myPrefix.getValueForContext(theContext));
}
@ -92,69 +103,115 @@ public class DateClientParam extends BaseClientParam implements IParam {
return b.toString();
}
@Override
public IDateSpecifier orAfter() {
return new DateWithPrefix(ParamPrefixEnum.GREATERTHAN, this);
}
@Override
public IDateSpecifier orAfterOrEquals() {
return new DateWithPrefix(ParamPrefixEnum.GREATERTHAN_OR_EQUALS, this);
}
@Override
public IDateSpecifier orBefore() {
return new DateWithPrefix(ParamPrefixEnum.LESSTHAN, this);
}
@Override
public IDateSpecifier orBeforeOrEquals() {
return new DateWithPrefix(ParamPrefixEnum.LESSTHAN_OR_EQUALS, this);
}
@Override
public IDateSpecifier orExactly() {
return new DateWithPrefix(ParamPrefixEnum.EQUAL, this);
}
}
private class DateWithPrefix implements IDateSpecifier {
private ParamPrefixEnum myPrefix;
private Criterion previous = null;
public DateWithPrefix(ParamPrefixEnum thePrefix, Criterion previous) {
myPrefix = thePrefix;
this.previous = previous;
}
public DateWithPrefix(ParamPrefixEnum thePrefix) {
myPrefix = thePrefix;
}
@Override
public ICriterion<DateClientParam> day(Date theValue) {
public IDateCriterion day(Date theValue) {
DateTimeDt dt = new DateTimeDt(theValue);
dt.setPrecision(TemporalPrecisionEnum.DAY);
String valueAsString = dt.getValueAsString();
return new Criterion(myPrefix, valueAsString);
return constructCriterion(dt);
}
@Override
public ICriterion<DateClientParam> day(String theValue) {
public IDateCriterion day(String theValue) {
DateTimeDt dt = new DateTimeDt(theValue);
dt.setPrecision(TemporalPrecisionEnum.DAY);
String valueAsString = dt.getValueAsString();
return new Criterion(myPrefix , valueAsString);
return constructCriterion(dt);
}
@Override
public ICriterion<DateClientParam> now() {
public IDateCriterion now() {
DateTimeDt dt = DateTimeDt.withCurrentTime();
dt.setPrecision(TemporalPrecisionEnum.SECOND);
String valueAsString = dt.getValueAsString();
return new Criterion(myPrefix , valueAsString);
return constructCriterion(dt);
}
@Override
public ICriterion<DateClientParam> second(Date theValue) {
public IDateCriterion second(Date theValue) {
DateTimeDt dt = new DateTimeDt(theValue);
dt.setPrecision(TemporalPrecisionEnum.SECOND);
String valueAsString = dt.getValueAsString();
return new Criterion(myPrefix , valueAsString);
return constructCriterion(dt);
}
@Override
public ICriterion<DateClientParam> second(String theValue) {
public IDateCriterion second(String theValue) {
DateTimeDt dt = new DateTimeDt(theValue);
dt.setPrecision(TemporalPrecisionEnum.SECOND);
String valueAsString = dt.getValueAsString();
return new Criterion(myPrefix , valueAsString);
return constructCriterion(dt);
}
private IDateCriterion constructCriterion(DateTimeDt dt) {
String valueAsString = dt.getValueAsString();
Criterion criterion = new Criterion(myPrefix, valueAsString);
if (previous != null) {
criterion.orCriterion = previous;
}
return criterion;
}
}
public interface IDateSpecifier {
ICriterion<DateClientParam> day(Date theValue);
IDateCriterion day(Date theValue);
ICriterion<DateClientParam> day(String theValue);
IDateCriterion day(String theValue);
ICriterion<DateClientParam> now();
IDateCriterion now();
ICriterion<DateClientParam> second(Date theValue);
IDateCriterion second(Date theValue);
ICriterion<DateClientParam> second(String theValue);
IDateCriterion second(String theValue);
}
public interface IDateCriterion extends ICriterion<DateClientParam> {
IDateSpecifier orAfter();
IDateSpecifier orAfterOrEquals();
IDateSpecifier orBefore();
IDateSpecifier orBeforeOrEquals();
IDateSpecifier orExactly();
}
}

View File

@ -1,5 +1,7 @@
package ca.uhn.fhir.rest.gclient;
import java.util.Collection;
/*
* #%L
* HAPI FHIR - Core Library
@ -81,6 +83,13 @@ public interface IQuery<T> extends IClientExecutable<IQuery<T>, T>, IBaseQuery<I
*/
IQuery<T> withProfile(String theProfileUri);
/**
* Matches any of the profiles given as argument. This would result in an OR search for resources matching one or more profiles.
* To do an AND search, make multiple calls to {@link #withProfile(String)}.
* @param theProfileUris The URIs of a given profile to search for resources which match.
*/
IQuery<T> withAnyProfile(Collection<String> theProfileUris);
/**
* Forces the query to perform the search using the given method (allowable methods are described in the
* <a href="http://www.hl7.org/fhir/search.html">FHIR Search Specification</a>)

View File

@ -26,6 +26,7 @@ import java.net.Socket;
import java.net.SocketTimeoutException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
@ -1641,7 +1642,56 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
assertEquals("Expects to retrieve the 2 patients which reference the two different organizations", expectedIds, actualIds);
}
@Test
public void testForResourcesWithProfile() {
Organization o1 = new Organization();
o1.setName("testSearchByResourceChainName01");
o1.getMeta().addProfile("http://profile1").addProfile("http://profile2");
IdDt o1id = (IdDt) ourClient.create().resource(o1).execute().getId().toUnqualifiedVersionless();
Organization o2 = new Organization();
o2.setName("testSearchByResourceChainName02");
o2.getMeta().addProfile("http://profile1").addProfile("http://profile3");
IdDt o2id = (IdDt) ourClient.create().resource(o2).execute().getId().toUnqualifiedVersionless();
//@formatter:off
Bundle actual = ourClient.search()
.forResource(Organization.class)
.withProfile("http://profile1")
.withProfile("http://profileX")
.encodedJson().prettyPrint().execute();
//@formatter:on
assertEquals("nothing matches profile x", Collections.emptyList(), actual.getEntries());
//@formatter:off
actual = ourClient.search()
.forResource(Organization.class)
.withProfile("http://profile1")
.withProfile("http://profile2")
.encodedJson().prettyPrint().execute();
//@formatter:on
Set<String> expectedIds = new HashSet<String>();
expectedIds.add(o1id.getIdPart());
Set<String> actualIds = new HashSet<String>();
for (BundleEntry ele : actual.getEntries()) {
actualIds.add(ele.getResource().getId().getIdPart());
}
assertEquals("Expects to retrieve the 1 orgination matching on Org1's profiles", expectedIds, actualIds);
//@formatter:off
actual = ourClient.search()
.forResource(Organization.class)
.withProfile("http://profile1")
.withAnyProfile(Arrays.asList("http://profile3", "http://profile2"))
.encodedJson().prettyPrint().execute();
//@formatter:on
expectedIds = new HashSet<String>();
expectedIds.add(o1id.getIdPart());
expectedIds.add(o2id.getIdPart());
actualIds = new HashSet<String>();
for (BundleEntry ele : actual.getEntries()) {
actualIds.add(ele.getResource().getId().getIdPart());
}
assertEquals("Expects to retrieve the 2 orginations, since we match on (the common profile AND (Org1's second profile OR org2's second profile))", expectedIds, actualIds);
}
@Test
public void testSearchLastUpdatedParamRp() throws InterruptedException {
String methodName = "testSearchLastUpdatedParamRp";