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

View File

@ -27,6 +27,7 @@ import java.util.Date;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.TemporalPrecisionEnum; import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
import ca.uhn.fhir.model.primitive.DateTimeDt; import ca.uhn.fhir.model.primitive.DateTimeDt;
import ca.uhn.fhir.rest.gclient.DateClientParam.IDateSpecifier;
import ca.uhn.fhir.rest.param.ParamPrefixEnum; import ca.uhn.fhir.rest.param.ParamPrefixEnum;
/** /**
@ -65,10 +66,11 @@ public class DateClientParam extends BaseClientParam implements IParam {
return new DateWithPrefix(ParamPrefixEnum.EQUAL); return new DateWithPrefix(ParamPrefixEnum.EQUAL);
} }
private class Criterion implements ICriterion<DateClientParam>, ICriterionInternal { private class Criterion implements IDateCriterion, ICriterionInternal {
private String myValue; private String myValue;
private ParamPrefixEnum myPrefix; private ParamPrefixEnum myPrefix;
private Criterion orCriterion;
public Criterion(ParamPrefixEnum thePrefix, String theValue) { public Criterion(ParamPrefixEnum thePrefix, String theValue) {
myPrefix = thePrefix; myPrefix = thePrefix;
@ -83,7 +85,16 @@ public class DateClientParam extends BaseClientParam implements IParam {
@Override @Override
public String getParameterValue(FhirContext theContext) { public String getParameterValue(FhirContext theContext) {
StringBuilder b = new StringBuilder(); StringBuilder b = new StringBuilder();
if (orCriterion != null) {
String orValue = orCriterion.getParameterValue(theContext);
if (isNotBlank(orValue)) {
b.append(orValue);
}
}
if (isNotBlank(myValue)) { if (isNotBlank(myValue)) {
if (b.length() > 0) {
b.append(',');
}
if (myPrefix != null && myPrefix != ParamPrefixEnum.EQUAL) { if (myPrefix != null && myPrefix != ParamPrefixEnum.EQUAL) {
b.append(myPrefix.getValueForContext(theContext)); b.append(myPrefix.getValueForContext(theContext));
} }
@ -92,69 +103,115 @@ public class DateClientParam extends BaseClientParam implements IParam {
return b.toString(); 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 class DateWithPrefix implements IDateSpecifier {
private ParamPrefixEnum myPrefix; private ParamPrefixEnum myPrefix;
private Criterion previous = null;
public DateWithPrefix(ParamPrefixEnum thePrefix, Criterion previous) {
myPrefix = thePrefix;
this.previous = previous;
}
public DateWithPrefix(ParamPrefixEnum thePrefix) { public DateWithPrefix(ParamPrefixEnum thePrefix) {
myPrefix = thePrefix; myPrefix = thePrefix;
} }
@Override @Override
public ICriterion<DateClientParam> day(Date theValue) { public IDateCriterion day(Date theValue) {
DateTimeDt dt = new DateTimeDt(theValue); DateTimeDt dt = new DateTimeDt(theValue);
dt.setPrecision(TemporalPrecisionEnum.DAY); dt.setPrecision(TemporalPrecisionEnum.DAY);
String valueAsString = dt.getValueAsString(); return constructCriterion(dt);
return new Criterion(myPrefix, valueAsString);
} }
@Override @Override
public ICriterion<DateClientParam> day(String theValue) { public IDateCriterion day(String theValue) {
DateTimeDt dt = new DateTimeDt(theValue); DateTimeDt dt = new DateTimeDt(theValue);
dt.setPrecision(TemporalPrecisionEnum.DAY); dt.setPrecision(TemporalPrecisionEnum.DAY);
String valueAsString = dt.getValueAsString(); return constructCriterion(dt);
return new Criterion(myPrefix , valueAsString);
} }
@Override @Override
public ICriterion<DateClientParam> now() { public IDateCriterion now() {
DateTimeDt dt = DateTimeDt.withCurrentTime(); DateTimeDt dt = DateTimeDt.withCurrentTime();
dt.setPrecision(TemporalPrecisionEnum.SECOND); dt.setPrecision(TemporalPrecisionEnum.SECOND);
String valueAsString = dt.getValueAsString(); return constructCriterion(dt);
return new Criterion(myPrefix , valueAsString);
} }
@Override @Override
public ICriterion<DateClientParam> second(Date theValue) { public IDateCriterion second(Date theValue) {
DateTimeDt dt = new DateTimeDt(theValue); DateTimeDt dt = new DateTimeDt(theValue);
dt.setPrecision(TemporalPrecisionEnum.SECOND); dt.setPrecision(TemporalPrecisionEnum.SECOND);
String valueAsString = dt.getValueAsString(); return constructCriterion(dt);
return new Criterion(myPrefix , valueAsString);
} }
@Override @Override
public ICriterion<DateClientParam> second(String theValue) { public IDateCriterion second(String theValue) {
DateTimeDt dt = new DateTimeDt(theValue); DateTimeDt dt = new DateTimeDt(theValue);
dt.setPrecision(TemporalPrecisionEnum.SECOND); dt.setPrecision(TemporalPrecisionEnum.SECOND);
String valueAsString = dt.getValueAsString(); return constructCriterion(dt);
return new Criterion(myPrefix , valueAsString); }
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 { 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; package ca.uhn.fhir.rest.gclient;
import java.util.Collection;
/* /*
* #%L * #%L
* HAPI FHIR - Core Library * HAPI FHIR - Core Library
@ -81,6 +83,13 @@ public interface IQuery<T> extends IClientExecutable<IQuery<T>, T>, IBaseQuery<I
*/ */
IQuery<T> withProfile(String theProfileUri); 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 * 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>) * <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.net.SocketTimeoutException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Arrays; import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.HashSet; 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); 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 @Test
public void testSearchLastUpdatedParamRp() throws InterruptedException { public void testSearchLastUpdatedParamRp() throws InterruptedException {
String methodName = "testSearchLastUpdatedParamRp"; String methodName = "testSearchLastUpdatedParamRp";