Generic client now allows search by URL
This commit is contained in:
parent
43aad1eb98
commit
80575b5380
|
@ -264,6 +264,19 @@ public class GenericClientExample {
|
|||
.execute();
|
||||
// END SNIPPET: searchCompartment
|
||||
|
||||
// START SNIPPET: searchUrl
|
||||
String searchUrl = "http://example.com/base/Patient?identifier=foo";
|
||||
|
||||
// Search URL can also be a relative URL in which case the client's base
|
||||
// URL will be added to it
|
||||
searchUrl = "Patient?identifier=foo";
|
||||
|
||||
response = client.search()
|
||||
.byUrl(searchUrl)
|
||||
.returnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class)
|
||||
.execute();
|
||||
// END SNIPPET: searchUrl
|
||||
|
||||
// START SNIPPET: searchSubsetSummary
|
||||
response = client.search()
|
||||
.forResource(Patient.class)
|
||||
|
|
|
@ -19,7 +19,8 @@ package ca.uhn.fhir.rest.client;
|
|||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
|
@ -144,6 +145,7 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
|||
import ca.uhn.fhir.rest.server.exceptions.NotModifiedException;
|
||||
import ca.uhn.fhir.util.ICallable;
|
||||
import ca.uhn.fhir.util.ParametersUtil;
|
||||
import ca.uhn.fhir.util.UrlUtil;
|
||||
|
||||
/**
|
||||
* @author James Agnew
|
||||
|
@ -724,7 +726,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
|
||||
@Override
|
||||
public ICreateTyped conditionalByUrl(String theSearchUrl) {
|
||||
mySearchUrl = theSearchUrl;
|
||||
mySearchUrl = validateAndEscapeConditionalUrl(theSearchUrl);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -899,8 +901,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
|
||||
@Override
|
||||
public IDeleteTyped resourceConditionalByUrl(String theSearchUrl) {
|
||||
Validate.notBlank(theSearchUrl, "theSearchUrl can not be blank/null");
|
||||
mySearchUrl = theSearchUrl;
|
||||
mySearchUrl = validateAndEscapeConditionalUrl(theSearchUrl);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -1473,12 +1474,12 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
Validate.notNull(theParameterType, "theParameterType must not be null");
|
||||
Validate.notEmpty(theName, "theName must not be null");
|
||||
Validate.notNull(theValue, "theValue must not be null");
|
||||
|
||||
|
||||
myParametersDef = myContext.getResourceDefinition(theParameterType);
|
||||
myParameters = (IBaseParameters) myParametersDef.newInstance();
|
||||
|
||||
|
||||
addParam(theName, theValue);
|
||||
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -1486,14 +1487,14 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
private void addParam(String theName, IBase theValue) {
|
||||
BaseRuntimeChildDefinition parameterChild = myParametersDef.getChildByName("parameter");
|
||||
BaseRuntimeElementCompositeDefinition<?> parameterElem = (BaseRuntimeElementCompositeDefinition<?>) parameterChild.getChildByName("parameter");
|
||||
|
||||
|
||||
IBase parameter = parameterElem.newInstance();
|
||||
parameterChild.getMutator().addValue(myParameters, parameter);
|
||||
|
||||
|
||||
IPrimitiveType<String> name = (IPrimitiveType<String>) myContext.getElementDefinition("string").newInstance();
|
||||
name.setValue(theName);
|
||||
parameterElem.getChildByName("name").getMutator().setValue(parameter, name);
|
||||
|
||||
|
||||
if (theValue instanceof IBaseDatatype) {
|
||||
String childElementName = "value" + StringUtils.capitalize(myContext.getElementDefinition(theValue.getClass()).getName());
|
||||
parameterElem.getChildByName(childElementName).getMutator().setValue(parameter, theValue);
|
||||
|
@ -1782,10 +1783,12 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
private List<TokenParam> mySecurity = new ArrayList<TokenParam>();
|
||||
private List<SortInternal> mySort = new ArrayList<SortInternal>();
|
||||
private List<TokenParam> myTags = new ArrayList<TokenParam>();
|
||||
private String mySearchUrl;
|
||||
|
||||
public SearchInternal() {
|
||||
myResourceType = null;
|
||||
myResourceName = null;
|
||||
mySearchUrl = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1857,7 +1860,12 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
|
||||
IdDt resourceId = myResourceId != null ? new IdDt(myResourceId) : null;
|
||||
|
||||
BaseHttpClientInvocation invocation = SearchMethodBinding.createSearchInvocation(myContext, myResourceName, params, resourceId, myCompartmentName, mySearchStyle);
|
||||
BaseHttpClientInvocation invocation;
|
||||
if (mySearchUrl != null) {
|
||||
invocation = SearchMethodBinding.createSearchInvocation(mySearchUrl, params);
|
||||
} else {
|
||||
invocation = SearchMethodBinding.createSearchInvocation(myContext, myResourceName, params, resourceId, myCompartmentName, mySearchStyle);
|
||||
}
|
||||
|
||||
return invoke(params, binding, invocation);
|
||||
|
||||
|
@ -1975,6 +1983,34 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IQuery byUrl(String theSearchUrl) {
|
||||
Validate.notBlank(theSearchUrl, "theSearchUrl must not be blank/null");
|
||||
|
||||
if (theSearchUrl.startsWith("http://") || theSearchUrl.startsWith("https://")) {
|
||||
mySearchUrl = theSearchUrl;
|
||||
int qIndex = mySearchUrl.indexOf('?');
|
||||
if (qIndex != -1) {
|
||||
mySearchUrl = mySearchUrl.substring(0, qIndex) + validateAndEscapeConditionalUrl(mySearchUrl.substring(qIndex));
|
||||
}
|
||||
} else {
|
||||
String searchUrl = theSearchUrl;
|
||||
if (searchUrl.startsWith("/")) {
|
||||
searchUrl = searchUrl.substring(1);
|
||||
}
|
||||
if (!searchUrl.matches("[a-zA-Z]+($|\\?.*)")) {
|
||||
throw new IllegalArgumentException("Search URL must be either a complete URL starting with http: or https:, or a relative FHIR URL in the form [ResourceType]?[Params]");
|
||||
}
|
||||
int qIndex = searchUrl.indexOf('?');
|
||||
if (qIndex == -1) {
|
||||
mySearchUrl = getUrlBase() + '/' + searchUrl;
|
||||
} else {
|
||||
mySearchUrl = getUrlBase() + '/' + validateAndEscapeConditionalUrl(searchUrl);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
|
@ -2154,7 +2190,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
|
||||
@Override
|
||||
public IUpdateTyped conditionalByUrl(String theSearchUrl) {
|
||||
mySearchUrl = theSearchUrl;
|
||||
mySearchUrl = validateAndEscapeConditionalUrl(theSearchUrl);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -2290,4 +2326,34 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
|
||||
}
|
||||
|
||||
private static String validateAndEscapeConditionalUrl(String theSearchUrl) {
|
||||
Validate.notBlank(theSearchUrl, "Conditional URL can not be blank/null");
|
||||
StringBuilder b = new StringBuilder();
|
||||
boolean haveHadQuestionMark = false;
|
||||
for (int i = 0; i < theSearchUrl.length(); i++) {
|
||||
char nextChar = theSearchUrl.charAt(i);
|
||||
if (!haveHadQuestionMark) {
|
||||
if (nextChar == '?') {
|
||||
haveHadQuestionMark = true;
|
||||
} else if (!Character.isLetter(nextChar)) {
|
||||
throw new IllegalArgumentException("Conditional URL must be in the format \"[ResourceType]?[Params]\" and must not have a base URL - Found: " + theSearchUrl);
|
||||
}
|
||||
b.append(nextChar);
|
||||
} else {
|
||||
switch (nextChar) {
|
||||
case '|':
|
||||
case '?':
|
||||
case '$':
|
||||
case ':':
|
||||
b.append(UrlUtil.escape(Character.toString(nextChar)));
|
||||
break;
|
||||
default:
|
||||
b.append(nextChar);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,7 +24,6 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
|
|||
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
|
||||
|
||||
public interface IUntypedQuery {
|
||||
|
||||
IQuery<Bundle> forAllResources();
|
||||
|
@ -32,5 +31,15 @@ public interface IUntypedQuery {
|
|||
IQuery<Bundle> forResource(String theResourceName);
|
||||
|
||||
IQuery<Bundle> forResource(Class<? extends IBaseResource> theClass);
|
||||
|
||||
|
||||
/**
|
||||
* Perform a search directly by URL. It is usually better to construct the URL using the {@link #forAllResources()}, {@link #forResource(Class)} etc, but sometimes it is useful to simply search by
|
||||
* entering a search URL directly.
|
||||
*
|
||||
* @param theSearchUrl
|
||||
* The URL to search for. Note that this URL may be complete (e.g. "http://example.com/base/Patient?name=foo") in which case the client's base URL will be ignored. Or it can be relative
|
||||
* (e.g. "Patient?name=foo") in which case the client's base URL will be used.
|
||||
*/
|
||||
IQuery<Bundle> byUrl(String theSearchUrl);
|
||||
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ import ca.uhn.fhir.rest.server.Constants;
|
|||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.IVersionSpecificBundleFactory;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.util.UrlUtil;
|
||||
|
||||
/**
|
||||
* @author James Agnew
|
||||
|
|
|
@ -477,4 +477,8 @@ public class SearchMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
|
||||
}
|
||||
|
||||
public static BaseHttpClientInvocation createSearchInvocation(String theSearchUrl, Map<String, List<String>> theParams) {
|
||||
return new HttpGetClientInvocation(theParams, theSearchUrl);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-cli</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
|
|
|
@ -16,6 +16,11 @@
|
|||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
|
||||
|
|
|
@ -93,11 +93,10 @@
|
|||
</dependency>
|
||||
|
||||
<!-- FHIR RI is pulled in for UCUM support, but we don't want any of its dependencies. -->
|
||||
<!-- <dependency> <groupId>me.fhir</groupId> <artifactId>fhir-dstu1</artifactId> <version>0.0.81.2489</version> <exclusions> <exclusion> <artifactId>Saxon-HE</artifactId>
|
||||
<groupId>net.sf.saxon</groupId> </exclusion> <exclusion> <artifactId>commons-discovery</artifactId> <groupId>commons-discovery</groupId> </exclusion> <exclusion>
|
||||
<artifactId>commons-codec</artifactId> <groupId>commons-codec</groupId> </exclusion> <exclusion> <artifactId>commons-logging</artifactId> <groupId>commons-logging</groupId>
|
||||
</exclusion> <exclusion> <artifactId>xpp3</artifactId> <groupId>xpp3</groupId> </exclusion> <exclusion> <artifactId>junit</artifactId> <groupId>junit</groupId> </exclusion>
|
||||
<exclusion> <artifactId>jdom</artifactId> <groupId>org.jdom</groupId> </exclusion> <exclusion> <artifactId>gson</artifactId> <groupId>com.google.code.gson</groupId>
|
||||
<!-- <dependency> <groupId>me.fhir</groupId> <artifactId>fhir-dstu1</artifactId> <version>0.0.81.2489</version> <exclusions> <exclusion> <artifactId>Saxon-HE</artifactId> <groupId>net.sf.saxon</groupId>
|
||||
</exclusion> <exclusion> <artifactId>commons-discovery</artifactId> <groupId>commons-discovery</groupId> </exclusion> <exclusion> <artifactId>commons-codec</artifactId> <groupId>commons-codec</groupId>
|
||||
</exclusion> <exclusion> <artifactId>commons-logging</artifactId> <groupId>commons-logging</groupId> </exclusion> <exclusion> <artifactId>xpp3</artifactId> <groupId>xpp3</groupId> </exclusion> <exclusion>
|
||||
<artifactId>junit</artifactId> <groupId>junit</groupId> </exclusion> <exclusion> <artifactId>jdom</artifactId> <groupId>org.jdom</groupId> </exclusion> <exclusion> <artifactId>gson</artifactId> <groupId>com.google.code.gson</groupId>
|
||||
</exclusion> </exclusions> </dependency> -->
|
||||
|
||||
|
||||
|
@ -230,7 +229,12 @@
|
|||
<groupId>org.glassfish</groupId>
|
||||
<artifactId>javax.el</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-search-orm</artifactId>
|
||||
<version>5.5.0.Final</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Misc -->
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
|
@ -400,8 +404,8 @@
|
|||
<target>SCRIPT</target>
|
||||
<skip>${skip-hib4}</skip>
|
||||
</configuration>
|
||||
<!-- This needs to be uncommented in order for this plugin to work with Hibernate 4.3+ (as of hibernate4-maven-plugin version 1.0.5) <dependencies> <dependency>
|
||||
<groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>${hibernate_version}</version> </dependency> </dependencies> -->
|
||||
<!-- This needs to be uncommented in order for this plugin to work with Hibernate 4.3+ (as of hibernate4-maven-plugin version 1.0.5) <dependencies> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId>
|
||||
<version>${hibernate_version}</version> </dependency> </dependencies> -->
|
||||
<executions>
|
||||
<execution>
|
||||
<id>o10g</id>
|
||||
|
|
|
@ -35,6 +35,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.persistence.EntityManager;
|
||||
|
@ -75,6 +76,7 @@ import ca.uhn.fhir.context.RuntimeChildResourceDefinition;
|
|||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
import ca.uhn.fhir.jpa.dao.SearchParameterMap.EverythingModeEnum;
|
||||
import ca.uhn.fhir.jpa.dao.data.ISearchResultDao;
|
||||
import ca.uhn.fhir.jpa.entity.BaseHasResource;
|
||||
import ca.uhn.fhir.jpa.entity.BaseResourceIndexedSearchParam;
|
||||
import ca.uhn.fhir.jpa.entity.BaseTag;
|
||||
|
@ -88,6 +90,8 @@ import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamUri;
|
|||
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.Search;
|
||||
import ca.uhn.fhir.jpa.entity.SearchResult;
|
||||
import ca.uhn.fhir.jpa.entity.TagDefinition;
|
||||
import ca.uhn.fhir.jpa.entity.TagTypeEnum;
|
||||
import ca.uhn.fhir.jpa.util.StopWatch;
|
||||
|
@ -157,6 +161,9 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
private Class<T> myResourceType;
|
||||
private String mySecondaryPrimaryKeyParamName;
|
||||
|
||||
@Autowired
|
||||
private ISearchResultDao mySearchResultDao;
|
||||
|
||||
private Set<Long> addPredicateComposite(RuntimeSearchParam theParamDef, Set<Long> thePids, List<? extends IQueryParameterType> theNextAnd) {
|
||||
// TODO: fail if missing is set for a composite query
|
||||
|
||||
|
@ -625,9 +632,8 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
if (params instanceof ReferenceParam) {
|
||||
ReferenceParam ref = (ReferenceParam) params;
|
||||
|
||||
String resourceId = ref.getValueAsQueryToken();
|
||||
|
||||
if (isBlank(ref.getChain())) {
|
||||
String resourceId = ref.getValueAsQueryToken();
|
||||
if (resourceId.contains("/")) {
|
||||
IIdType dt = new IdDt(resourceId);
|
||||
resourceId = dt.getIdPart();
|
||||
|
@ -646,13 +652,17 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
throw new ConfigurationException("Property " + paramPath + " of type " + myResourceName + " is not a resource: " + def.getClass());
|
||||
}
|
||||
List<Class<? extends IBaseResource>> resourceTypes;
|
||||
if (isBlank(ref.getResourceType())) {
|
||||
|
||||
String resourceId;
|
||||
if (!ref.getValue().matches("[a-zA-Z]+\\/.*")) {
|
||||
RuntimeChildResourceDefinition resDef = (RuntimeChildResourceDefinition) def;
|
||||
resourceTypes = resDef.getResourceTypes();
|
||||
resourceId = ref.getValue();
|
||||
} else {
|
||||
resourceTypes = new ArrayList<Class<? extends IBaseResource>>();
|
||||
RuntimeResourceDefinition resDef = getContext().getResourceDefinition(ref.getResourceType());
|
||||
resourceTypes.add(resDef.getImplementingClass());
|
||||
resourceId = ref.getIdPart();
|
||||
}
|
||||
|
||||
boolean foundChainMatch = false;
|
||||
|
@ -1348,11 +1358,20 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
|
||||
@Override
|
||||
public DaoMethodOutcome deleteByUrl(String theUrl) {
|
||||
return deleteByUrl(theUrl, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DaoMethodOutcome deleteByUrl(String theUrl, boolean theInTransaction) {
|
||||
StopWatch w = new StopWatch();
|
||||
|
||||
Set<Long> resource = processMatchUrl(theUrl, myResourceType);
|
||||
if (resource.isEmpty()) {
|
||||
throw new ResourceNotFoundException(getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "unableToDeleteNotFound", theUrl));
|
||||
if (!theInTransaction) {
|
||||
throw new ResourceNotFoundException(getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "unableToDeleteNotFound", theUrl));
|
||||
} else {
|
||||
return new DaoMethodOutcome();
|
||||
}
|
||||
} else if (resource.size() > 1) {
|
||||
if (myDaoConfig.isAllowMultipleDelete() == false) {
|
||||
throw new PreconditionFailedException(getContext().getLocalizer().getMessage(BaseHapiFhirDao.class, "transactionOperationWithMultipleMatchFailure", "DELETE", theUrl, resource.size()));
|
||||
|
@ -1640,6 +1659,46 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBundleProvider everything(IIdType theId) {
|
||||
Search search = new Search();
|
||||
search.setUuid(UUID.randomUUID().toString());
|
||||
search.setCreated(new Date());
|
||||
myEntityManager.persist(search);
|
||||
|
||||
List<SearchResult> results = new ArrayList<SearchResult>();
|
||||
if (theId != null) {
|
||||
Long pid = translateForcedIdToPid(theId);
|
||||
ResourceTable entity = myEntityManager.find(ResourceTable.class, pid);
|
||||
validateGivenIdIsAppropriateToRetrieveResource(theId, entity);
|
||||
SearchResult res = new SearchResult(search);
|
||||
res.setResourcePid(pid);
|
||||
results.add(res);
|
||||
} else {
|
||||
TypedQuery<Tuple> query = createSearchAllByTypeQuery();
|
||||
for (Tuple next : query.getResultList()) {
|
||||
SearchResult res = new SearchResult(search);
|
||||
res.setResourcePid(next.get(0, Long.class));
|
||||
results.add(res);
|
||||
}
|
||||
}
|
||||
|
||||
mySearchResultDao.save(results);
|
||||
mySearchResultDao.flush();
|
||||
|
||||
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Long> cq = builder.createQuery(Long.class);
|
||||
// cq.
|
||||
Subquery<Long> subQ = cq.subquery(Long.class);
|
||||
Root<ResourceLink> subQfrom = subQ.from(ResourceLink.class);
|
||||
subQ.select(subQfrom.get("mySourceResourceId").as(Long.class));
|
||||
// subQ.where(builder.in(subQfrom.get("myTargetResourceId"), y));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* THIS SHOULD RETURN HASHSET and not jsut Set because we add to it later (so it can't be Collections.emptySet())
|
||||
*/
|
||||
|
@ -1650,15 +1709,20 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
if (theRevIncludes == null || theRevIncludes.isEmpty()) {
|
||||
return new HashSet<Long>();
|
||||
}
|
||||
String fieldName = theReverseMode ? "myTargetResourcePid" : "mySourceResourcePid";
|
||||
String searchFieldName = theReverseMode ? "myTargetResourcePid" : "mySourceResourcePid";
|
||||
|
||||
Collection<Long> nextRoundMatches = theMatches;
|
||||
HashSet<Long> allAdded = new HashSet<Long>();
|
||||
HashSet<Long> original = new HashSet<Long>(theMatches);
|
||||
ArrayList<Include> includes = new ArrayList<Include>(theRevIncludes);
|
||||
|
||||
int roundCounts = 0;
|
||||
StopWatch w = new StopWatch();
|
||||
|
||||
boolean addedSomeThisRound;
|
||||
do {
|
||||
roundCounts++;
|
||||
|
||||
HashSet<Long> pidsToInclude = new HashSet<Long>();
|
||||
Set<Long> nextRoundOmit = new HashSet<Long>();
|
||||
|
||||
|
@ -1671,13 +1735,13 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
boolean matchAll = "*".equals(nextInclude.getValue());
|
||||
if (matchAll) {
|
||||
String sql;
|
||||
sql = "SELECT r FROM ResourceLink r WHERE r." + fieldName + " IN (:target_pids)";
|
||||
sql = "SELECT r FROM ResourceLink r WHERE r." + searchFieldName + " IN (:target_pids)";
|
||||
TypedQuery<ResourceLink> q = myEntityManager.createQuery(sql, ResourceLink.class);
|
||||
q.setParameter("target_pids", nextRoundMatches);
|
||||
List<ResourceLink> results = q.getResultList();
|
||||
for (ResourceLink resourceLink : results) {
|
||||
if (theReverseMode) {
|
||||
if (theEverythingModeEnum == EverythingModeEnum.ENCOUNTER) {
|
||||
if (theEverythingModeEnum.isEncounter()) {
|
||||
if (resourceLink.getSourcePath().equals("Encounter.subject") || resourceLink.getSourcePath().equals("Encounter.patient")) {
|
||||
nextRoundOmit.add(resourceLink.getSourceResourcePid());
|
||||
}
|
||||
|
@ -1715,7 +1779,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
}
|
||||
|
||||
for (String nextPath : paths) {
|
||||
String sql = "SELECT r FROM ResourceLink r WHERE r.mySourcePath = :src_path AND r." + fieldName + " IN (:target_pids)";
|
||||
String sql = "SELECT r FROM ResourceLink r WHERE r.mySourcePath = :src_path AND r." + searchFieldName + " IN (:target_pids)";
|
||||
TypedQuery<ResourceLink> q = myEntityManager.createQuery(sql, ResourceLink.class);
|
||||
q.setParameter("src_path", nextPath);
|
||||
q.setParameter("target_pids", nextRoundMatches);
|
||||
|
@ -1743,6 +1807,10 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
nextRoundMatches = pidsToInclude;
|
||||
} while (includes.size() > 0 && nextRoundMatches.size() > 0 && addedSomeThisRound);
|
||||
|
||||
ourLog.info("Loaded {} {} in {} rounds and {} ms", new Object[] {
|
||||
allAdded.size(), theReverseMode ? "_revincludes" : "_includes", roundCounts, w.getMillisAndRestart()
|
||||
});
|
||||
|
||||
return allAdded;
|
||||
}
|
||||
|
||||
|
@ -2038,15 +2106,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
Set<Long> loadPids;
|
||||
if (theParams.isEmpty()) {
|
||||
loadPids = new HashSet<Long>();
|
||||
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Tuple> cq = builder.createTupleQuery();
|
||||
Root<ResourceTable> from = cq.from(ResourceTable.class);
|
||||
cq.multiselect(from.get("myId").as(Long.class));
|
||||
Predicate typeEquals = builder.equal(from.get("myResourceType"), myResourceName);
|
||||
Predicate notDeleted = builder.isNull(from.get("myDeleted"));
|
||||
cq.where(builder.and(typeEquals, notDeleted));
|
||||
|
||||
TypedQuery<Tuple> query = myEntityManager.createQuery(cq);
|
||||
TypedQuery<Tuple> query = createSearchAllByTypeQuery();
|
||||
for (Tuple next : query.getResultList()) {
|
||||
loadPids.add(next.get(0, Long.class));
|
||||
}
|
||||
|
@ -2163,6 +2223,19 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
|
|||
return retVal;
|
||||
}
|
||||
|
||||
private TypedQuery<Tuple> createSearchAllByTypeQuery() {
|
||||
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Tuple> cq = builder.createTupleQuery();
|
||||
Root<ResourceTable> from = cq.from(ResourceTable.class);
|
||||
cq.multiselect(from.get("myId").as(Long.class));
|
||||
Predicate typeEquals = builder.equal(from.get("myResourceType"), myResourceName);
|
||||
Predicate notDeleted = builder.isNull(from.get("myDeleted"));
|
||||
cq.where(builder.and(typeEquals, notDeleted));
|
||||
|
||||
TypedQuery<Tuple> query = myEntityManager.createQuery(cq);
|
||||
return query;
|
||||
}
|
||||
|
||||
private List<Long> processSort(final SearchParameterMap theParams, Set<Long> theLoadPids) {
|
||||
final List<Long> pids;
|
||||
Set<Long> loadPids = theLoadPids;
|
||||
|
|
|
@ -45,7 +45,7 @@ public class FhirResourceDaoEncounterDstu2 extends FhirResourceDaoDstu2<Encounte
|
|||
|
||||
paramMap.setRevIncludes(Collections.singleton(IResource.INCLUDE_ALL.asRecursive()));
|
||||
paramMap.setIncludes(Collections.singleton(IResource.INCLUDE_ALL.asRecursive()));
|
||||
paramMap.setEverythingMode(EverythingModeEnum.ENCOUNTER);
|
||||
paramMap.setEverythingMode(theId != null ? EverythingModeEnum.ENCOUNTER_INSTANCE : EverythingModeEnum.ENCOUNTER_TYPE);
|
||||
paramMap.setSort(theSort);
|
||||
paramMap.setLastUpdated(theLastUpdated);
|
||||
if (theId != null) {
|
||||
|
|
|
@ -45,7 +45,7 @@ public class FhirResourceDaoPatientDstu2 extends FhirResourceDaoDstu2<Patient>im
|
|||
|
||||
paramMap.setRevIncludes(Collections.singleton(IResource.INCLUDE_ALL.asRecursive()));
|
||||
paramMap.setIncludes(Collections.singleton(IResource.INCLUDE_ALL.asRecursive()));
|
||||
paramMap.setEverythingMode(EverythingModeEnum.PATIENT);
|
||||
paramMap.setEverythingMode(theId != null ? EverythingModeEnum.PATIENT_INSTANCE : EverythingModeEnum.PATIENT_TYPE);
|
||||
paramMap.setSort(theSort);
|
||||
paramMap.setLastUpdated(theLastUpdated);
|
||||
if (theId != null) {
|
||||
|
|
|
@ -38,6 +38,7 @@ import org.springframework.data.domain.Page;
|
|||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
@ -92,7 +93,7 @@ public class FhirResourceDaoSubscriptionDstu2 extends FhirResourceDaoDstu2<Subsc
|
|||
@Scheduled(fixedDelay = 10 * DateUtils.MILLIS_PER_SECOND)
|
||||
@Transactional(propagation = Propagation.NOT_SUPPORTED)
|
||||
@Override
|
||||
public void pollForNewUndeliveredResources() {
|
||||
public synchronized void pollForNewUndeliveredResources() {
|
||||
if (getConfig().isSubscriptionEnabled() == false) {
|
||||
return;
|
||||
}
|
||||
|
@ -106,7 +107,7 @@ public class FhirResourceDaoSubscriptionDstu2 extends FhirResourceDaoDstu2<Subsc
|
|||
List<SubscriptionTable> subscriptions = q.getResultList();
|
||||
|
||||
TransactionTemplate txTemplate = new TransactionTemplate(myTxManager);
|
||||
txTemplate.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRES_NEW);
|
||||
txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
|
||||
for (final SubscriptionTable nextSubscriptionTable : subscriptions) {
|
||||
txTemplate.execute(new TransactionCallback<Void>() {
|
||||
@Override
|
||||
|
@ -253,7 +254,7 @@ public class FhirResourceDaoSubscriptionDstu2 extends FhirResourceDaoDstu2<Subsc
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<IBaseResource> getUndeliveredResourcesAndPurge(Long theSubscriptionPid) {
|
||||
public synchronized List<IBaseResource> getUndeliveredResourcesAndPurge(Long theSubscriptionPid) {
|
||||
List<IBaseResource> retVal = new ArrayList<IBaseResource>();
|
||||
Page<SubscriptionFlaggedResource> flaggedResources = mySubscriptionFlaggedResourceDataDao.findAllBySubscriptionId(theSubscriptionPid, new PageRequest(0, 100));
|
||||
for (SubscriptionFlaggedResource nextFlaggedResource : flaggedResources) {
|
||||
|
@ -295,7 +296,7 @@ public class FhirResourceDaoSubscriptionDstu2 extends FhirResourceDaoDstu2<Subsc
|
|||
ourLog.info("Deleting inactive subscription {} - Created {}, last client poll {}",
|
||||
new Object[] { subscriptionId.toUnqualified(), subscriptionTable.getCreated(), subscriptionTable.getLastClientPoll() });
|
||||
TransactionTemplate txTemplate = new TransactionTemplate(myTxManager);
|
||||
txTemplate.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRES_NEW);
|
||||
txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
|
||||
txTemplate.execute(new TransactionCallback<Void>() {
|
||||
@Override
|
||||
public Void doInTransaction(TransactionStatus theStatus) {
|
||||
|
|
|
@ -282,7 +282,7 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle> {
|
|||
if (parts.getResourceId() != null) {
|
||||
dao.delete(new IdDt(parts.getResourceType(), parts.getResourceId()));
|
||||
} else {
|
||||
dao.deleteByUrl(parts.getResourceType() + '?' + parts.getParams());
|
||||
dao.deleteByUrl(parts.getResourceType() + '?' + parts.getParams(), true);
|
||||
}
|
||||
|
||||
newEntry.getResponse().setStatus(toStatusString(Constants.STATUS_HTTP_204_NO_CONTENT));
|
||||
|
|
|
@ -139,4 +139,14 @@ public interface IFhirResourceDao<T extends IBaseResource> extends IDao {
|
|||
*/
|
||||
MethodOutcome validate(T theResource, IIdType theId, String theRawResource, EncodingEnum theEncoding, ValidationModeEnum theMode, String theProfile);
|
||||
|
||||
/**
|
||||
* @param theTransaction Is this being called in a bundle? If so, don't throw an exception if no matches
|
||||
*/
|
||||
DaoMethodOutcome deleteByUrl(String theUrl, boolean theTransaction);
|
||||
|
||||
/**
|
||||
* Invoke the everything operation
|
||||
*/
|
||||
IBundleProvider everything(IIdType theId);
|
||||
|
||||
}
|
||||
|
|
|
@ -165,7 +165,36 @@ public class SearchParameterMap extends LinkedHashMap<String, List<List<? extend
|
|||
}
|
||||
|
||||
public enum EverythingModeEnum {
|
||||
PATIENT, ENCOUNTER
|
||||
//@formatter:off
|
||||
PATIENT_TYPE(true, false, false),
|
||||
PATIENT_INSTANCE(true, false, true),
|
||||
ENCOUNTER_TYPE(false, true, false),
|
||||
ENCOUNTER_INSTANCE(false, true, true);
|
||||
//@formatter:on
|
||||
|
||||
private final boolean myPatient;
|
||||
|
||||
public boolean isPatient() {
|
||||
return myPatient;
|
||||
}
|
||||
|
||||
public boolean isEncounter() {
|
||||
return myEncounter;
|
||||
}
|
||||
|
||||
public boolean isInstance() {
|
||||
return myInstance;
|
||||
}
|
||||
|
||||
private final boolean myEncounter;
|
||||
private final boolean myInstance;
|
||||
|
||||
private EverythingModeEnum(boolean thePatient, boolean theEncounter, boolean theInstance) {
|
||||
assert thePatient ^ theEncounter;
|
||||
myPatient = thePatient;
|
||||
myEncounter = theEncounter;
|
||||
myInstance = theInstance;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.SearchResult;
|
||||
|
||||
public interface ISearchResultDao extends JpaRepository<SearchResult, Long> {
|
||||
// nothing
|
||||
}
|
|
@ -24,9 +24,11 @@ import java.io.Serializable;
|
|||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Index;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
|
@ -35,9 +37,14 @@ import org.apache.commons.lang3.Validate;
|
|||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
|
||||
import com.phloc.commons.annotations.ContainsSoftMigration;
|
||||
|
||||
@Entity
|
||||
@Table(name = "HFJ_RES_LINK"/* , indexes= {@Index(name="IDX_RL_TPATHRES", columnList= "SRC_PATH,TARGET_RESOURCE_ID")} */)
|
||||
@org.hibernate.annotations.Table(appliesTo = "HFJ_RES_LINK", indexes = { @org.hibernate.annotations.Index(name = "IDX_RL_TPATHRES", columnNames = { "SRC_PATH", "TARGET_RESOURCE_ID" }) })
|
||||
@Table(name = "HFJ_RES_LINK" , indexes= {
|
||||
@Index(name="IDX_RL_TPATHRES", columnList= "SRC_PATH,TARGET_RESOURCE_ID"),
|
||||
@Index(name="IDX_RL_SRC", columnList= "SRC_RESOURCE_ID"),
|
||||
@Index(name="IDX_RL_DEST", columnList= "TARGET_RESOURCE_ID")
|
||||
})
|
||||
public class ResourceLink implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
@ -50,14 +57,14 @@ public class ResourceLink implements Serializable {
|
|||
@Column(name = "SRC_PATH", length = 100, nullable = false)
|
||||
private String mySourcePath;
|
||||
|
||||
@ManyToOne(optional = false)
|
||||
@ManyToOne(optional = false, fetch=FetchType.LAZY)
|
||||
@JoinColumn(name = "SRC_RESOURCE_ID", referencedColumnName = "RES_ID", nullable = false)
|
||||
private ResourceTable mySourceResource;
|
||||
|
||||
@Column(name = "SRC_RESOURCE_ID", insertable = false, updatable = false, nullable = false)
|
||||
private Long mySourceResourcePid;
|
||||
|
||||
@ManyToOne(optional = false)
|
||||
@ManyToOne(optional = false, fetch=FetchType.LAZY)
|
||||
@JoinColumn(name = "TARGET_RESOURCE_ID", referencedColumnName = "RES_ID", nullable = false)
|
||||
private ResourceTable myTargetResource;
|
||||
|
||||
|
@ -141,8 +148,8 @@ public class ResourceLink implements Serializable {
|
|||
StringBuilder b = new StringBuilder();
|
||||
b.append("ResourceLink[");
|
||||
b.append("path=").append(mySourcePath);
|
||||
b.append(", src=").append(mySourceResource.getId());
|
||||
b.append(", target=").append(myTargetResource.getId());
|
||||
b.append(", src=").append(mySourceResourcePid);
|
||||
b.append(", target=").append(myTargetResourcePid);
|
||||
|
||||
b.append("]");
|
||||
return b.toString();
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
package ca.uhn.fhir.jpa.entity;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.SequenceGenerator;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
|
||||
//@formatter:off
|
||||
@Entity
|
||||
@Table(name = "HFJ_SEARCH", uniqueConstraints= {
|
||||
@UniqueConstraint(name="IDX_SEARCH_UUID", columnNames="SEARCH_UUID")
|
||||
})
|
||||
//@formatter:on
|
||||
public class Search implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
@Column(name="CREATED", nullable=false)
|
||||
private Date myCreated;
|
||||
|
||||
@GeneratedValue(strategy = GenerationType.AUTO, generator="SEQ_SEARCH")
|
||||
@SequenceGenerator(name="SEQ_SEARCH", sequenceName="SEQ_SEARCH")
|
||||
@Id
|
||||
@Column(name = "PID")
|
||||
private Long myId;
|
||||
|
||||
@Column(name="SEARCH_UUID", length=40, nullable=false)
|
||||
private String myUuid;
|
||||
|
||||
public Date getCreated() {
|
||||
return myCreated;
|
||||
}
|
||||
|
||||
public String getUuid() {
|
||||
return myUuid;
|
||||
}
|
||||
|
||||
public void setCreated(Date theCreated) {
|
||||
myCreated = theCreated;
|
||||
}
|
||||
|
||||
public void setUuid(String theUuid) {
|
||||
myUuid = theUuid;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
package ca.uhn.fhir.jpa.entity;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.ForeignKey;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.SequenceGenerator;
|
||||
import javax.persistence.Table;
|
||||
|
||||
//@formatter:off
|
||||
@Entity
|
||||
@Table(name = "HFJ_SEARCH_RESULT", uniqueConstraints= {
|
||||
})
|
||||
//@formatter:on
|
||||
public class SearchResult implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@GeneratedValue(strategy = GenerationType.AUTO, generator="SEQ_SEARCH_RES")
|
||||
@SequenceGenerator(name="SEQ_SEARCH_RES", sequenceName="SEQ_SEARCH_RES")
|
||||
@Id
|
||||
@Column(name = "PID")
|
||||
private Long myId;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name="RESOURCE_PID", referencedColumnName="RES_ID", foreignKey=@ForeignKey(name="FK_SEARCHRES_RES"), insertable=false, updatable=false, nullable=false)
|
||||
private ResourceTable myResource;
|
||||
|
||||
@Column(name="RESOURCE_PID", insertable=true, updatable=false, nullable=false)
|
||||
private Long myResourcePid;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name="SEARCH_PID", referencedColumnName="PID", foreignKey=@ForeignKey(name="FK_SEARCHRES_SEARCH"))
|
||||
private Search mySearch;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public SearchResult() {
|
||||
// nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public SearchResult(Search theSearch) {
|
||||
mySearch = theSearch;
|
||||
}
|
||||
|
||||
public void setResourcePid(Long theResourcePid) {
|
||||
myResourcePid = theResourcePid;
|
||||
}
|
||||
}
|
|
@ -120,7 +120,7 @@ public abstract class BaseJpaDstu2Test extends BaseJpaTest {
|
|||
protected IFhirResourceDao<Organization> myOrganizationDao;
|
||||
@Autowired
|
||||
@Qualifier("myPatientDaoDstu2")
|
||||
protected IFhirResourceDao<Patient> myPatientDao;
|
||||
protected IFhirResourceDaoPatient<Patient> myPatientDao;
|
||||
@Autowired
|
||||
@Qualifier("myPractitionerDaoDstu2")
|
||||
protected IFhirResourceDao<Practitioner> myPractitionerDao;
|
||||
|
|
|
@ -11,6 +11,7 @@ import static org.junit.Assert.assertEquals;
|
|||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
|
@ -20,6 +21,8 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
|
@ -39,6 +42,7 @@ import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
|||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
|
||||
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
|
||||
import ca.uhn.fhir.model.dstu.resource.BaseResource;
|
||||
import ca.uhn.fhir.model.dstu.valueset.QuantityCompararatorEnum;
|
||||
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.IdentifierDt;
|
||||
|
@ -52,8 +56,11 @@ import ca.uhn.fhir.model.dstu2.resource.DiagnosticReport;
|
|||
import ca.uhn.fhir.model.dstu2.resource.Encounter;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Immunization;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Location;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Medication;
|
||||
import ca.uhn.fhir.model.dstu2.resource.MedicationOrder;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Observation;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Organization;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Parameters;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Practitioner;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Subscription;
|
||||
|
@ -570,21 +577,21 @@ public class FhirResourceDaoDstu2SearchTest extends BaseJpaDstu2Test {
|
|||
}
|
||||
{
|
||||
Map<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
|
||||
params.put(Patient.SP_RES_LANGUAGE, new StringParam("en_CA"));
|
||||
params.put(BaseResource.SP_RES_LANGUAGE, new StringParam("en_CA"));
|
||||
List<IResource> patients = toList(myPatientDao.search(params));
|
||||
assertEquals(1, patients.size());
|
||||
assertEquals(id1.toUnqualifiedVersionless(), patients.get(0).getId().toUnqualifiedVersionless());
|
||||
}
|
||||
{
|
||||
Map<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
|
||||
params.put(Patient.SP_RES_LANGUAGE, new StringParam("en_US"));
|
||||
params.put(BaseResource.SP_RES_LANGUAGE, new StringParam("en_US"));
|
||||
List<Patient> patients = toList(myPatientDao.search(params));
|
||||
assertEquals(1, patients.size());
|
||||
assertEquals(id2.toUnqualifiedVersionless(), patients.get(0).getId().toUnqualifiedVersionless());
|
||||
}
|
||||
{
|
||||
Map<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
|
||||
params.put(Patient.SP_RES_LANGUAGE, new StringParam("en_GB"));
|
||||
params.put(BaseResource.SP_RES_LANGUAGE, new StringParam("en_GB"));
|
||||
List<Patient> patients = toList(myPatientDao.search(params));
|
||||
assertEquals(0, patients.size());
|
||||
}
|
||||
|
@ -610,12 +617,12 @@ public class FhirResourceDaoDstu2SearchTest extends BaseJpaDstu2Test {
|
|||
}
|
||||
{
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.add(Patient.SP_RES_LANGUAGE, new StringOrListParam().addOr(new StringParam("en_CA")).addOr(new StringParam("en_US")));
|
||||
params.add(BaseResource.SP_RES_LANGUAGE, new StringOrListParam().addOr(new StringParam("en_CA")).addOr(new StringParam("en_US")));
|
||||
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(params)), containsInAnyOrder(id1, id2));
|
||||
}
|
||||
{
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.add(Patient.SP_RES_LANGUAGE, new StringOrListParam().addOr(new StringParam("en_CA")).addOr(new StringParam("ZZZZ")));
|
||||
params.add(BaseResource.SP_RES_LANGUAGE, new StringOrListParam().addOr(new StringParam("en_CA")).addOr(new StringParam("ZZZZ")));
|
||||
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(params)), containsInAnyOrder(id1));
|
||||
}
|
||||
{
|
||||
|
@ -623,7 +630,7 @@ public class FhirResourceDaoDstu2SearchTest extends BaseJpaDstu2Test {
|
|||
StringAndListParam and = new StringAndListParam();
|
||||
and.addAnd(new StringOrListParam().addOr(new StringParam("en_CA")).addOr(new StringParam("ZZZZ")));
|
||||
and.addAnd(new StringOrListParam().addOr(new StringParam("en_CA")));
|
||||
params.add(Patient.SP_RES_LANGUAGE, and);
|
||||
params.add(BaseResource.SP_RES_LANGUAGE, and);
|
||||
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(params)), containsInAnyOrder(id1));
|
||||
}
|
||||
{
|
||||
|
@ -631,7 +638,7 @@ public class FhirResourceDaoDstu2SearchTest extends BaseJpaDstu2Test {
|
|||
StringAndListParam and = new StringAndListParam();
|
||||
and.addAnd(new StringOrListParam().addOr(new StringParam("en_CA")).addOr(new StringParam("ZZZZ")));
|
||||
and.addAnd(new StringOrListParam().addOr(new StringParam("ZZZZZ")));
|
||||
params.add(Patient.SP_RES_LANGUAGE, and);
|
||||
params.add(BaseResource.SP_RES_LANGUAGE, and);
|
||||
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(params)), empty());
|
||||
}
|
||||
{
|
||||
|
@ -639,7 +646,7 @@ public class FhirResourceDaoDstu2SearchTest extends BaseJpaDstu2Test {
|
|||
StringAndListParam and = new StringAndListParam();
|
||||
and.addAnd(new StringOrListParam().addOr(new StringParam("ZZZZZ")));
|
||||
and.addAnd(new StringOrListParam().addOr(new StringParam("en_CA")).addOr(new StringParam("ZZZZ")));
|
||||
params.add(Patient.SP_RES_LANGUAGE, and);
|
||||
params.add(BaseResource.SP_RES_LANGUAGE, and);
|
||||
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(params)), empty());
|
||||
}
|
||||
{
|
||||
|
@ -647,7 +654,7 @@ public class FhirResourceDaoDstu2SearchTest extends BaseJpaDstu2Test {
|
|||
StringAndListParam and = new StringAndListParam();
|
||||
and.addAnd(new StringOrListParam().addOr(new StringParam("en_CA")).addOr(new StringParam("ZZZZ")));
|
||||
and.addAnd(new StringOrListParam().addOr(new StringParam("")).addOr(new StringParam(null)));
|
||||
params.add(Patient.SP_RES_LANGUAGE, and);
|
||||
params.add(BaseResource.SP_RES_LANGUAGE, and);
|
||||
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(params)), containsInAnyOrder(id1));
|
||||
}
|
||||
{
|
||||
|
@ -656,7 +663,7 @@ public class FhirResourceDaoDstu2SearchTest extends BaseJpaDstu2Test {
|
|||
StringAndListParam and = new StringAndListParam();
|
||||
and.addAnd(new StringOrListParam().addOr(new StringParam("en_CA")).addOr(new StringParam("ZZZZ")));
|
||||
and.addAnd(new StringOrListParam().addOr(new StringParam("")).addOr(new StringParam(null)));
|
||||
params.add(Patient.SP_RES_LANGUAGE, and);
|
||||
params.add(BaseResource.SP_RES_LANGUAGE, and);
|
||||
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(params)), containsInAnyOrder(id1));
|
||||
}
|
||||
{
|
||||
|
@ -664,12 +671,41 @@ public class FhirResourceDaoDstu2SearchTest extends BaseJpaDstu2Test {
|
|||
StringAndListParam and = new StringAndListParam();
|
||||
and.addAnd(new StringOrListParam().addOr(new StringParam("en_CA")).addOr(new StringParam("ZZZZ")));
|
||||
and.addAnd(new StringOrListParam().addOr(new StringParam("")).addOr(new StringParam(null)));
|
||||
params.add(Patient.SP_RES_LANGUAGE, and);
|
||||
params.add(BaseResource.SP_RES_LANGUAGE, and);
|
||||
params.add("_id", new StringParam(id1.getIdPart()));
|
||||
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(params)), containsInAnyOrder(id1));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testEverythingTimings() throws Exception {
|
||||
String methodName = "testEverythingIncludesBackReferences";
|
||||
|
||||
Organization org = new Organization();
|
||||
org.setName(methodName);
|
||||
IIdType orgId = myOrganizationDao.create(org).getId().toUnqualifiedVersionless();
|
||||
|
||||
Medication med = new Medication();
|
||||
med.getCode().setText(methodName);
|
||||
IIdType medId = myMedicationDao.create(med).getId().toUnqualifiedVersionless();
|
||||
|
||||
Patient pat = new Patient();
|
||||
pat.addAddress().addLine(methodName);
|
||||
pat.getManagingOrganization().setReference(orgId);
|
||||
IIdType patId = myPatientDao.create(pat).getId().toUnqualifiedVersionless();
|
||||
|
||||
MedicationOrder mo = new MedicationOrder();
|
||||
mo.getPatient().setReference(patId);
|
||||
mo.setMedication(new ResourceReferenceDt(medId));
|
||||
IIdType moId = myMedicationOrderDao.create(mo).getId().toUnqualifiedVersionless();
|
||||
|
||||
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||
IBundleProvider resp = myPatientDao.patientTypeEverything(request, null, null, null);
|
||||
assertEquals(4, resp.size());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSearchLastUpdatedParamWithComparator() throws InterruptedException {
|
||||
|
@ -1053,7 +1089,13 @@ public class FhirResourceDaoDstu2SearchTest extends BaseJpaDstu2Test {
|
|||
|
||||
ourLog.info("P1[{}] L1[{}] Obs1[{}] Obs2[{}]", new Object[] { patientId01, locId01, obsId01, obsId02 });
|
||||
|
||||
List<Observation> result = toList(myObservationDao.search(Observation.SP_SUBJECT, new ReferenceParam(Patient.SP_NAME, "testSearchResourceLinkWithChainWithMultipleTypes01")));
|
||||
List<Observation> result;
|
||||
|
||||
result = toList(myObservationDao.search(Observation.SP_SUBJECT, new ReferenceParam("Patient", Patient.SP_NAME, "testSearchResourceLinkWithChainWithMultipleTypes01")));
|
||||
assertEquals(1, result.size());
|
||||
assertEquals(obsId01.getIdPart(), result.get(0).getId().getIdPart());
|
||||
|
||||
result = toList(myObservationDao.search(Observation.SP_SUBJECT, new ReferenceParam(Patient.SP_NAME, "testSearchResourceLinkWithChainWithMultipleTypes01")));
|
||||
assertEquals(2, result.size());
|
||||
|
||||
result = toList(myObservationDao.search(Observation.SP_SUBJECT, new ReferenceParam(Patient.SP_NAME, "testSearchResourceLinkWithChainWithMultipleTypesXX")));
|
||||
|
@ -1062,10 +1104,6 @@ public class FhirResourceDaoDstu2SearchTest extends BaseJpaDstu2Test {
|
|||
result = toList(myObservationDao.search(Observation.SP_SUBJECT, new ReferenceParam(Patient.SP_NAME, "testSearchResourceLinkWithChainWithMultipleTypesYY")));
|
||||
assertEquals(0, result.size());
|
||||
|
||||
result = toList(myObservationDao.search(Observation.SP_SUBJECT, new ReferenceParam("Patient", Patient.SP_NAME, "testSearchResourceLinkWithChainWithMultipleTypes01")));
|
||||
assertEquals(1, result.size());
|
||||
assertEquals(obsId01.getIdPart(), result.get(0).getId().getIdPart());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -1184,12 +1222,12 @@ public class FhirResourceDaoDstu2SearchTest extends BaseJpaDstu2Test {
|
|||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("001");
|
||||
patient.addName().addFamily(value);
|
||||
longId = (IdDt) myPatientDao.create(patient).getId().toUnqualifiedVersionless();
|
||||
longId = myPatientDao.create(patient).getId().toUnqualifiedVersionless();
|
||||
}
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("002");
|
||||
shortId = (IdDt) myPatientDao.create(patient).getId().toUnqualifiedVersionless();
|
||||
shortId = myPatientDao.create(patient).getId().toUnqualifiedVersionless();
|
||||
}
|
||||
|
||||
Map<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
|
||||
|
@ -1479,7 +1517,7 @@ public class FhirResourceDaoDstu2SearchTest extends BaseJpaDstu2Test {
|
|||
|
||||
{
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.add(Organization.SP_RES_ID, new StringDt(orgId.getIdPart()));
|
||||
params.add(ca.uhn.fhir.model.dstu2.resource.BaseResource.SP_RES_ID, new StringDt(orgId.getIdPart()));
|
||||
params.addInclude(Organization.INCLUDE_PARTOF.asNonRecursive());
|
||||
List<IIdType> resources = toUnqualifiedVersionlessIds(myOrganizationDao.search(params));
|
||||
assertThat(resources, contains(orgId, parentOrgId));
|
||||
|
@ -1833,8 +1871,6 @@ public class FhirResourceDaoDstu2SearchTest extends BaseJpaDstu2Test {
|
|||
|
||||
@Test
|
||||
public void testSearchWithUriParam() throws Exception {
|
||||
String methodName = "testSearchWithUriParam";
|
||||
|
||||
Class<ValueSet> type = ValueSet.class;
|
||||
String resourceName = "/valueset-dstu2.json";
|
||||
ValueSet vs = loadResourceFromClasspath(type, resourceName);
|
||||
|
|
|
@ -822,6 +822,34 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
|
||||
assertGone(id);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testDeleteWithMatchUrlChainedIdentifier() {
|
||||
String methodName = "testDeleteWithMatchUrlChainedIdentifer";
|
||||
|
||||
Organization org = new Organization();
|
||||
org.setName(methodName);
|
||||
org.addIdentifier().setSystem("http://example.com").setValue(methodName);
|
||||
IIdType orgId = myOrganizationDao.create(org).getId().toUnqualifiedVersionless();
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.getManagingOrganization().setReference(orgId);
|
||||
IIdType id = myPatientDao.create(p).getId().toUnqualifiedVersionless();
|
||||
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
myPatientDao.deleteByUrl("Patient?organization.identifier=http://example.com|" + methodName);
|
||||
assertGone(id);
|
||||
assertNotGone(orgId);
|
||||
|
||||
myOrganizationDao.deleteByUrl("Organization?identifier=http://example.com|" + methodName);
|
||||
assertGone(id);
|
||||
assertGone(orgId);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testDeleteWithMatchUrlChainedTag() {
|
||||
|
|
|
@ -77,7 +77,8 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
public void testTransactionFromBundle6() throws Exception {
|
||||
InputStream bundleRes = SystemProviderDstu2Test.class.getResourceAsStream("/simone_bundle3.xml");
|
||||
String bundle = IOUtils.toString(bundleRes);
|
||||
mySystemDao.transaction(myFhirCtx.newXmlParser().parseResource(Bundle.class, bundle));
|
||||
Bundle output = mySystemDao.transaction(myFhirCtx.newXmlParser().parseResource(Bundle.class, bundle));
|
||||
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(output));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -712,12 +713,12 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
Bundle request = new Bundle();
|
||||
request.addEntry().getRequest().setMethod(HTTPVerbEnum.DELETE).setUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
try {
|
||||
// try {
|
||||
mySystemDao.transaction(request);
|
||||
fail();
|
||||
} catch (ResourceNotFoundException e) {
|
||||
assertThat(e.getMessage(), containsString("resource matching URL \"Patient?"));
|
||||
}
|
||||
// fail();
|
||||
// } catch (ResourceNotFoundException e) {
|
||||
// assertThat(e.getMessage(), containsString("resource matching URL \"Patient?"));
|
||||
// }
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -797,15 +798,6 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
assertEquals("201 Created", resp.getEntry().get(1).getResponse().getStatus());
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
Communication com = new Communication();
|
||||
com.getSender().setReference("Patient/james");
|
||||
com.addRecipient().setReference("Group/everyone");
|
||||
com.addMedium().setText("Skype");
|
||||
com.addPayload().setContent(new StringDt("Welcome to Connectathon 10! Any HAPI users feel free to grab me if you want to chat or need help!"));
|
||||
System.out.println(FhirContext.forDstu2().newJsonParser().setPrettyPrint(true).encodeResourceToString(com));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionWithReferenceToCreateIfNoneExist() {
|
||||
Bundle bundle = new Bundle();
|
||||
|
|
|
@ -41,6 +41,7 @@ import org.apache.http.entity.StringEntity;
|
|||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.junit.Test;
|
||||
import org.thymeleaf.util.UrlUtils;
|
||||
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
|
@ -94,6 +95,7 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
|||
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||
import ca.uhn.fhir.util.UrlUtil;
|
||||
|
||||
public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
|
||||
|
||||
|
@ -269,7 +271,92 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
|
|||
assertThat(e.getMessage(), containsString("Question with linkId[link0]"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateResourceConditionalComplex() throws IOException {
|
||||
Patient pt = new Patient();
|
||||
pt.addIdentifier().setSystem("http://general-hospital.co.uk/Identifiers").setValue("09832345234543876876");
|
||||
String resource = myFhirCtx.newXmlParser().encodeResourceToString(pt);
|
||||
|
||||
HttpPost post = new HttpPost(ourServerBase + "/Patient");
|
||||
post.addHeader(Constants.HEADER_IF_NONE_EXIST, "Patient?identifier=http://general-hospital.co.uk/Identifiers|09832345234543876876");
|
||||
post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||
|
||||
IdDt id;
|
||||
CloseableHttpResponse response = ourHttpClient.execute(post);
|
||||
try {
|
||||
assertEquals(201, response.getStatusLine().getStatusCode());
|
||||
String newIdString = response.getFirstHeader(Constants.HEADER_LOCATION_LC).getValue();
|
||||
assertThat(newIdString, startsWith(ourServerBase + "/Patient/"));
|
||||
id = new IdDt(newIdString);
|
||||
} finally {
|
||||
response.close();
|
||||
}
|
||||
|
||||
pt.addName().addFamily("FOO");
|
||||
resource = myFhirCtx.newXmlParser().encodeResourceToString(pt);
|
||||
HttpPut put = new HttpPut(ourServerBase + "/Patient?identifier=" + ("http://general-hospital.co.uk/Identifiers|09832345234543876876".replace("|", UrlUtil.escape("|"))));
|
||||
put.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||
|
||||
IdDt id2;
|
||||
response = ourHttpClient.execute(put);
|
||||
try {
|
||||
assertEquals(200, response.getStatusLine().getStatusCode());
|
||||
String newIdString = response.getFirstHeader(Constants.HEADER_LOCATION_LC).getValue();
|
||||
assertThat(newIdString, startsWith(ourServerBase + "/Patient/"));
|
||||
id2 = new IdDt(newIdString);
|
||||
} finally {
|
||||
response.close();
|
||||
}
|
||||
|
||||
assertEquals(id.getIdPart(), id2.getIdPart());
|
||||
assertEquals("1", id.getVersionIdPart());
|
||||
assertEquals("2", id2.getVersionIdPart());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateResourceConditionalComplex() throws IOException {
|
||||
Patient pt = new Patient();
|
||||
pt.addIdentifier().setSystem("http://general-hospital.co.uk/Identifiers").setValue("09832345234543876876");
|
||||
String resource = myFhirCtx.newXmlParser().encodeResourceToString(pt);
|
||||
|
||||
HttpPost post = new HttpPost(ourServerBase + "/Patient");
|
||||
post.addHeader(Constants.HEADER_IF_NONE_EXIST, "Patient?identifier=http://general-hospital.co.uk/Identifiers|09832345234543876876");
|
||||
post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||
|
||||
IdDt id;
|
||||
CloseableHttpResponse response = ourHttpClient.execute(post);
|
||||
try {
|
||||
assertEquals(201, response.getStatusLine().getStatusCode());
|
||||
String newIdString = response.getFirstHeader(Constants.HEADER_LOCATION_LC).getValue();
|
||||
assertThat(newIdString, startsWith(ourServerBase + "/Patient/"));
|
||||
id = new IdDt(newIdString);
|
||||
} finally {
|
||||
response.close();
|
||||
}
|
||||
|
||||
IdDt id2;
|
||||
response = ourHttpClient.execute(post);
|
||||
try {
|
||||
assertEquals(200, response.getStatusLine().getStatusCode());
|
||||
String newIdString = response.getFirstHeader(Constants.HEADER_LOCATION_LC).getValue();
|
||||
assertThat(newIdString, startsWith(ourServerBase + "/Patient/"));
|
||||
id2 = new IdDt(newIdString);
|
||||
} finally {
|
||||
response.close();
|
||||
}
|
||||
|
||||
// //@formatter:off
|
||||
// IIdType id3 = ourClient
|
||||
// .update()
|
||||
// .resource(pt)
|
||||
// .conditionalByUrl("Patient?identifier=http://general-hospital.co.uk/Identifiers|09832345234543876876")
|
||||
// .execute().getId();
|
||||
// //@formatter:on
|
||||
|
||||
assertEquals(id.getValue(), id2.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateResourceConditional() throws IOException {
|
||||
String methodName = "testCreateResourceConditional";
|
||||
|
@ -2042,7 +2129,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
|
|||
try {
|
||||
String resp = IOUtils.toString(response.getEntity().getContent());
|
||||
ourLog.info(resp);
|
||||
assertEquals(412, response.getStatusLine().getStatusCode());
|
||||
assertEquals(200, response.getStatusLine().getStatusCode());
|
||||
} finally {
|
||||
IOUtils.closeQuietly(response.getEntity().getContent());
|
||||
response.close();
|
||||
|
@ -2069,7 +2156,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
|
|||
try {
|
||||
String resp = IOUtils.toString(response.getEntity().getContent());
|
||||
ourLog.info(resp);
|
||||
assertEquals(412, response.getStatusLine().getStatusCode());
|
||||
assertEquals(200, response.getStatusLine().getStatusCode());
|
||||
} finally {
|
||||
IOUtils.closeQuietly(response.getEntity().getContent());
|
||||
response.close();
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
<class>ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamCoords</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.ResourceLink</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.ResourceTag</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.Search</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.SearchResult</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.SubscriptionTable</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.SubscriptionFlaggedResource</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.TagDefinition</class>
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
</logger>
|
||||
|
||||
<!-- Set to 'trace' to enable SQL logging -->
|
||||
<logger name="org.hibernate.SQL" additivity="false" level="info">
|
||||
<logger name="org.hibernate.SQL" additivity="false" level="trace">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</logger>
|
||||
|
||||
|
|
|
@ -170,7 +170,7 @@
|
|||
<webApp>
|
||||
<contextPath>/hapi-fhir-jpaserver-example</contextPath>
|
||||
<allowDuplicateFragmentNames>true</allowDuplicateFragmentNames>
|
||||
</webAppConfig>
|
||||
</webApp>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
|
|
@ -2,14 +2,18 @@
|
|||
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||
<level>INFO</level>
|
||||
<level>TRACE</level>
|
||||
</filter>
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} [%file:%line] %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root>
|
||||
<logger name="org.hibernate.SQL" additivity="false" level="trace">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</logger>
|
||||
|
||||
<root level="info">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
|
||||
|
|
|
@ -343,6 +343,15 @@ public class GenericClientDstu2Test {
|
|||
assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod());
|
||||
idx++;
|
||||
|
||||
client.create().resource(p).conditionalByUrl("Patient?name=http://foo|bar").execute();
|
||||
assertEquals(1, capt.getAllValues().get(idx).getHeaders(Constants.HEADER_CONTENT_TYPE).length);
|
||||
assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue());
|
||||
assertThat(extractBody(capt, idx), containsString("<family value=\"FOOFAMILY\"/>"));
|
||||
assertEquals("http://example.com/fhir/Patient", capt.getAllValues().get(idx).getURI().toString());
|
||||
assertEquals("http://example.com/fhir/Patient?name=http://foo%7Cbar", capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_IF_NONE_EXIST).getValue());
|
||||
assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod());
|
||||
idx++;
|
||||
|
||||
client.create().resource(p).conditional().where(Patient.NAME.matches().value("foo")).execute();
|
||||
assertEquals(1, capt.getAllValues().get(idx).getHeaders(Constants.HEADER_CONTENT_TYPE).length);
|
||||
assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue());
|
||||
|
@ -1683,6 +1692,84 @@ public class GenericClientDstu2Test {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchByUrl() throws Exception {
|
||||
|
||||
final 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()).thenAnswer(new Answer<InputStream>() {
|
||||
@Override
|
||||
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
return new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8"));
|
||||
}});
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
int idx = 0;
|
||||
|
||||
//@formatter:off
|
||||
ca.uhn.fhir.model.dstu2.resource.Bundle response = client.search()
|
||||
.byUrl("http://foo?name=http://foo|bar")
|
||||
.encodedJson()
|
||||
.returnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class)
|
||||
.execute();
|
||||
//@formatter:on
|
||||
assertEquals("http://foo?name=http%3A//foo%7Cbar&_format=json", capt.getAllValues().get(idx).getURI().toString());
|
||||
assertNotNull(response);
|
||||
idx++;
|
||||
|
||||
//@formatter:off
|
||||
response = client.search()
|
||||
.byUrl("Patient?name=http://foo|bar")
|
||||
.encodedJson()
|
||||
.returnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class)
|
||||
.execute();
|
||||
//@formatter:on
|
||||
assertEquals("http://example.com/fhir/Patient?name=http%3A//foo%7Cbar&_format=json", capt.getAllValues().get(idx).getURI().toString());
|
||||
assertNotNull(response);
|
||||
idx++;
|
||||
|
||||
//@formatter:off
|
||||
response = client.search()
|
||||
.byUrl("/Patient?name=http://foo|bar")
|
||||
.encodedJson()
|
||||
.returnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class)
|
||||
.execute();
|
||||
//@formatter:on
|
||||
assertEquals("http://example.com/fhir/Patient?name=http%3A//foo%7Cbar&_format=json", capt.getAllValues().get(idx).getURI().toString());
|
||||
assertNotNull(response);
|
||||
idx++;
|
||||
|
||||
//@formatter:off
|
||||
response = client.search()
|
||||
.byUrl("Patient")
|
||||
.returnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class)
|
||||
.execute();
|
||||
//@formatter:on
|
||||
assertEquals("http://example.com/fhir/Patient", capt.getAllValues().get(idx).getURI().toString());
|
||||
assertNotNull(response);
|
||||
idx++;
|
||||
|
||||
//@formatter:off
|
||||
response = client.search()
|
||||
.byUrl("Patient?")
|
||||
.returnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class)
|
||||
.execute();
|
||||
//@formatter:on
|
||||
assertEquals("http://example.com/fhir/Patient?", capt.getAllValues().get(idx).getURI().toString());
|
||||
assertNotNull(response);
|
||||
idx++;
|
||||
|
||||
try {
|
||||
client.search().byUrl("foo/bar?test=1");
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertEquals("Search URL must be either a complete URL starting with http: or https:, or a relative FHIR URL in the form [ResourceType]?[Params]", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithSummaryParam() throws Exception {
|
||||
String msg = "{\"resourceType\":\"Bundle\",\"id\":null,\"base\":\"http://localhost:57931/fhir/contextDev\",\"total\":1,\"link\":[{\"relation\":\"self\",\"url\":\"http://localhost:57931/fhir/contextDev/Patient?identifier=urn%3AMultiFhirVersionTest%7CtestSubmitPatient01&_format=json\"}],\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\",\"lastUpdated\":\"2014-12-20T18:41:29.706-05:00\"},\"identifier\":[{\"system\":\"urn:MultiFhirVersionTest\",\"value\":\"testSubmitPatient01\"}]}}]}";
|
||||
|
@ -1885,6 +1972,14 @@ public class GenericClientDstu2Test {
|
|||
assertEquals("http://example.com/fhir/Patient?name=foo", capt.getAllValues().get(idx).getURI().toString());
|
||||
idx++;
|
||||
|
||||
client.update().resource(p).conditionalByUrl("Patient?name=http://foo|bar").execute();
|
||||
assertEquals(1, capt.getAllValues().get(idx).getHeaders(Constants.HEADER_CONTENT_TYPE).length);
|
||||
assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue());
|
||||
assertThat(extractBody(capt, idx), containsString("<family value=\"FOOFAMILY\"/>"));
|
||||
assertEquals("PUT", capt.getAllValues().get(idx).getRequestLine().getMethod());
|
||||
assertEquals("http://example.com/fhir/Patient?name=http%3A//foo%7Cbar", capt.getAllValues().get(idx).getURI().toString());
|
||||
idx++;
|
||||
|
||||
client.update().resource(ourCtx.newXmlParser().encodeResourceToString(p)).conditionalByUrl("Patient?name=foo").execute();
|
||||
assertEquals(1, capt.getAllValues().get(idx).getHeaders(Constants.HEADER_CONTENT_TYPE).length);
|
||||
assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue());
|
||||
|
@ -1911,7 +2006,6 @@ public class GenericClientDstu2Test {
|
|||
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
public void testUpdateNonFluent() throws Exception {
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
<class>ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamCoords</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.ResourceLink</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.ResourceTag</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.Search</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.SearchResult</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.SubscriptionTable</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.SubscriptionFlaggedResource</class>
|
||||
<class>ca.uhn.fhir.jpa.entity.TagDefinition</class>
|
||||
|
|
|
@ -144,7 +144,12 @@
|
|||
process if the condition had a chain or a
|
||||
qualifier, e.g. "Patient?organization.name" or
|
||||
"Patient.identifier:missing"
|
||||
|
||||
</action>
|
||||
<action type="add">
|
||||
Generic/fluent client search can now be
|
||||
performed using a complete URL supplied
|
||||
by user code. Thanks to Simone Heckmann
|
||||
pointing out that this was needed!
|
||||
</action>
|
||||
</release>
|
||||
<release version="1.2" date="2015-09-18">
|
||||
|
|
|
@ -175,6 +175,19 @@
|
|||
value="examples/src/main/java/example/GenericClientExample.java" />
|
||||
</macro>
|
||||
|
||||
<h4>Search - By plain URL</h4>
|
||||
<p>
|
||||
You can also perform a search using a String URL, instead
|
||||
of using the fluent method calls to build the URL. This
|
||||
can be useful if you have a URL you retrieved from
|
||||
somewhere else that you want to use as a search.
|
||||
</p>
|
||||
<macro name="snippet">
|
||||
<param name="id" value="searchUrl" />
|
||||
<param name="file"
|
||||
value="examples/src/main/java/example/GenericClientExample.java" />
|
||||
</macro>
|
||||
|
||||
<h4>Search - Other Query Options</h4>
|
||||
<p>
|
||||
The fluent search also has methods for sorting, limiting, specifying
|
||||
|
|
Loading…
Reference in New Issue