Implements support for _tag in JPA server and client
This commit is contained in:
parent
7988cc3993
commit
ab2129d651
|
@ -269,6 +269,7 @@ public class GenericClientExample {
|
|||
.encodedJson()
|
||||
.where(Patient.BIRTHDATE.beforeOrEquals().day("2012-01-22"))
|
||||
.and(Patient.BIRTHDATE.after().day("2011-01-01"))
|
||||
.withTag("http://acme.org/codes", "needs-review")
|
||||
.include(Patient.INCLUDE_ORGANIZATION)
|
||||
.revInclude(Provenance.INCLUDE_TARGET)
|
||||
.lastUpdated(new DateRangeParam("2011-01-01", null))
|
||||
|
|
|
@ -129,6 +129,7 @@ import ca.uhn.fhir.rest.method.ValidateMethodBindingDstu1;
|
|||
import ca.uhn.fhir.rest.method.ValidateMethodBindingDstu2;
|
||||
import ca.uhn.fhir.rest.param.DateParam;
|
||||
import ca.uhn.fhir.rest.param.DateRangeParam;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.IVersionSpecificBundleFactory;
|
||||
|
@ -1556,6 +1557,10 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
|
||||
myCriterion.populateParamList(params);
|
||||
|
||||
for (TokenParam next : myTags) {
|
||||
addParam(params, Constants.PARAM_TAG, next.getValueAsQueryToken());
|
||||
}
|
||||
|
||||
for (Include next : myInclude) {
|
||||
addParam(params, Constants.PARAM_INCLUDE, next.getValue());
|
||||
}
|
||||
|
@ -1689,6 +1694,15 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
return this;
|
||||
}
|
||||
|
||||
private List<TokenParam> myTags = new ArrayList<TokenParam>();
|
||||
|
||||
@Override
|
||||
public IQuery<Object> withTag(String theSystem, String theCode) {
|
||||
Validate.notBlank(theCode, "theCode must not be null or empty");
|
||||
myTags.add(new TokenParam(theSystem, theCode));
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
|
|
|
@ -251,6 +251,12 @@ public interface IGenericClient extends IRestfulClient {
|
|||
@Override
|
||||
void registerInterceptor(IClientInterceptor theInterceptor);
|
||||
|
||||
/**
|
||||
* Search for resources matching a given set of criteria. Searching is a very powerful
|
||||
* feature in FHIR with many features for specifying exactly what should be seaerched for
|
||||
* and how it should be returned. See the <a href="http://www.hl7.org/fhir/search.html">specification on search</a>
|
||||
* for more information.
|
||||
*/
|
||||
IUntypedQuery search();
|
||||
|
||||
/**
|
||||
|
|
|
@ -37,6 +37,14 @@ public interface IQuery<T> extends IClientExecutable<IQuery<T>, T>, IBaseQuery<I
|
|||
|
||||
IQuery<T> limitTo(int theLimitTo);
|
||||
|
||||
/**
|
||||
* Match only resources where the resource has the given tag. This parameter corresponds to
|
||||
* the <code>_tag</code> URL parameter.
|
||||
* @param theSystem The tag code system, or <code>null</code> to match any code system (this may not be supported on all servers)
|
||||
* @param theCode The tag code. Must not be <code>null</code> or empty.
|
||||
*/
|
||||
IQuery<T> withTag(String theSystem, String theCode);
|
||||
|
||||
/**
|
||||
* Forces the query to perform the search using the given method (allowable methods are described in the
|
||||
* <a href="http://www.hl7.org/implement/standards/fhir/http.html#search">FHIR Specification Section 2.1.11</a>)
|
||||
|
|
|
@ -110,6 +110,7 @@ public class Constants {
|
|||
public static final String PARAM_SORT_ASC = "_sort:asc";
|
||||
public static final String PARAM_SORT_DESC = "_sort:desc";
|
||||
public static final String PARAM_TAGS = "_tags";
|
||||
public static final String PARAM_TAG = "_tag";
|
||||
public static final String PARAM_VALIDATE = "_validate";
|
||||
public static final String PARAMQUALIFIER_MISSING = ":missing";
|
||||
public static final String PARAMQUALIFIER_MISSING_FALSE = "false";
|
||||
|
|
|
@ -59,7 +59,6 @@ import org.apache.commons.lang3.StringUtils;
|
|||
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.omg.PortableInterceptor.InterceptorOperations;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Required;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
@ -86,6 +85,7 @@ import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamString;
|
|||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamToken;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceLink;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceTag;
|
||||
import ca.uhn.fhir.jpa.entity.TagDefinition;
|
||||
import ca.uhn.fhir.jpa.entity.TagTypeEnum;
|
||||
import ca.uhn.fhir.jpa.util.StopWatch;
|
||||
|
@ -293,6 +293,71 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
return new HashSet<Long>(q.getResultList());
|
||||
}
|
||||
|
||||
private Set<Long> addPredicateTag(Set<Long> thePids, List<List<? extends IQueryParameterType>> theList) {
|
||||
Set<Long> pids = thePids;
|
||||
if (theList == null || theList.isEmpty()) {
|
||||
return pids;
|
||||
}
|
||||
|
||||
for (List<? extends IQueryParameterType> nextAndParams : theList) {
|
||||
boolean haveTags = false;
|
||||
for (IQueryParameterType nextParamUncasted : nextAndParams) {
|
||||
TokenParam nextParam = (TokenParam) nextParamUncasted;
|
||||
if (isNotBlank(nextParam.getValue())) {
|
||||
haveTags = true;
|
||||
} else if (isNotBlank(nextParam.getSystem())) {
|
||||
throw new InvalidRequestException("Invalid _tag parameter (must supply a value/code and not just a system): " + nextParam.getValueAsQueryToken());
|
||||
}
|
||||
}
|
||||
if (!haveTags) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Long> cq = builder.createQuery(Long.class);
|
||||
Root<ResourceTag> from = cq.from(ResourceTag.class);
|
||||
cq.select(from.get("myResourceId").as(Long.class));
|
||||
|
||||
List<Predicate> andPredicates = new ArrayList<Predicate>();
|
||||
andPredicates.add(builder.equal(from.get("myResourceType"), myResourceName));
|
||||
|
||||
List<Predicate> orPredicates = new ArrayList<Predicate>();
|
||||
for (IQueryParameterType nextOrParams : nextAndParams) {
|
||||
TokenParam nextParam = (TokenParam) nextOrParams;
|
||||
|
||||
From<ResourceTag, TagDefinition> defJoin = from.join("myTag");
|
||||
Predicate codePrediate = builder.equal(defJoin.get("myCode"), nextParam.getValue());
|
||||
if (isBlank(nextParam.getValue())) {
|
||||
continue;
|
||||
}
|
||||
if (isNotBlank(nextParam.getSystem())) {
|
||||
Predicate systemPrediate = builder.equal(defJoin.get("mySystem"), nextParam.getSystem());
|
||||
orPredicates.add(builder.and(systemPrediate, codePrediate));
|
||||
} else {
|
||||
orPredicates.add(codePrediate);
|
||||
}
|
||||
|
||||
}
|
||||
if (orPredicates.isEmpty() == false) {
|
||||
andPredicates.add(builder.or(orPredicates.toArray(new Predicate[0])));
|
||||
}
|
||||
|
||||
Predicate masterCodePredicate = builder.and(andPredicates.toArray(new Predicate[0]));
|
||||
|
||||
if (pids.size() > 0) {
|
||||
Predicate inPids = (from.get("myResourceId").in(pids));
|
||||
cq.where(builder.and(masterCodePredicate, inPids));
|
||||
} else {
|
||||
cq.where(masterCodePredicate);
|
||||
}
|
||||
|
||||
TypedQuery<Long> q = myEntityManager.createQuery(cq);
|
||||
pids = new HashSet<Long>(q.getResultList());
|
||||
}
|
||||
|
||||
return pids;
|
||||
}
|
||||
|
||||
private boolean addPredicateMissingFalseIfPresent(CriteriaBuilder theBuilder, String theParamName, Root<? extends BaseResourceIndexedSearchParam> from, List<Predicate> codePredicates,
|
||||
IQueryParameterType nextOr) {
|
||||
boolean missingFalse = false;
|
||||
|
@ -635,11 +700,11 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
RuntimeResourceDefinition resDef = getContext().getResourceDefinition(ref.getResourceType());
|
||||
resourceTypes.add(resDef.getImplementingClass());
|
||||
}
|
||||
|
||||
|
||||
boolean foundChainMatch = false;
|
||||
for (Class<? extends IBaseResource> nextType : resourceTypes) {
|
||||
RuntimeResourceDefinition typeDef = getContext().getResourceDefinition(nextType);
|
||||
|
||||
|
||||
String chain = ref.getChain();
|
||||
String remainingChain = null;
|
||||
int chainDotIndex = chain.indexOf('.');
|
||||
|
@ -658,23 +723,23 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
ourLog.debug("Don't have a DAO for type {}", nextType.getSimpleName(), param);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
IQueryParameterType chainValue;
|
||||
if (remainingChain != null) {
|
||||
if (param.getParamType() != RestSearchParameterTypeEnum.REFERENCE) {
|
||||
ourLog.debug("Type {} parameter {} is not a reference, can not chain {}", new Object[] { nextType.getSimpleName(), chain, remainingChain });
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
chainValue = new ReferenceParam();
|
||||
chainValue.setValueAsQueryToken(null, resourceId);
|
||||
((ReferenceParam)chainValue).setChain(remainingChain);
|
||||
((ReferenceParam) chainValue).setChain(remainingChain);
|
||||
} else {
|
||||
chainValue = toParameterType(param, resourceId);
|
||||
}
|
||||
|
||||
|
||||
foundChainMatch = true;
|
||||
|
||||
|
||||
Set<Long> pids = dao.searchForIds(chain, chainValue);
|
||||
if (pids.isEmpty()) {
|
||||
continue;
|
||||
|
@ -684,7 +749,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
codePredicates.add(eq);
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (!foundChainMatch) {
|
||||
throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "invalidParameterChain", theParamName + '.' + ref.getChain()));
|
||||
}
|
||||
|
@ -894,7 +959,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
protected IBaseOperationOutcome createErrorOperationOutcome(String theMessage) {
|
||||
return createOperationOutcome(IssueSeverityEnum.ERROR.getCode(), theMessage);
|
||||
}
|
||||
|
||||
|
||||
protected IBaseOperationOutcome createInfoOperationOutcome(String theMessage) {
|
||||
return createOperationOutcome(IssueSeverityEnum.INFORMATION.getCode(), theMessage);
|
||||
}
|
||||
|
@ -1017,12 +1082,12 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
}
|
||||
|
||||
if (system != null && system.length() > ResourceIndexedSearchParamToken.MAX_LENGTH) {
|
||||
throw new InvalidRequestException("Parameter[" + theParamName + "] has system (" + system.length() + ") that is longer than maximum allowed (" + ResourceIndexedSearchParamToken.MAX_LENGTH
|
||||
+ "): " + system);
|
||||
throw new InvalidRequestException(
|
||||
"Parameter[" + theParamName + "] has system (" + system.length() + ") that is longer than maximum allowed (" + ResourceIndexedSearchParamToken.MAX_LENGTH + "): " + system);
|
||||
}
|
||||
if (code != null && code.length() > ResourceIndexedSearchParamToken.MAX_LENGTH) {
|
||||
throw new InvalidRequestException("Parameter[" + theParamName + "] has code (" + code.length() + ") that is longer than maximum allowed (" + ResourceIndexedSearchParamToken.MAX_LENGTH
|
||||
+ "): " + code);
|
||||
throw new InvalidRequestException(
|
||||
"Parameter[" + theParamName + "] has code (" + code.length() + ") that is longer than maximum allowed (" + ResourceIndexedSearchParamToken.MAX_LENGTH + "): " + code);
|
||||
}
|
||||
|
||||
ArrayList<Predicate> singleCodePredicates = (new ArrayList<Predicate>());
|
||||
|
@ -1096,13 +1161,13 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
}
|
||||
|
||||
From<?, ?> stringJoin = theFrom.join(joinAttrName, JoinType.INNER);
|
||||
|
||||
|
||||
if (param.getParamType() == RestSearchParameterTypeEnum.REFERENCE) {
|
||||
thePredicates.add(stringJoin.get("mySourcePath").as(String.class).in(param.getPathsSplit()));
|
||||
} else {
|
||||
thePredicates.add(theBuilder.equal(stringJoin.get("myParamName"), theSort.getParamName()));
|
||||
}
|
||||
|
||||
|
||||
// Predicate p = theBuilder.equal(stringJoin.get("myParamName"), theSort.getParamName());
|
||||
// Predicate pn = theBuilder.isNull(stringJoin.get("myParamName"));
|
||||
// thePredicates.add(theBuilder.or(p, pn));
|
||||
|
@ -1197,7 +1262,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
DaoMethodOutcome outcome = toMethodOutcome(entity, theResource).setCreated(true);
|
||||
|
||||
notifyWriteCompleted();
|
||||
|
||||
|
||||
String msg = getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "successfulCreate", outcome.getId(), w.getMillisAndRestart());
|
||||
outcome.setOperationOutcome(createInfoOperationOutcome(msg));
|
||||
|
||||
|
@ -1594,8 +1659,8 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
|
||||
if (entity == null) {
|
||||
if (theId.hasVersionIdPart()) {
|
||||
TypedQuery<ResourceHistoryTable> q = myEntityManager.createQuery(
|
||||
"SELECT t from ResourceHistoryTable t WHERE t.myResourceId = :RID AND t.myResourceType = :RTYP AND t.myResourceVersion = :RVER", ResourceHistoryTable.class);
|
||||
TypedQuery<ResourceHistoryTable> q = myEntityManager
|
||||
.createQuery("SELECT t from ResourceHistoryTable t WHERE t.myResourceId = :RID AND t.myResourceType = :RTYP AND t.myResourceVersion = :RVER", ResourceHistoryTable.class);
|
||||
q.setParameter("RID", pid);
|
||||
q.setParameter("RTYP", myResourceName);
|
||||
q.setParameter("RVER", Long.parseLong(theId.getVersionIdPart()));
|
||||
|
@ -1930,6 +1995,10 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
|
||||
pids = addPredicateLanguage(pids, nextParamEntry.getValue());
|
||||
|
||||
} else if (nextParamName.equals("_tag")) {
|
||||
|
||||
pids = addPredicateTag(pids, nextParamEntry.getValue());
|
||||
|
||||
} else {
|
||||
|
||||
RuntimeSearchParam nextParamDef = resourceDef.getSearchParam(nextParamName);
|
||||
|
@ -2136,7 +2205,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
ResourceTable savedEntity = updateEntity(theResource, entity, true, null, thePerformIndexing, true);
|
||||
|
||||
notifyWriteCompleted();
|
||||
|
||||
|
||||
DaoMethodOutcome outcome = toMethodOutcome(savedEntity, theResource).setCreated(false);
|
||||
|
||||
String msg = getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "successfulCreate", outcome.getId(), w.getMillisAndRestart());
|
||||
|
@ -2160,8 +2229,8 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
|
||||
private void validateResourceType(BaseHasResource entity) {
|
||||
if (!myResourceName.equals(entity.getResourceType())) {
|
||||
throw new ResourceNotFoundException("Resource with ID " + entity.getIdDt().getIdPart() + " exists but it is not of type " + myResourceName + ", found resource of type "
|
||||
+ entity.getResourceType());
|
||||
throw new ResourceNotFoundException(
|
||||
"Resource with ID " + entity.getIdDt().getIdPart() + " exists but it is not of type " + myResourceName + ", found resource of type " + entity.getResourceType());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,12 +44,12 @@ public class ResourceTag extends BaseTag {
|
|||
@JoinColumn(name = "RES_ID", referencedColumnName = "RES_ID")
|
||||
private ResourceTable myResource;
|
||||
|
||||
@Column(name = "RES_TYPE", length = ResourceTable.RESTYPE_LEN,nullable=false)
|
||||
@Column(name = "RES_TYPE", length = ResourceTable.RESTYPE_LEN, nullable = false)
|
||||
private String myResourceType;
|
||||
|
||||
@Column(name="RES_ID", insertable=false,updatable=false)
|
||||
@Column(name = "RES_ID", insertable = false, updatable = false)
|
||||
private Long myResourceId;
|
||||
|
||||
|
||||
public Long getResourceId() {
|
||||
return myResourceId;
|
||||
}
|
||||
|
|
|
@ -39,9 +39,7 @@ import ca.uhn.fhir.model.api.Tag;
|
|||
|
||||
//@formatter:on
|
||||
@Entity
|
||||
@Table(name = "HFJ_TAG_DEF", uniqueConstraints = {
|
||||
@UniqueConstraint(columnNames = { "TAG_TYPE", "TAG_SYSTEM", "TAG_CODE" })
|
||||
})
|
||||
@Table(name = "HFJ_TAG_DEF", uniqueConstraints = { @UniqueConstraint(columnNames = { "TAG_TYPE", "TAG_SYSTEM", "TAG_CODE" }) })
|
||||
//@formatter:off
|
||||
public class TagDefinition implements Serializable {
|
||||
|
||||
|
@ -89,6 +87,10 @@ public class TagDefinition implements Serializable {
|
|||
return myDisplay;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return myId;
|
||||
}
|
||||
|
||||
public String getSystem() {
|
||||
return mySystem;
|
||||
}
|
||||
|
|
|
@ -87,6 +87,7 @@ import ca.uhn.fhir.rest.param.NumberParam;
|
|||
import ca.uhn.fhir.rest.param.QuantityParam;
|
||||
import ca.uhn.fhir.rest.param.ReferenceParam;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import ca.uhn.fhir.rest.param.TokenAndListParam;
|
||||
import ca.uhn.fhir.rest.param.TokenOrListParam;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||
|
@ -1873,6 +1874,80 @@ public class FhirResourceDaoDstu2Test extends BaseJpaTest {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithTagParameter() {
|
||||
String methodName = "testSearchWithTagParameter";
|
||||
|
||||
IIdType tag1id;
|
||||
{
|
||||
Organization org = new Organization();
|
||||
org.getNameElement().setValue("FOO");
|
||||
TagList tagList = new TagList();
|
||||
tagList.addTag("urn:taglist", methodName + "1a");
|
||||
tagList.addTag("urn:taglist", methodName + "1b");
|
||||
ResourceMetadataKeyEnum.TAG_LIST.put(org, tagList);
|
||||
tag1id = ourOrganizationDao.create(org).getId().toUnqualifiedVersionless();
|
||||
}
|
||||
IIdType tag2id;
|
||||
{
|
||||
Organization org = new Organization();
|
||||
org.getNameElement().setValue("FOO");
|
||||
TagList tagList = new TagList();
|
||||
tagList.addTag("urn:taglist", methodName + "2a");
|
||||
tagList.addTag("urn:taglist", methodName + "2b");
|
||||
ResourceMetadataKeyEnum.TAG_LIST.put(org, tagList);
|
||||
tag2id = ourOrganizationDao.create(org).getId().toUnqualifiedVersionless();
|
||||
}
|
||||
|
||||
{
|
||||
// One tag
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.add("_tag", new TokenParam("urn:taglist", methodName + "1a"));
|
||||
List<IIdType> patients = toUnqualifiedVersionlessIds(ourOrganizationDao.search(params));
|
||||
assertThat(patients, containsInAnyOrder(tag1id));
|
||||
}
|
||||
{
|
||||
// Code only
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.add("_tag", new TokenParam(null, methodName + "1a"));
|
||||
List<IIdType> patients = toUnqualifiedVersionlessIds(ourOrganizationDao.search(params));
|
||||
assertThat(patients, containsInAnyOrder(tag1id));
|
||||
}
|
||||
{
|
||||
// Or tags
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
TokenOrListParam orListParam = new TokenOrListParam();
|
||||
orListParam.add(new TokenParam("urn:taglist", methodName + "1a"));
|
||||
orListParam.add(new TokenParam("urn:taglist", methodName + "2a"));
|
||||
params.add("_tag", orListParam);
|
||||
List<IIdType> patients = toUnqualifiedVersionlessIds(ourOrganizationDao.search(params));
|
||||
assertThat(patients, containsInAnyOrder(tag1id, tag2id));
|
||||
}
|
||||
// TODO: get multiple/AND working
|
||||
{
|
||||
// And tags
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
TokenAndListParam andListParam = new TokenAndListParam();
|
||||
andListParam.addValue(new TokenOrListParam("urn:taglist", methodName + "1a"));
|
||||
andListParam.addValue(new TokenOrListParam("urn:taglist", methodName + "2a"));
|
||||
params.add("_tag", andListParam);
|
||||
List<IIdType> patients = toUnqualifiedVersionlessIds(ourOrganizationDao.search(params));
|
||||
assertEquals(0, patients.size());
|
||||
}
|
||||
|
||||
{
|
||||
// And tags
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
TokenAndListParam andListParam = new TokenAndListParam();
|
||||
andListParam.addValue(new TokenOrListParam("urn:taglist", methodName + "1a"));
|
||||
andListParam.addValue(new TokenOrListParam("urn:taglist", methodName + "1b"));
|
||||
params.add("_tag", andListParam);
|
||||
List<IIdType> patients = toUnqualifiedVersionlessIds(ourOrganizationDao.search(params));
|
||||
assertThat(patients, containsInAnyOrder(tag1id));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithIncludes() {
|
||||
IIdType parentOrgId;
|
||||
|
|
|
@ -693,6 +693,34 @@ public class GenericClientTest {
|
|||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Test
|
||||
public void testSearchByTag() throws Exception {
|
||||
|
||||
String msg = getPatientFeedWithOneResult();
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
//@formatter:off
|
||||
Bundle response = client.search()
|
||||
.forResource(Patient.class)
|
||||
.withTag("urn:foo", "123")
|
||||
.withTag("urn:bar", "456")
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
assertEquals(
|
||||
"http://example.com/fhir/Patient?_tag=urn%3Afoo%7C123&_tag=urn%3Abar%7C456",
|
||||
capt.getValue().getURI().toString());
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Test
|
||||
public void testSearchWithReverseInclude() throws Exception {
|
||||
|
|
|
@ -49,6 +49,11 @@ public class ${className}ResourceProvider extends
|
|||
@Description(shortDefinition="The resource language")
|
||||
@OptionalParam(name="_language")
|
||||
StringParam theResourceLanguage,
|
||||
|
||||
@Description(shortDefinition="Search for resources which have the given tag")
|
||||
@OptionalParam(name="_tag")
|
||||
TokenAndListParam theSearchForTag,
|
||||
|
||||
#foreach ( $param in $searchParams ) #{if}(true) #{end}
|
||||
|
||||
@Description(shortDefinition="${param.description}")
|
||||
|
@ -113,10 +118,11 @@ public class ${className}ResourceProvider extends
|
|||
startRequest(theServletRequest);
|
||||
try {
|
||||
SearchParameterMap paramMap = new SearchParameterMap();
|
||||
paramMap.add("_id", theId);
|
||||
paramMap.add("_language", theResourceLanguage);
|
||||
paramMap.add("_id", theId);
|
||||
paramMap.add("_language", theResourceLanguage);
|
||||
paramMap.add("_tag", theSearchForTag);
|
||||
#foreach ( $param in $searchParams )
|
||||
paramMap.add("${param.name}", the${param.nameCapitalized});
|
||||
paramMap.add("${param.name}", the${param.nameCapitalized});
|
||||
#end
|
||||
#if ( $version != 'dstu' )
|
||||
paramMap.setRevIncludes(theRevIncludes);
|
||||
|
|
|
@ -64,6 +64,9 @@
|
|||
package lists are up to date. Thanks to GitHub user
|
||||
Brian S. Corbin (@corbinbs) for thr contribution!
|
||||
</action>
|
||||
<action type="add">
|
||||
JPA server and generic client now both support the _tag search parameter
|
||||
</action>
|
||||
</release>
|
||||
<release version="1.1" date="2015-07-13">
|
||||
<action type="add">
|
||||
|
|
|
@ -178,7 +178,7 @@
|
|||
<h4>Search - Other Query Options</h4>
|
||||
<p>
|
||||
The fluent search also has methods for sorting, limiting, specifying
|
||||
JSON encoding, _include, _revinclude, _lastUpdated, etc.
|
||||
JSON encoding, _include, _revinclude, _lastUpdated, _tag, etc.
|
||||
</p>
|
||||
<macro name="snippet">
|
||||
<param name="id" value="searchAdv" />
|
||||
|
|
Loading…
Reference in New Issue