Fix #148 - Add _count support to everything operation
This commit is contained in:
parent
8c37973a78
commit
11507ef97c
|
@ -246,12 +246,11 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Integer count = RestfulServerUtils.extractCountParameter(theRequest.getServletRequest());
|
|
||||||
|
|
||||||
boolean respondGzip = theRequest.isRespondGzip();
|
|
||||||
|
|
||||||
HttpServletResponse response = theRequest.getServletResponse();
|
|
||||||
Object resultObj = invokeServer(theRequest, params);
|
Object resultObj = invokeServer(theRequest, params);
|
||||||
|
|
||||||
|
Integer count = RestfulServerUtils.extractCountParameter(theRequest.getServletRequest());
|
||||||
|
boolean respondGzip = theRequest.isRespondGzip();
|
||||||
|
HttpServletResponse response = theRequest.getServletResponse();
|
||||||
switch (getReturnType()) {
|
switch (getReturnType()) {
|
||||||
case BUNDLE: {
|
case BUNDLE: {
|
||||||
|
|
||||||
|
@ -283,12 +282,15 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
|
||||||
RestfulServerUtils.streamResponseAsResource(theServer, response, resource, responseEncoding, prettyPrint, requestIsBrowser, narrativeMode, respondGzip, theRequest.getFhirServerBase());
|
RestfulServerUtils.streamResponseAsResource(theServer, response, resource, responseEncoding, prettyPrint, requestIsBrowser, narrativeMode, respondGzip, theRequest.getFhirServerBase());
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
Set<Include> includes = getRequestIncludesFromParams(params);
|
Set<Include> includes = getRequestIncludesFromParams(params);
|
||||||
|
|
||||||
IBundleProvider result = (IBundleProvider) resultObj;
|
IBundleProvider result = (IBundleProvider) resultObj;
|
||||||
|
if (count == null) {
|
||||||
|
count = result.preferredPageSize();
|
||||||
|
}
|
||||||
|
|
||||||
IVersionSpecificBundleFactory bundleFactory = theServer.getFhirContext().newBundleFactory();
|
IVersionSpecificBundleFactory bundleFactory = theServer.getFhirContext().newBundleFactory();
|
||||||
bundleFactory.initializeBundleFromBundleProvider(theServer, result, responseEncoding, theRequest.getFhirServerBase(), theRequest.getCompleteUrl(), prettyPrint, 0, count, null,
|
bundleFactory.initializeBundleFromBundleProvider(theServer, result, responseEncoding, theRequest.getFhirServerBase(), theRequest.getCompleteUrl(), prettyPrint, 0, count, null, getResponseBundleType(), includes);
|
||||||
getResponseBundleType(), includes);
|
|
||||||
Bundle bundle = bundleFactory.getDstu1Bundle();
|
Bundle bundle = bundleFactory.getDstu1Bundle();
|
||||||
if (bundle != null) {
|
if (bundle != null) {
|
||||||
for (int i = theServer.getInterceptors().size() - 1; i >= 0; i--) {
|
for (int i = theServer.getInterceptors().size() - 1; i >= 0; i--) {
|
||||||
|
|
|
@ -208,6 +208,11 @@ public class HistoryMethodBinding extends BaseResourceReturningMethodBinding {
|
||||||
public int size() {
|
public int size() {
|
||||||
return resources.size();
|
return resources.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer preferredPageSize() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,11 @@ public class BundleProviders {
|
||||||
public InstantDt getPublished() {
|
public InstantDt getPublished() {
|
||||||
return published;
|
return published;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer preferredPageSize() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,21 +26,24 @@ import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import ca.uhn.fhir.model.api.*;
|
|
||||||
import ca.uhn.fhir.util.ResourceReferenceInfo;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.commons.lang3.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
import org.hl7.fhir.instance.model.IBaseResource;
|
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||||
|
import ca.uhn.fhir.model.api.Bundle;
|
||||||
|
import ca.uhn.fhir.model.api.BundleEntry;
|
||||||
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
|
import ca.uhn.fhir.model.api.Include;
|
||||||
|
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||||
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
|
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
|
||||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
||||||
import ca.uhn.fhir.model.primitive.IdDt;
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
import ca.uhn.fhir.model.valueset.BundleEntrySearchModeEnum;
|
import ca.uhn.fhir.model.valueset.BundleEntrySearchModeEnum;
|
||||||
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
|
import ca.uhn.fhir.util.ResourceReferenceInfo;
|
||||||
|
|
||||||
public class Dstu1BundleFactory implements IVersionSpecificBundleFactory {
|
public class Dstu1BundleFactory implements IVersionSpecificBundleFactory {
|
||||||
|
|
||||||
|
@ -253,7 +256,7 @@ public class Dstu1BundleFactory implements IVersionSpecificBundleFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBaseResource getResourceBundle() {
|
public IResource getResourceBundle() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,14 +28,37 @@ import ca.uhn.fhir.model.primitive.InstantDt;
|
||||||
public interface IBundleProvider {
|
public interface IBundleProvider {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Load the given collection of resources by index, plus any additional resources per the
|
||||||
|
* server's processing rules (e.g. _include'd resources, OperationOutcome, etc.). For example,
|
||||||
|
* if the method is invoked with index 0,10 the method might return 10 search results, plus an
|
||||||
|
* additional 20 resources which matched a client's _include specification.
|
||||||
|
*
|
||||||
* @param theFromIndex The low index (inclusive) to return
|
* @param theFromIndex The low index (inclusive) to return
|
||||||
* @param theToIndex The high index (exclusive) to return
|
* @param theToIndex The high index (exclusive) to return
|
||||||
* @return A list of resources. The size of this list must be at least <code>theToIndex - theFromIndex</code>.
|
* @return A list of resources. The size of this list must be at least <code>theToIndex - theFromIndex</code>.
|
||||||
*/
|
*/
|
||||||
List<IResource> getResources(int theFromIndex, int theToIndex);
|
List<IResource> getResources(int theFromIndex, int theToIndex);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optionally may be used to signal a preferred page size to the server, e.g. because
|
||||||
|
* the implementing code recognizes that the resources which will be returned by this
|
||||||
|
* implementation are expensive to load so a smaller page size should be used. The value
|
||||||
|
* returned by this method will only be used if the client has not explicitly requested
|
||||||
|
* a page size.
|
||||||
|
*
|
||||||
|
* @return Returns the preferred page size or <code>null</code>
|
||||||
|
*/
|
||||||
|
Integer preferredPageSize();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the total number of results which match the given query (exclusive of any
|
||||||
|
* _include's or OperationOutcome)
|
||||||
|
*/
|
||||||
int size();
|
int size();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the instant as of which this result was valid
|
||||||
|
*/
|
||||||
InstantDt getPublished();
|
InstantDt getPublished();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,11 +23,9 @@ package ca.uhn.fhir.rest.server;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import ca.uhn.fhir.model.api.Include;
|
|
||||||
import org.hl7.fhir.instance.model.IBaseResource;
|
|
||||||
|
|
||||||
import ca.uhn.fhir.model.api.Bundle;
|
import ca.uhn.fhir.model.api.Bundle;
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
|
import ca.uhn.fhir.model.api.Include;
|
||||||
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -41,11 +39,11 @@ public interface IVersionSpecificBundleFactory {
|
||||||
void addRootPropertiesToBundle(String theAuthor, String theServerBase, String theCompleteUrl, Integer theTotalResults, BundleTypeEnum theBundleType);
|
void addRootPropertiesToBundle(String theAuthor, String theServerBase, String theCompleteUrl, Integer theTotalResults, BundleTypeEnum theBundleType);
|
||||||
|
|
||||||
void initializeBundleFromBundleProvider(RestfulServer theServer, IBundleProvider theResult, EncodingEnum theResponseEncoding, String theServerBase, String theCompleteUrl, boolean thePrettyPrint,
|
void initializeBundleFromBundleProvider(RestfulServer theServer, IBundleProvider theResult, EncodingEnum theResponseEncoding, String theServerBase, String theCompleteUrl, boolean thePrettyPrint,
|
||||||
int theOffset, Integer theLimit, String theSearchId, BundleTypeEnum theBundleType, Set<Include> theIncludes);
|
int theOffset, Integer theCount, String theSearchId, BundleTypeEnum theBundleType, Set<Include> theIncludes);
|
||||||
|
|
||||||
Bundle getDstu1Bundle();
|
Bundle getDstu1Bundle();
|
||||||
|
|
||||||
IBaseResource getResourceBundle();
|
IResource getResourceBundle();
|
||||||
|
|
||||||
void initializeBundleFromResourceList(String theAuthor, List<IResource> theResult, String theServerBase, String theCompleteUrl, int theTotalResults, BundleTypeEnum theBundleType);
|
void initializeBundleFromResourceList(String theAuthor, List<IResource> theResult, String theServerBase, String theCompleteUrl, int theTotalResults, BundleTypeEnum theBundleType);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
package ca.uhn.fhir.rest.server;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.Validate;
|
||||||
|
import org.hl7.fhir.instance.model.IBaseResource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by {@link IBundleProvider} to provide a single page worth of results.
|
||||||
|
*
|
||||||
|
* If the server chooses to, it may return a different number of matching results to the number that the user requested.
|
||||||
|
* For example, if the client requested 100 results but the server decided to return only 10 (perhaps because they were
|
||||||
|
* very large), this value should be set to 10. Note that this count refers only to resources which are included in the
|
||||||
|
* indexes provided to {@link IBundleProvider#getResources(int, int)}, so it should not reflect any additional results
|
||||||
|
* added to the response as a result of _include parameters, OperationOutcome's etc.
|
||||||
|
*/
|
||||||
|
public class ResponseResourceList {
|
||||||
|
/**
|
||||||
|
* Singleton unmodifiable empty list
|
||||||
|
*/
|
||||||
|
public static final ResponseResourceList EMPTY = new EmptyResponseResourceList();
|
||||||
|
|
||||||
|
private List<IBaseResource> myIncludeResults;
|
||||||
|
private List<IBaseResource> myMatchResults;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an "include" results. Include results are results which are added as a result of <code>_include</code>
|
||||||
|
* directives in search requests.
|
||||||
|
*/
|
||||||
|
public void addIncludeResults(IBaseResource theIncludeResult) {
|
||||||
|
if (myIncludeResults == null) {
|
||||||
|
myIncludeResults = new ArrayList<IBaseResource>();
|
||||||
|
}
|
||||||
|
myIncludeResults.add(theIncludeResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a "match" result. A match result is a result added as a direct result of the operation in question. E.g. for
|
||||||
|
* a search invocation a match result would be a result which directly matched the search criteria. For a history
|
||||||
|
* invocation it would be a historical version of a resource or the current version.
|
||||||
|
*/
|
||||||
|
public void addMatchResult(IBaseResource theResource) {
|
||||||
|
Validate.notNull(theResource, "theResource must not be null");
|
||||||
|
if (myMatchResults == null) {
|
||||||
|
myMatchResults = new ArrayList<IBaseResource>();
|
||||||
|
}
|
||||||
|
myMatchResults.add(theResource);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<IBaseResource> getIncludeResults() {
|
||||||
|
return myIncludeResults;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<IBaseResource> getMatchResults() {
|
||||||
|
return myMatchResults;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the "include" results. Include results are results which are added as a result of <code>_include</code>
|
||||||
|
* directives in search requests.
|
||||||
|
*/
|
||||||
|
public void setIncludeResults(List<IBaseResource> theIncludeResults) {
|
||||||
|
myIncludeResults = theIncludeResults;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the "match" results. A match result is a result added as a direct result of the operation in question. E.g.
|
||||||
|
* for a search invocation a match result would be a result which directly matched the search criteria. For a
|
||||||
|
* history invocation it would be a historical version of a resource or the current version.
|
||||||
|
*/
|
||||||
|
public void setMatchResults(List<IBaseResource> theMatchResults) {
|
||||||
|
myMatchResults = theMatchResults;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class EmptyResponseResourceList extends ResponseResourceList {
|
||||||
|
@Override
|
||||||
|
public void addIncludeResults(IBaseResource theIncludeResult) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addMatchResult(IBaseResource theResource) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setIncludeResults(List<IBaseResource> theIncludeResults) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setMatchResults(List<IBaseResource> theMatchResults) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -59,5 +59,10 @@ public class SimpleBundleProvider implements IBundleProvider {
|
||||||
public InstantDt getPublished() {
|
public InstantDt getPublished() {
|
||||||
return InstantDt.withCurrentTime();
|
return InstantDt.withCurrentTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer preferredPageSize() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -494,6 +494,11 @@ public abstract class BaseFhirDao implements IDao {
|
||||||
public int size() {
|
public int size() {
|
||||||
return tuples.size();
|
return tuples.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer preferredPageSize() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -659,6 +659,18 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
||||||
return new HashSet<Long>(q.getResultList());
|
return new HashSet<Long>(q.getResultList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<IResource> addResourcesAsIncludesById(List<IResource> theListToPopulate, Set<IdDt> includePids, List<IResource> resources) {
|
||||||
|
if (!includePids.isEmpty()) {
|
||||||
|
ourLog.info("Loading {} included resources", includePids.size());
|
||||||
|
resources = loadResourcesById(includePids);
|
||||||
|
for (IResource next : resources) {
|
||||||
|
ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE.put(next, BundleEntrySearchModeEnum.INCLUDE);
|
||||||
|
}
|
||||||
|
theListToPopulate.addAll(resources);
|
||||||
|
}
|
||||||
|
return resources;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addTag(IdDt theId, TagTypeEnum theTagType, String theScheme, String theTerm, String theLabel) {
|
public void addTag(IdDt theId, TagTypeEnum theTagType, String theScheme, String theTerm, String theLabel) {
|
||||||
StopWatch w = new StopWatch();
|
StopWatch w = new StopWatch();
|
||||||
|
@ -713,50 +725,6 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
||||||
return doCreate(theResource, theIfNoneExist, thePerformIndexing);
|
return doCreate(theResource, theIfNoneExist, thePerformIndexing);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DaoMethodOutcome doCreate(T theResource, String theIfNoneExist, boolean thePerformIndexing) {
|
|
||||||
StopWatch w = new StopWatch();
|
|
||||||
ResourceTable entity = new ResourceTable();
|
|
||||||
entity.setResourceType(toResourceName(theResource));
|
|
||||||
|
|
||||||
if (isNotBlank(theIfNoneExist)) {
|
|
||||||
Set<Long> match = processMatchUrl(theIfNoneExist, myResourceType);
|
|
||||||
if (match.size() > 1) {
|
|
||||||
String msg = getContext().getLocalizer().getMessage(BaseFhirDao.class, "transactionOperationWithMultipleMatchFailure", "CREATE", theIfNoneExist, match.size());
|
|
||||||
throw new PreconditionFailedException(msg);
|
|
||||||
} else if (match.size() == 1) {
|
|
||||||
Long pid = match.iterator().next();
|
|
||||||
entity = myEntityManager.find(ResourceTable.class, pid);
|
|
||||||
return toMethodOutcome(entity, theResource).setCreated(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (theResource.getId().isEmpty() == false) {
|
|
||||||
if (isValidPid(theResource.getId())) {
|
|
||||||
throw new UnprocessableEntityException(
|
|
||||||
"This server cannot create an entity with a user-specified numeric ID - Client should not specify an ID when creating a new resource, or should include at least one letter in the ID to force a client-defined ID");
|
|
||||||
}
|
|
||||||
createForcedIdIfNeeded(entity, theResource.getId());
|
|
||||||
|
|
||||||
if (entity.getForcedId() != null) {
|
|
||||||
try {
|
|
||||||
translateForcedIdToPid(theResource.getId());
|
|
||||||
throw new UnprocessableEntityException(getContext().getLocalizer().getMessage(BaseFhirResourceDao.class, "duplicateCreateForcedId", theResource.getId().getIdPart()));
|
|
||||||
} catch (ResourceNotFoundException e) {
|
|
||||||
// good, this ID doesn't exist so we can create it
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
updateEntity(theResource, entity, false, null, thePerformIndexing, true);
|
|
||||||
|
|
||||||
DaoMethodOutcome outcome = toMethodOutcome(entity, theResource).setCreated(true);
|
|
||||||
|
|
||||||
notifyWriteCompleted();
|
|
||||||
ourLog.info("Processed create on {} in {}ms", myResourceName, w.getMillisAndRestart());
|
|
||||||
return outcome;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Predicate createCompositeParamPart(CriteriaBuilder builder, Root<ResourceTable> from, RuntimeSearchParam left, IQueryParameterType leftValue) {
|
private Predicate createCompositeParamPart(CriteriaBuilder builder, Root<ResourceTable> from, RuntimeSearchParam left, IQueryParameterType leftValue) {
|
||||||
Predicate retVal = null;
|
Predicate retVal = null;
|
||||||
switch (left.getParamType()) {
|
switch (left.getParamType()) {
|
||||||
|
@ -979,6 +947,50 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
||||||
return toMethodOutcome(savedEntity, null);
|
return toMethodOutcome(savedEntity, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private DaoMethodOutcome doCreate(T theResource, String theIfNoneExist, boolean thePerformIndexing) {
|
||||||
|
StopWatch w = new StopWatch();
|
||||||
|
ResourceTable entity = new ResourceTable();
|
||||||
|
entity.setResourceType(toResourceName(theResource));
|
||||||
|
|
||||||
|
if (isNotBlank(theIfNoneExist)) {
|
||||||
|
Set<Long> match = processMatchUrl(theIfNoneExist, myResourceType);
|
||||||
|
if (match.size() > 1) {
|
||||||
|
String msg = getContext().getLocalizer().getMessage(BaseFhirDao.class, "transactionOperationWithMultipleMatchFailure", "CREATE", theIfNoneExist, match.size());
|
||||||
|
throw new PreconditionFailedException(msg);
|
||||||
|
} else if (match.size() == 1) {
|
||||||
|
Long pid = match.iterator().next();
|
||||||
|
entity = myEntityManager.find(ResourceTable.class, pid);
|
||||||
|
return toMethodOutcome(entity, theResource).setCreated(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (theResource.getId().isEmpty() == false) {
|
||||||
|
if (isValidPid(theResource.getId())) {
|
||||||
|
throw new UnprocessableEntityException(
|
||||||
|
"This server cannot create an entity with a user-specified numeric ID - Client should not specify an ID when creating a new resource, or should include at least one letter in the ID to force a client-defined ID");
|
||||||
|
}
|
||||||
|
createForcedIdIfNeeded(entity, theResource.getId());
|
||||||
|
|
||||||
|
if (entity.getForcedId() != null) {
|
||||||
|
try {
|
||||||
|
translateForcedIdToPid(theResource.getId());
|
||||||
|
throw new UnprocessableEntityException(getContext().getLocalizer().getMessage(BaseFhirResourceDao.class, "duplicateCreateForcedId", theResource.getId().getIdPart()));
|
||||||
|
} catch (ResourceNotFoundException e) {
|
||||||
|
// good, this ID doesn't exist so we can create it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
updateEntity(theResource, entity, false, null, thePerformIndexing, true);
|
||||||
|
|
||||||
|
DaoMethodOutcome outcome = toMethodOutcome(entity, theResource).setCreated(true);
|
||||||
|
|
||||||
|
notifyWriteCompleted();
|
||||||
|
ourLog.info("Processed create on {} in {}ms", myResourceName, w.getMillisAndRestart());
|
||||||
|
return outcome;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TagList getAllResourceTags() {
|
public TagList getAllResourceTags() {
|
||||||
StopWatch w = new StopWatch();
|
StopWatch w = new StopWatch();
|
||||||
|
@ -987,6 +999,8 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
||||||
return tags;
|
return tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected abstract List<Object> getIncludeValues(FhirTerser theTerser, Include theInclude, IResource theResource, RuntimeResourceDefinition theResourceDef);
|
||||||
|
|
||||||
public Class<T> getResourceType() {
|
public Class<T> getResourceType() {
|
||||||
return myResourceType;
|
return myResourceType;
|
||||||
}
|
}
|
||||||
|
@ -1092,6 +1106,11 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer preferredPageSize() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int size() {
|
public int size() {
|
||||||
return count;
|
return count;
|
||||||
|
@ -1140,6 +1159,159 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void loadReverseIncludes(List<Long> theMatches, Set<Include> theRevIncludes) {
|
||||||
|
if (theMatches.size() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
HashSet<Long> pidsToInclude = new HashSet<Long>();
|
||||||
|
|
||||||
|
for (Include nextInclude : theRevIncludes) {
|
||||||
|
boolean matchAll = "*".equals(nextInclude.getValue());
|
||||||
|
if (matchAll) {
|
||||||
|
String sql = "SELECT r FROM ResourceLink r WHERE r.myTargetResourcePid IN (:target_pids)";
|
||||||
|
TypedQuery<ResourceLink> q = myEntityManager.createQuery(sql, ResourceLink.class);
|
||||||
|
q.setParameter("target_pids", theMatches);
|
||||||
|
List<ResourceLink> results = q.getResultList();
|
||||||
|
for (ResourceLink resourceLink : results) {
|
||||||
|
pidsToInclude.add(resourceLink.getSourceResourcePid());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int colonIdx = nextInclude.getValue().indexOf(':');
|
||||||
|
if (colonIdx < 2) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String resType = nextInclude.getValue().substring(0, colonIdx);
|
||||||
|
RuntimeResourceDefinition def = getContext().getResourceDefinition(resType);
|
||||||
|
if (def == null) {
|
||||||
|
ourLog.warn("Unknown resource type in _revinclude=" + nextInclude.getValue());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String paramName = nextInclude.getValue().substring(colonIdx + 1);
|
||||||
|
RuntimeSearchParam param = def.getSearchParam(paramName);
|
||||||
|
if (param == null) {
|
||||||
|
ourLog.warn("Unknown param name in _revinclude=" + nextInclude.getValue());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String nextPath : param.getPathsSplit()) {
|
||||||
|
String sql = "SELECT r FROM ResourceLink r WHERE r.mySourcePath = :src_path AND r.myTargetResourcePid IN (:target_pids)";
|
||||||
|
TypedQuery<ResourceLink> q = myEntityManager.createQuery(sql, ResourceLink.class);
|
||||||
|
q.setParameter("src_path", nextPath);
|
||||||
|
q.setParameter("target_pids", theMatches);
|
||||||
|
List<ResourceLink> results = q.getResultList();
|
||||||
|
for (ResourceLink resourceLink : results) {
|
||||||
|
pidsToInclude.add(resourceLink.getSourceResourcePid());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
theMatches.addAll(pidsToInclude);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MetaDt metaAddOperation(IdDt theResourceId, MetaDt theMetaAdd) {
|
||||||
|
StopWatch w = new StopWatch();
|
||||||
|
BaseHasResource entity = readEntity(theResourceId);
|
||||||
|
if (entity == null) {
|
||||||
|
throw new ResourceNotFoundException(theResourceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<TagDefinition> tags = toTagList(theMetaAdd);
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
for (TagDefinition nextDef : tags) {
|
||||||
|
|
||||||
|
boolean hasTag = false;
|
||||||
|
for (BaseTag next : new ArrayList<BaseTag>(entity.getTags())) {
|
||||||
|
if (ObjectUtil.equals(next.getTag().getTagType(), nextDef.getTagType()) &&
|
||||||
|
ObjectUtil.equals(next.getTag().getSystem(), nextDef.getSystem()) &&
|
||||||
|
ObjectUtil.equals(next.getTag().getCode(), nextDef.getCode())) {
|
||||||
|
hasTag = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasTag) {
|
||||||
|
entity.setHasTags(true);
|
||||||
|
|
||||||
|
TagDefinition def = getTag(nextDef.getTagType(), nextDef.getSystem(), nextDef.getCode(), nextDef.getDisplay());
|
||||||
|
BaseTag newEntity = entity.addTag(def);
|
||||||
|
myEntityManager.persist(newEntity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//@formatter:on
|
||||||
|
|
||||||
|
myEntityManager.merge(entity);
|
||||||
|
notifyWriteCompleted();
|
||||||
|
ourLog.info("Processed metaAddOperation on {} in {}ms", new Object[] { theResourceId, w.getMillisAndRestart() });
|
||||||
|
|
||||||
|
return metaGetOperation(theResourceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MetaDt metaDeleteOperation(IdDt theResourceId, MetaDt theMetaDel) {
|
||||||
|
StopWatch w = new StopWatch();
|
||||||
|
BaseHasResource entity = readEntity(theResourceId);
|
||||||
|
if (entity == null) {
|
||||||
|
throw new ResourceNotFoundException(theResourceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<TagDefinition> tags = toTagList(theMetaDel);
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
for (TagDefinition nextDef : tags) {
|
||||||
|
for (BaseTag next : new ArrayList<BaseTag>(entity.getTags())) {
|
||||||
|
if (ObjectUtil.equals(next.getTag().getTagType(), nextDef.getTagType()) &&
|
||||||
|
ObjectUtil.equals(next.getTag().getSystem(), nextDef.getSystem()) &&
|
||||||
|
ObjectUtil.equals(next.getTag().getCode(), nextDef.getCode())) {
|
||||||
|
myEntityManager.remove(next);
|
||||||
|
entity.getTags().remove(next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//@formatter:on
|
||||||
|
|
||||||
|
if (entity.getTags().isEmpty()) {
|
||||||
|
entity.setHasTags(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
myEntityManager.merge(entity);
|
||||||
|
|
||||||
|
ourLog.info("Processed metaDeleteOperation on {} in {}ms", new Object[] { theResourceId.getValue(), w.getMillisAndRestart() });
|
||||||
|
|
||||||
|
return metaGetOperation(theResourceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MetaDt metaGetOperation() {
|
||||||
|
String sql = "SELECT d FROM TagDefinition d WHERE d.myId IN (SELECT DISTINCT t.myTagId FROM ResourceTag t WHERE t.myResourceType = :res_type)";
|
||||||
|
TypedQuery<TagDefinition> q = myEntityManager.createQuery(sql, TagDefinition.class);
|
||||||
|
q.setParameter("res_type", myResourceName);
|
||||||
|
List<TagDefinition> tagDefinitions = q.getResultList();
|
||||||
|
|
||||||
|
MetaDt retVal = super.toMetaDt(tagDefinitions);
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MetaDt metaGetOperation(IdDt theId) {
|
||||||
|
Long pid = super.translateForcedIdToPid(theId);
|
||||||
|
|
||||||
|
String sql = "SELECT d FROM TagDefinition d WHERE d.myId IN (SELECT DISTINCT t.myTagId FROM ResourceTag t WHERE t.myResourceType = :res_type AND t.myResourceId = :res_id)";
|
||||||
|
TypedQuery<TagDefinition> q = myEntityManager.createQuery(sql, TagDefinition.class);
|
||||||
|
q.setParameter("res_type", myResourceName);
|
||||||
|
q.setParameter("res_id", pid);
|
||||||
|
List<TagDefinition> tagDefinitions = q.getResultList();
|
||||||
|
|
||||||
|
MetaDt retVal = super.toMetaDt(tagDefinitions);
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void postConstruct() {
|
public void postConstruct() {
|
||||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(myResourceType);
|
RuntimeResourceDefinition def = getContext().getResourceDefinition(myResourceType);
|
||||||
|
@ -1341,7 +1513,6 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
||||||
}
|
}
|
||||||
|
|
||||||
IBundleProvider retVal = new IBundleProvider() {
|
IBundleProvider retVal = new IBundleProvider() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InstantDt getPublished() {
|
public InstantDt getPublished() {
|
||||||
return now;
|
return now;
|
||||||
|
@ -1422,6 +1593,11 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer preferredPageSize() {
|
||||||
|
return theParams.getCount();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int size() {
|
public int size() {
|
||||||
return pids.size();
|
return pids.size();
|
||||||
|
@ -1433,77 +1609,11 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<IResource> addResourcesAsIncludesById(List<IResource> theListToPopulate, Set<IdDt> includePids, List<IResource> resources) {
|
|
||||||
if (!includePids.isEmpty()) {
|
|
||||||
ourLog.info("Loading {} included resources", includePids.size());
|
|
||||||
resources = loadResourcesById(includePids);
|
|
||||||
for (IResource next : resources) {
|
|
||||||
ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE.put(next, BundleEntrySearchModeEnum.INCLUDE);
|
|
||||||
}
|
|
||||||
theListToPopulate.addAll(resources);
|
|
||||||
}
|
|
||||||
return resources;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void loadReverseIncludes(List<Long> theMatches, Set<Include> theRevIncludes) {
|
|
||||||
if (theMatches.size() == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
HashSet<Long> pidsToInclude = new HashSet<Long>();
|
|
||||||
|
|
||||||
for (Include nextInclude : theRevIncludes) {
|
|
||||||
boolean matchAll = "*".equals(nextInclude.getValue());
|
|
||||||
if (matchAll) {
|
|
||||||
String sql = "SELECT r FROM ResourceLink r WHERE r.myTargetResourcePid IN (:target_pids)";
|
|
||||||
TypedQuery<ResourceLink> q = myEntityManager.createQuery(sql, ResourceLink.class);
|
|
||||||
q.setParameter("target_pids", theMatches);
|
|
||||||
List<ResourceLink> results = q.getResultList();
|
|
||||||
for (ResourceLink resourceLink : results) {
|
|
||||||
pidsToInclude.add(resourceLink.getSourceResourcePid());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
int colonIdx = nextInclude.getValue().indexOf(':');
|
|
||||||
if (colonIdx < 2) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
String resType = nextInclude.getValue().substring(0, colonIdx);
|
|
||||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(resType);
|
|
||||||
if (def == null) {
|
|
||||||
ourLog.warn("Unknown resource type in _revinclude=" + nextInclude.getValue());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
String paramName = nextInclude.getValue().substring(colonIdx + 1);
|
|
||||||
RuntimeSearchParam param = def.getSearchParam(paramName);
|
|
||||||
if (param == null) {
|
|
||||||
ourLog.warn("Unknown param name in _revinclude=" + nextInclude.getValue());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (String nextPath : param.getPathsSplit()) {
|
|
||||||
String sql = "SELECT r FROM ResourceLink r WHERE r.mySourcePath = :src_path AND r.myTargetResourcePid IN (:target_pids)";
|
|
||||||
TypedQuery<ResourceLink> q = myEntityManager.createQuery(sql, ResourceLink.class);
|
|
||||||
q.setParameter("src_path", nextPath);
|
|
||||||
q.setParameter("target_pids", theMatches);
|
|
||||||
List<ResourceLink> results = q.getResultList();
|
|
||||||
for (ResourceLink resourceLink : results) {
|
|
||||||
pidsToInclude.add(resourceLink.getSourceResourcePid());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
theMatches.addAll(pidsToInclude);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBundleProvider search(String theParameterName, IQueryParameterType theValue) {
|
public IBundleProvider search(String theParameterName, IQueryParameterType theValue) {
|
||||||
return search(Collections.singletonMap(theParameterName, theValue));
|
return search(Collections.singletonMap(theParameterName, theValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract List<Object> getIncludeValues(FhirTerser theTerser, Include theInclude, IResource theResource, RuntimeResourceDefinition theResourceDef);
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<Long> searchForIds(Map<String, IQueryParameterType> theParams) {
|
public Set<Long> searchForIds(Map<String, IQueryParameterType> theParams) {
|
||||||
SearchParameterMap map = new SearchParameterMap();
|
SearchParameterMap map = new SearchParameterMap();
|
||||||
|
@ -1708,6 +1818,22 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
||||||
return qp;
|
return qp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ArrayList<TagDefinition> toTagList(MetaDt theMeta) {
|
||||||
|
ArrayList<TagDefinition> retVal = new ArrayList<TagDefinition>();
|
||||||
|
|
||||||
|
for (CodingDt next : theMeta.getTag()) {
|
||||||
|
retVal.add(new TagDefinition(TagTypeEnum.TAG, next.getSystem(), next.getCode(), next.getDisplay()));
|
||||||
|
}
|
||||||
|
for (CodingDt next : theMeta.getSecurity()) {
|
||||||
|
retVal.add(new TagDefinition(TagTypeEnum.SECURITY_LABEL, next.getSystem(), next.getCode(), next.getDisplay()));
|
||||||
|
}
|
||||||
|
for (UriDt next : theMeta.getProfile()) {
|
||||||
|
retVal.add(new TagDefinition(TagTypeEnum.PROFILE, BaseFhirDao.NS_JPA_PROFILE, next.getValue(), null));
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DaoMethodOutcome update(T theResource) {
|
public DaoMethodOutcome update(T theResource) {
|
||||||
return update(theResource, null);
|
return update(theResource, null);
|
||||||
|
@ -1788,121 +1914,4 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public MetaDt metaGetOperation() {
|
|
||||||
String sql = "SELECT d FROM TagDefinition d WHERE d.myId IN (SELECT DISTINCT t.myTagId FROM ResourceTag t WHERE t.myResourceType = :res_type)";
|
|
||||||
TypedQuery<TagDefinition> q = myEntityManager.createQuery(sql, TagDefinition.class);
|
|
||||||
q.setParameter("res_type", myResourceName);
|
|
||||||
List<TagDefinition> tagDefinitions = q.getResultList();
|
|
||||||
|
|
||||||
MetaDt retVal = super.toMetaDt(tagDefinitions);
|
|
||||||
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MetaDt metaGetOperation(IdDt theId) {
|
|
||||||
Long pid = super.translateForcedIdToPid(theId);
|
|
||||||
|
|
||||||
String sql = "SELECT d FROM TagDefinition d WHERE d.myId IN (SELECT DISTINCT t.myTagId FROM ResourceTag t WHERE t.myResourceType = :res_type AND t.myResourceId = :res_id)";
|
|
||||||
TypedQuery<TagDefinition> q = myEntityManager.createQuery(sql, TagDefinition.class);
|
|
||||||
q.setParameter("res_type", myResourceName);
|
|
||||||
q.setParameter("res_id", pid);
|
|
||||||
List<TagDefinition> tagDefinitions = q.getResultList();
|
|
||||||
|
|
||||||
MetaDt retVal = super.toMetaDt(tagDefinitions);
|
|
||||||
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MetaDt metaDeleteOperation(IdDt theResourceId, MetaDt theMetaDel) {
|
|
||||||
StopWatch w = new StopWatch();
|
|
||||||
BaseHasResource entity = readEntity(theResourceId);
|
|
||||||
if (entity == null) {
|
|
||||||
throw new ResourceNotFoundException(theResourceId);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<TagDefinition> tags = toTagList(theMetaDel);
|
|
||||||
|
|
||||||
//@formatter:off
|
|
||||||
for (TagDefinition nextDef : tags) {
|
|
||||||
for (BaseTag next : new ArrayList<BaseTag>(entity.getTags())) {
|
|
||||||
if (ObjectUtil.equals(next.getTag().getTagType(), nextDef.getTagType()) &&
|
|
||||||
ObjectUtil.equals(next.getTag().getSystem(), nextDef.getSystem()) &&
|
|
||||||
ObjectUtil.equals(next.getTag().getCode(), nextDef.getCode())) {
|
|
||||||
myEntityManager.remove(next);
|
|
||||||
entity.getTags().remove(next);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//@formatter:on
|
|
||||||
|
|
||||||
if (entity.getTags().isEmpty()) {
|
|
||||||
entity.setHasTags(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
myEntityManager.merge(entity);
|
|
||||||
|
|
||||||
ourLog.info("Processed metaDeleteOperation on {} in {}ms", new Object[] { theResourceId.getValue(), w.getMillisAndRestart() });
|
|
||||||
|
|
||||||
return metaGetOperation(theResourceId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MetaDt metaAddOperation(IdDt theResourceId, MetaDt theMetaAdd) {
|
|
||||||
StopWatch w = new StopWatch();
|
|
||||||
BaseHasResource entity = readEntity(theResourceId);
|
|
||||||
if (entity == null) {
|
|
||||||
throw new ResourceNotFoundException(theResourceId);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<TagDefinition> tags = toTagList(theMetaAdd);
|
|
||||||
|
|
||||||
//@formatter:off
|
|
||||||
for (TagDefinition nextDef : tags) {
|
|
||||||
|
|
||||||
boolean hasTag = false;
|
|
||||||
for (BaseTag next : new ArrayList<BaseTag>(entity.getTags())) {
|
|
||||||
if (ObjectUtil.equals(next.getTag().getTagType(), nextDef.getTagType()) &&
|
|
||||||
ObjectUtil.equals(next.getTag().getSystem(), nextDef.getSystem()) &&
|
|
||||||
ObjectUtil.equals(next.getTag().getCode(), nextDef.getCode())) {
|
|
||||||
hasTag = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasTag) {
|
|
||||||
entity.setHasTags(true);
|
|
||||||
|
|
||||||
TagDefinition def = getTag(nextDef.getTagType(), nextDef.getSystem(), nextDef.getCode(), nextDef.getDisplay());
|
|
||||||
BaseTag newEntity = entity.addTag(def);
|
|
||||||
myEntityManager.persist(newEntity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//@formatter:on
|
|
||||||
|
|
||||||
myEntityManager.merge(entity);
|
|
||||||
notifyWriteCompleted();
|
|
||||||
ourLog.info("Processed metaAddOperation on {} in {}ms", new Object[] { theResourceId, w.getMillisAndRestart() });
|
|
||||||
|
|
||||||
return metaGetOperation(theResourceId);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ArrayList<TagDefinition> toTagList(MetaDt theMeta) {
|
|
||||||
ArrayList<TagDefinition> retVal = new ArrayList<TagDefinition>();
|
|
||||||
|
|
||||||
for (CodingDt next : theMeta.getTag()) {
|
|
||||||
retVal.add(new TagDefinition(TagTypeEnum.TAG, next.getSystem(), next.getCode(), next.getDisplay()));
|
|
||||||
}
|
|
||||||
for (CodingDt next : theMeta.getSecurity()) {
|
|
||||||
retVal.add(new TagDefinition(TagTypeEnum.SECURITY_LABEL, next.getSystem(), next.getCode(), next.getDisplay()));
|
|
||||||
}
|
|
||||||
for (UriDt next : theMeta.getProfile()) {
|
|
||||||
retVal.add(new TagDefinition(TagTypeEnum.PROFILE, BaseFhirDao.NS_JPA_PROFILE, next.getValue(), null));
|
|
||||||
}
|
|
||||||
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ import java.util.Date;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.TreeSet;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
|
@ -50,6 +51,7 @@ import ca.uhn.fhir.model.dstu.resource.Practitioner;
|
||||||
import ca.uhn.fhir.model.dstu2.composite.PeriodDt;
|
import ca.uhn.fhir.model.dstu2.composite.PeriodDt;
|
||||||
import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt;
|
import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
|
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
|
||||||
|
import ca.uhn.fhir.model.dstu2.resource.Condition;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.DiagnosticOrder;
|
import ca.uhn.fhir.model.dstu2.resource.DiagnosticOrder;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.DocumentManifest;
|
import ca.uhn.fhir.model.dstu2.resource.DocumentManifest;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.DocumentReference;
|
import ca.uhn.fhir.model.dstu2.resource.DocumentReference;
|
||||||
|
@ -62,7 +64,9 @@ import ca.uhn.fhir.model.dstu2.resource.Parameters;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||||
import ca.uhn.fhir.model.dstu2.valueset.EncounterClassEnum;
|
import ca.uhn.fhir.model.dstu2.valueset.EncounterClassEnum;
|
||||||
import ca.uhn.fhir.model.dstu2.valueset.EncounterStateEnum;
|
import ca.uhn.fhir.model.dstu2.valueset.EncounterStateEnum;
|
||||||
|
import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum;
|
||||||
import ca.uhn.fhir.model.primitive.IdDt;
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
|
import ca.uhn.fhir.model.primitive.IntegerDt;
|
||||||
import ca.uhn.fhir.model.valueset.BundleEntrySearchModeEnum;
|
import ca.uhn.fhir.model.valueset.BundleEntrySearchModeEnum;
|
||||||
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
||||||
import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
|
import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
|
||||||
|
@ -127,15 +131,15 @@ public class ResourceProviderDstu2Test {
|
||||||
|
|
||||||
HttpPost post = new HttpPost(ourServerBase + "/Patient");
|
HttpPost post = new HttpPost(ourServerBase + "/Patient");
|
||||||
post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||||
|
|
||||||
CloseableHttpResponse response = ourHttpClient.execute(post);
|
CloseableHttpResponse response = ourHttpClient.execute(post);
|
||||||
try {
|
try {
|
||||||
|
|
||||||
assertEquals(201, response.getStatusLine().getStatusCode());
|
assertEquals(201, response.getStatusLine().getStatusCode());
|
||||||
assertThat(response.getFirstHeader(Constants.HEADER_LOCATION_LC).getValue(), startsWith(ourServerBase + "/Patient/"));
|
assertThat(response.getFirstHeader(Constants.HEADER_LOCATION_LC).getValue(), startsWith(ourServerBase + "/Patient/"));
|
||||||
assertThat(response.getFirstHeader(Constants.HEADER_LOCATION_LC).getValue(), endsWith("/_history/1"));
|
assertThat(response.getFirstHeader(Constants.HEADER_LOCATION_LC).getValue(), endsWith("/_history/1"));
|
||||||
assertThat(response.getFirstHeader(Constants.HEADER_LOCATION_LC).getValue(), not(containsString("1777")));
|
assertThat(response.getFirstHeader(Constants.HEADER_LOCATION_LC).getValue(), not(containsString("1777")));
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
response.close();
|
response.close();
|
||||||
}
|
}
|
||||||
|
@ -144,7 +148,7 @@ public class ResourceProviderDstu2Test {
|
||||||
@Test
|
@Test
|
||||||
public void testCreateResourceConditional() throws IOException {
|
public void testCreateResourceConditional() throws IOException {
|
||||||
String methodName = "testCreateResourceConditional";
|
String methodName = "testCreateResourceConditional";
|
||||||
|
|
||||||
Patient pt = new Patient();
|
Patient pt = new Patient();
|
||||||
pt.addName().addFamily(methodName);
|
pt.addName().addFamily(methodName);
|
||||||
String resource = ourFhirCtx.newXmlParser().encodeResourceToString(pt);
|
String resource = ourFhirCtx.newXmlParser().encodeResourceToString(pt);
|
||||||
|
@ -161,7 +165,7 @@ public class ResourceProviderDstu2Test {
|
||||||
} finally {
|
} finally {
|
||||||
response.close();
|
response.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
post = new HttpPost(ourServerBase + "/Patient");
|
post = new HttpPost(ourServerBase + "/Patient");
|
||||||
post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||||
post.addHeader(Constants.HEADER_IF_NONE_EXIST, "Patient?name=" + methodName);
|
post.addHeader(Constants.HEADER_IF_NONE_EXIST, "Patient?name=" + methodName);
|
||||||
|
@ -173,13 +177,13 @@ public class ResourceProviderDstu2Test {
|
||||||
} finally {
|
} finally {
|
||||||
response.close();
|
response.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateResourceConditional() throws IOException {
|
public void testUpdateResourceConditional() throws IOException {
|
||||||
String methodName = "testUpdateResourceConditional";
|
String methodName = "testUpdateResourceConditional";
|
||||||
|
|
||||||
Patient pt = new Patient();
|
Patient pt = new Patient();
|
||||||
pt.addName().addFamily(methodName);
|
pt.addName().addFamily(methodName);
|
||||||
String resource = ourFhirCtx.newXmlParser().encodeResourceToString(pt);
|
String resource = ourFhirCtx.newXmlParser().encodeResourceToString(pt);
|
||||||
|
@ -196,7 +200,7 @@ public class ResourceProviderDstu2Test {
|
||||||
} finally {
|
} finally {
|
||||||
response.close();
|
response.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpPut put = new HttpPut(ourServerBase + "/Patient?name=" + methodName);
|
HttpPut put = new HttpPut(ourServerBase + "/Patient?name=" + methodName);
|
||||||
put.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
put.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||||
response = ourHttpClient.execute(put);
|
response = ourHttpClient.execute(put);
|
||||||
|
@ -208,13 +212,13 @@ public class ResourceProviderDstu2Test {
|
||||||
} finally {
|
} finally {
|
||||||
response.close();
|
response.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDeleteResourceConditional() throws IOException {
|
public void testDeleteResourceConditional() throws IOException {
|
||||||
String methodName = "testDeleteResourceConditional";
|
String methodName = "testDeleteResourceConditional";
|
||||||
|
|
||||||
Patient pt = new Patient();
|
Patient pt = new Patient();
|
||||||
pt.addName().addFamily(methodName);
|
pt.addName().addFamily(methodName);
|
||||||
String resource = ourFhirCtx.newXmlParser().encodeResourceToString(pt);
|
String resource = ourFhirCtx.newXmlParser().encodeResourceToString(pt);
|
||||||
|
@ -231,7 +235,7 @@ public class ResourceProviderDstu2Test {
|
||||||
} finally {
|
} finally {
|
||||||
response.close();
|
response.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpDelete delete = new HttpDelete(ourServerBase + "/Patient?name=" + methodName);
|
HttpDelete delete = new HttpDelete(ourServerBase + "/Patient?name=" + methodName);
|
||||||
response = ourHttpClient.execute(delete);
|
response = ourHttpClient.execute(delete);
|
||||||
try {
|
try {
|
||||||
|
@ -239,7 +243,7 @@ public class ResourceProviderDstu2Test {
|
||||||
} finally {
|
} finally {
|
||||||
response.close();
|
response.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpGet read = new HttpGet(ourServerBase + "/Patient/" + id.getIdPart());
|
HttpGet read = new HttpGet(ourServerBase + "/Patient/" + id.getIdPart());
|
||||||
response = ourHttpClient.execute(read);
|
response = ourHttpClient.execute(read);
|
||||||
try {
|
try {
|
||||||
|
@ -257,7 +261,7 @@ public class ResourceProviderDstu2Test {
|
||||||
@Test
|
@Test
|
||||||
public void testReadAllInstancesOfType() throws Exception {
|
public void testReadAllInstancesOfType() throws Exception {
|
||||||
Patient pat;
|
Patient pat;
|
||||||
|
|
||||||
pat = new Patient();
|
pat = new Patient();
|
||||||
pat.addIdentifier().setSystem("urn:system").setValue("testReadAllInstancesOfType_01");
|
pat.addIdentifier().setSystem("urn:system").setValue("testReadAllInstancesOfType_01");
|
||||||
ourClient.create().resource(pat).prettyPrint().encodedXml().execute().getId();
|
ourClient.create().resource(pat).prettyPrint().encodedXml().execute().getId();
|
||||||
|
@ -277,11 +281,10 @@ public class ResourceProviderDstu2Test {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchWithInclude() throws Exception {
|
public void testSearchWithInclude() throws Exception {
|
||||||
Organization org = new Organization();
|
Organization org = new Organization();
|
||||||
org.addIdentifier().setSystem("urn:system:rpdstu2").setValue( "testSearchWithInclude01");
|
org.addIdentifier().setSystem("urn:system:rpdstu2").setValue("testSearchWithInclude01");
|
||||||
IdDt orgId = ourClient.create().resource(org).prettyPrint().encodedXml().execute().getId();
|
IdDt orgId = ourClient.create().resource(org).prettyPrint().encodedXml().execute().getId();
|
||||||
|
|
||||||
Patient pat = new Patient();
|
Patient pat = new Patient();
|
||||||
|
@ -298,7 +301,7 @@ public class ResourceProviderDstu2Test {
|
||||||
.prettyPrint()
|
.prettyPrint()
|
||||||
.execute();
|
.execute();
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
|
|
||||||
assertEquals(2, found.size());
|
assertEquals(2, found.size());
|
||||||
assertEquals(Patient.class, found.getEntries().get(0).getResource().getClass());
|
assertEquals(Patient.class, found.getEntries().get(0).getResource().getClass());
|
||||||
assertEquals(BundleEntrySearchModeEnum.MATCH, found.getEntries().get(0).getSearchMode().getValueAsEnum());
|
assertEquals(BundleEntrySearchModeEnum.MATCH, found.getEntries().get(0).getSearchMode().getValueAsEnum());
|
||||||
|
@ -311,16 +314,16 @@ public class ResourceProviderDstu2Test {
|
||||||
@Test
|
@Test
|
||||||
public void testEverythingOperation() throws Exception {
|
public void testEverythingOperation() throws Exception {
|
||||||
String methodName = "testEverythingOperation";
|
String methodName = "testEverythingOperation";
|
||||||
|
|
||||||
Organization org1 = new Organization();
|
Organization org1 = new Organization();
|
||||||
org1.setName(methodName + "1");
|
org1.setName(methodName + "1");
|
||||||
IdDt orgId1 = ourClient.create().resource(org1).execute().getId();
|
IdDt orgId1 = ourClient.create().resource(org1).execute().getId();
|
||||||
|
|
||||||
Patient p = new Patient();
|
Patient p = new Patient();
|
||||||
p.addName().addFamily(methodName);
|
p.addName().addFamily(methodName);
|
||||||
p.getManagingOrganization().setReference(orgId1);
|
p.getManagingOrganization().setReference(orgId1);
|
||||||
IdDt patientId = ourClient.create().resource(p).execute().getId();
|
IdDt patientId = ourClient.create().resource(p).execute().getId();
|
||||||
|
|
||||||
Organization org2 = new Organization();
|
Organization org2 = new Organization();
|
||||||
org2.setName(methodName + "1");
|
org2.setName(methodName + "1");
|
||||||
IdDt orgId2 = ourClient.create().resource(org2).execute().getId();
|
IdDt orgId2 = ourClient.create().resource(org2).execute().getId();
|
||||||
|
@ -328,31 +331,30 @@ public class ResourceProviderDstu2Test {
|
||||||
Device dev = new Device();
|
Device dev = new Device();
|
||||||
dev.setModel(methodName);
|
dev.setModel(methodName);
|
||||||
dev.getOwner().setReference(orgId2);
|
dev.getOwner().setReference(orgId2);
|
||||||
IdDt devId = ourClient.create().resource(dev).execute().getId();
|
IdDt devId = ourClient.create().resource(dev).execute().getId();
|
||||||
|
|
||||||
Observation obs = new Observation();
|
Observation obs = new Observation();
|
||||||
obs.getSubject().setReference(patientId);
|
obs.getSubject().setReference(patientId);
|
||||||
obs.getDevice().setReference(devId);
|
obs.getDevice().setReference(devId);
|
||||||
IdDt obsId = ourClient.create().resource(obs).execute().getId();
|
IdDt obsId = ourClient.create().resource(obs).execute().getId();
|
||||||
|
|
||||||
Encounter enc = new Encounter();
|
Encounter enc = new Encounter();
|
||||||
enc.getPatient().setReference(patientId);
|
enc.getPatient().setReference(patientId);
|
||||||
IdDt encId = ourClient.create().resource(enc).execute().getId();
|
IdDt encId = ourClient.create().resource(enc).execute().getId();
|
||||||
|
|
||||||
Parameters output = ourClient.operation().onInstance(patientId).named("everything").withNoParameters(Parameters.class).execute();
|
Parameters output = ourClient.operation().onInstance(patientId).named("everything").withNoParameters(Parameters.class).execute();
|
||||||
ca.uhn.fhir.model.dstu2.resource.Bundle b = (ca.uhn.fhir.model.dstu2.resource.Bundle) output.getParameterFirstRep().getResource();
|
ca.uhn.fhir.model.dstu2.resource.Bundle b = (ca.uhn.fhir.model.dstu2.resource.Bundle) output.getParameterFirstRep().getResource();
|
||||||
|
|
||||||
Set<IdDt> ids = new HashSet<IdDt>();
|
Set<IdDt> ids = new HashSet<IdDt>();
|
||||||
for (Entry next : b.getEntry()) {
|
for (Entry next : b.getEntry()) {
|
||||||
ids.add(next.getResource().getId());
|
ids.add(next.getResource().getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
assertThat(ids, containsInAnyOrder(patientId, devId, obsId, encId, orgId1, orgId2));
|
assertThat(ids, containsInAnyOrder(patientId, devId, obsId, encId, orgId1, orgId2));
|
||||||
|
|
||||||
// _revinclude's are counted but not _include's
|
// _revinclude's are counted but not _include's
|
||||||
assertEquals(3, b.getTotal().intValue());
|
assertEquals(3, b.getTotal().intValue());
|
||||||
|
|
||||||
ourLog.info(ids.toString());
|
ourLog.info(ids.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -360,33 +362,101 @@ public class ResourceProviderDstu2Test {
|
||||||
* See #147
|
* See #147
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testEverythingDoesnRepeatPatient() throws Exception {
|
public void testEverythingDoesntRepeatPatient() throws Exception {
|
||||||
ca.uhn.fhir.model.dstu2.resource.Bundle b;
|
ca.uhn.fhir.model.dstu2.resource.Bundle b;
|
||||||
b = ourFhirCtx.newJsonParser().parseResource(ca.uhn.fhir.model.dstu2.resource.Bundle.class, new InputStreamReader(ResourceProviderDstu2Test.class.getResourceAsStream("/bug147-bundle.json")));
|
b = ourFhirCtx.newJsonParser().parseResource(ca.uhn.fhir.model.dstu2.resource.Bundle.class, new InputStreamReader(ResourceProviderDstu2Test.class.getResourceAsStream("/bug147-bundle.json")));
|
||||||
|
|
||||||
ca.uhn.fhir.model.dstu2.resource.Bundle resp = ourClient.transaction().withBundle(b).execute();
|
ca.uhn.fhir.model.dstu2.resource.Bundle resp = ourClient.transaction().withBundle(b).execute();
|
||||||
|
|
||||||
ourLog.info(ourFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(resp));
|
|
||||||
|
|
||||||
IdDt patientId = new IdDt(resp.getEntry().get(1).getTransactionResponse().getLocation());
|
|
||||||
assertEquals("Patient", patientId.getResourceType());
|
|
||||||
|
|
||||||
Parameters output = ourClient.operation().onInstance(patientId).named("everything").withNoParameters(Parameters.class).execute();
|
|
||||||
b = (ca.uhn.fhir.model.dstu2.resource.Bundle) output.getParameterFirstRep().getResource();
|
|
||||||
|
|
||||||
List<IdDt> ids = new ArrayList<IdDt>();
|
List<IdDt> ids = new ArrayList<IdDt>();
|
||||||
boolean dupes = false;
|
for (Entry next : resp.getEntry()) {
|
||||||
for (Entry next : b.getEntry()) {
|
IdDt toAdd = new IdDt(next.getTransactionResponse().getLocation()).toUnqualifiedVersionless();
|
||||||
IdDt toAdd = next.getResource().getId().toUnqualifiedVersionless();
|
|
||||||
dupes = dupes | ids.contains(toAdd);
|
|
||||||
ids.add(toAdd);
|
ids.add(toAdd);
|
||||||
}
|
}
|
||||||
|
ourLog.info("Created: " + ids.toString());
|
||||||
ourLog.info(ids.toString());
|
|
||||||
|
IdDt patientId = new IdDt(resp.getEntry().get(1).getTransactionResponse().getLocation());
|
||||||
assertFalse(ids.toString(), dupes);
|
assertEquals("Patient", patientId.getResourceType());
|
||||||
|
|
||||||
|
{
|
||||||
|
Parameters output = ourClient.operation().onInstance(patientId).named("everything").withNoParameters(Parameters.class).execute();
|
||||||
|
b = (ca.uhn.fhir.model.dstu2.resource.Bundle) output.getParameterFirstRep().getResource();
|
||||||
|
|
||||||
|
ids = new ArrayList<IdDt>();
|
||||||
|
boolean dupes = false;
|
||||||
|
for (Entry next : b.getEntry()) {
|
||||||
|
IdDt toAdd = next.getResource().getId().toUnqualifiedVersionless();
|
||||||
|
dupes = dupes | ids.contains(toAdd);
|
||||||
|
ids.add(toAdd);
|
||||||
|
}
|
||||||
|
ourLog.info("$everything: " + ids.toString());
|
||||||
|
|
||||||
|
assertFalse(ids.toString(), dupes);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Condition/11 is the 11th resource and the default page size is 10 so we don't show the 11th.
|
||||||
|
*/
|
||||||
|
assertThat(ids.toString(), not(containsString("Condition")));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now try with a size specified
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
Parameters input = new Parameters();
|
||||||
|
input.addParameter().setName(Constants.PARAM_COUNT).setValue(new IntegerDt(100));
|
||||||
|
Parameters output = ourClient.operation().onInstance(patientId).named("everything").withParameters(input).execute();
|
||||||
|
b = (ca.uhn.fhir.model.dstu2.resource.Bundle) output.getParameterFirstRep().getResource();
|
||||||
|
|
||||||
|
ids = new ArrayList<IdDt>();
|
||||||
|
boolean dupes = false;
|
||||||
|
for (Entry next : b.getEntry()) {
|
||||||
|
IdDt toAdd = next.getResource().getId().toUnqualifiedVersionless();
|
||||||
|
dupes = dupes | ids.contains(toAdd);
|
||||||
|
ids.add(toAdd);
|
||||||
|
}
|
||||||
|
ourLog.info("$everything: " + ids.toString());
|
||||||
|
|
||||||
|
assertFalse(ids.toString(), dupes);
|
||||||
|
assertThat(ids.toString(), containsString("Condition"));
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See #148
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testEverythingIncludesCondition() throws Exception {
|
||||||
|
ca.uhn.fhir.model.dstu2.resource.Bundle b = new ca.uhn.fhir.model.dstu2.resource.Bundle();
|
||||||
|
Patient p = new Patient();
|
||||||
|
p.setId("1");
|
||||||
|
b.addEntry().setResource(p).getTransaction().setMethod(HTTPVerbEnum.POST);
|
||||||
|
|
||||||
|
Condition c = new Condition();
|
||||||
|
c.getPatient().setReference("Patient/1");
|
||||||
|
b.addEntry().setResource(c).getTransaction().setMethod(HTTPVerbEnum.POST);
|
||||||
|
|
||||||
|
ca.uhn.fhir.model.dstu2.resource.Bundle resp = ourClient.transaction().withBundle(b).execute();
|
||||||
|
|
||||||
|
ourLog.info(ourFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(resp));
|
||||||
|
|
||||||
|
IdDt patientId = new IdDt(resp.getEntry().get(1).getTransactionResponse().getLocation());
|
||||||
|
assertEquals("Patient", patientId.getResourceType());
|
||||||
|
|
||||||
|
Parameters output = ourClient.operation().onInstance(patientId).named("everything").withNoParameters(Parameters.class).execute();
|
||||||
|
b = (ca.uhn.fhir.model.dstu2.resource.Bundle) output.getParameterFirstRep().getResource();
|
||||||
|
|
||||||
|
List<IdDt> ids = new ArrayList<IdDt>();
|
||||||
|
for (Entry next : b.getEntry()) {
|
||||||
|
IdDt toAdd = next.getResource().getId().toUnqualifiedVersionless();
|
||||||
|
ids.add(toAdd);
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThat(ids.toString(), containsString("Patient/"));
|
||||||
|
assertThat(ids.toString(), containsString("Condition/"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCountParam() throws Exception {
|
public void testCountParam() throws Exception {
|
||||||
// NB this does not get used- The paging provider has its own limits built in
|
// NB this does not get used- The paging provider has its own limits built in
|
||||||
|
@ -435,7 +505,7 @@ public class ResourceProviderDstu2Test {
|
||||||
public void testDocumentManifestResources() throws Exception {
|
public void testDocumentManifestResources() throws Exception {
|
||||||
ourFhirCtx.getResourceDefinition(Practitioner.class);
|
ourFhirCtx.getResourceDefinition(Practitioner.class);
|
||||||
ourFhirCtx.getResourceDefinition(ca.uhn.fhir.model.dstu.resource.DocumentManifest.class);
|
ourFhirCtx.getResourceDefinition(ca.uhn.fhir.model.dstu.resource.DocumentManifest.class);
|
||||||
|
|
||||||
IGenericClient client = ourClient;
|
IGenericClient client = ourClient;
|
||||||
|
|
||||||
int initialSize = client.search().forResource(DocumentManifest.class).execute().size();
|
int initialSize = client.search().forResource(DocumentManifest.class).execute().size();
|
||||||
|
@ -477,7 +547,7 @@ public class ResourceProviderDstu2Test {
|
||||||
int initialSize = client.search().forResource(DiagnosticOrder.class).execute().size();
|
int initialSize = client.search().forResource(DiagnosticOrder.class).execute().size();
|
||||||
|
|
||||||
DiagnosticOrder res = new DiagnosticOrder();
|
DiagnosticOrder res = new DiagnosticOrder();
|
||||||
res.addIdentifier().setSystem("urn:foo").setValue( "123");
|
res.addIdentifier().setSystem("urn:foo").setValue("123");
|
||||||
|
|
||||||
client.create().resource(res).execute();
|
client.create().resource(res).execute();
|
||||||
|
|
||||||
|
@ -737,7 +807,7 @@ public class ResourceProviderDstu2Test {
|
||||||
RestfulServer restServer = new RestfulServer();
|
RestfulServer restServer = new RestfulServer();
|
||||||
ourFhirCtx = FhirContext.forDstu2();
|
ourFhirCtx = FhirContext.forDstu2();
|
||||||
restServer.setFhirContext(ourFhirCtx);
|
restServer.setFhirContext(ourFhirCtx);
|
||||||
|
|
||||||
ourServerBase = "http://localhost:" + port + "/fhir/context";
|
ourServerBase = "http://localhost:" + port + "/fhir/context";
|
||||||
|
|
||||||
ourAppCtx = new ClassPathXmlApplicationContext("hapi-fhir-server-resourceproviders-dstu2.xml", "fhir-jpabase-spring-test-config.xml");
|
ourAppCtx = new ClassPathXmlApplicationContext("hapi-fhir-server-resourceproviders-dstu2.xml", "fhir-jpabase-spring-test-config.xml");
|
||||||
|
@ -771,7 +841,7 @@ public class ResourceProviderDstu2Test {
|
||||||
ourFhirCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000);
|
ourFhirCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000);
|
||||||
ourClient = ourFhirCtx.newRestfulGenericClient(ourServerBase);
|
ourClient = ourFhirCtx.newRestfulGenericClient(ourServerBase);
|
||||||
ourClient.registerInterceptor(new LoggingInterceptor(true));
|
ourClient.registerInterceptor(new LoggingInterceptor(true));
|
||||||
|
|
||||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
||||||
HttpClientBuilder builder = HttpClientBuilder.create();
|
HttpClientBuilder builder = HttpClientBuilder.create();
|
||||||
builder.setConnectionManager(connectionManager);
|
builder.setConnectionManager(connectionManager);
|
||||||
|
|
|
@ -24,7 +24,11 @@
|
||||||
"entry":
|
"entry":
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"transaction": { "method":"POST" },
|
"transaction":
|
||||||
|
{
|
||||||
|
"method": "POST"
|
||||||
|
},
|
||||||
|
|
||||||
"resource":
|
"resource":
|
||||||
{
|
{
|
||||||
"resourceType": "Patient",
|
"resourceType": "Patient",
|
||||||
|
@ -114,7 +118,11 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"transaction": { "method":"POST" },
|
"transaction":
|
||||||
|
{
|
||||||
|
"method": "POST"
|
||||||
|
},
|
||||||
|
|
||||||
"resource":
|
"resource":
|
||||||
{
|
{
|
||||||
"resourceType": "Encounter",
|
"resourceType": "Encounter",
|
||||||
|
@ -148,7 +156,11 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"transaction": { "method":"POST" },
|
"transaction":
|
||||||
|
{
|
||||||
|
"method": "POST"
|
||||||
|
},
|
||||||
|
|
||||||
"resource":
|
"resource":
|
||||||
{
|
{
|
||||||
"resourceType": "ClinicalImpression",
|
"resourceType": "ClinicalImpression",
|
||||||
|
@ -193,7 +205,11 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"transaction": { "method":"POST" },
|
"transaction":
|
||||||
|
{
|
||||||
|
"method": "POST"
|
||||||
|
},
|
||||||
|
|
||||||
"resource":
|
"resource":
|
||||||
{
|
{
|
||||||
"resourceType": "ClinicalImpression",
|
"resourceType": "ClinicalImpression",
|
||||||
|
@ -238,7 +254,11 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"transaction": { "method":"POST" },
|
"transaction":
|
||||||
|
{
|
||||||
|
"method": "POST"
|
||||||
|
},
|
||||||
|
|
||||||
"resource":
|
"resource":
|
||||||
{
|
{
|
||||||
"resourceType": "Encounter",
|
"resourceType": "Encounter",
|
||||||
|
@ -267,7 +287,11 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"transaction": { "method":"POST" },
|
"transaction":
|
||||||
|
{
|
||||||
|
"method": "POST"
|
||||||
|
},
|
||||||
|
|
||||||
"resource":
|
"resource":
|
||||||
{
|
{
|
||||||
"resourceType": "ClinicalImpression",
|
"resourceType": "ClinicalImpression",
|
||||||
|
@ -311,7 +335,11 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"transaction": { "method":"POST" },
|
"transaction":
|
||||||
|
{
|
||||||
|
"method": "POST"
|
||||||
|
},
|
||||||
|
|
||||||
"resource":
|
"resource":
|
||||||
{
|
{
|
||||||
"resourceType": "Encounter",
|
"resourceType": "Encounter",
|
||||||
|
@ -340,7 +368,11 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"transaction": { "method":"POST" },
|
"transaction":
|
||||||
|
{
|
||||||
|
"method": "POST"
|
||||||
|
},
|
||||||
|
|
||||||
"resource":
|
"resource":
|
||||||
{
|
{
|
||||||
"resourceType": "ClinicalImpression",
|
"resourceType": "ClinicalImpression",
|
||||||
|
@ -384,7 +416,11 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"transaction": { "method":"POST" },
|
"transaction":
|
||||||
|
{
|
||||||
|
"method": "POST"
|
||||||
|
},
|
||||||
|
|
||||||
"resource":
|
"resource":
|
||||||
{
|
{
|
||||||
"resourceType": "Observation",
|
"resourceType": "Observation",
|
||||||
|
@ -417,7 +453,11 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"transaction": { "method":"POST" },
|
"transaction":
|
||||||
|
{
|
||||||
|
"method": "POST"
|
||||||
|
},
|
||||||
|
|
||||||
"resource":
|
"resource":
|
||||||
{
|
{
|
||||||
"resourceType": "Observation",
|
"resourceType": "Observation",
|
||||||
|
@ -447,7 +487,50 @@
|
||||||
{
|
{
|
||||||
"mode": "match"
|
"mode": "match"
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"transaction":
|
||||||
|
{
|
||||||
|
"method": "POST"
|
||||||
|
},
|
||||||
|
|
||||||
|
"resource":
|
||||||
|
{
|
||||||
|
"resourceType": "Condition",
|
||||||
|
"id": "20443",
|
||||||
|
"meta":
|
||||||
|
{
|
||||||
|
"versionId": "1",
|
||||||
|
"lastUpdated": "2015-04-03T22:56:49.886-04:00"
|
||||||
|
},
|
||||||
|
|
||||||
|
"text":
|
||||||
|
{
|
||||||
|
"status": "generated",
|
||||||
|
"div": "<div xmlns=\"http://www.w3.org/1999/xhtml\">pharyngitis working </div>"
|
||||||
|
},
|
||||||
|
|
||||||
|
"patient":
|
||||||
|
{
|
||||||
|
"reference": "Patient/1702",
|
||||||
|
"display": "Eve Everywoman "
|
||||||
|
},
|
||||||
|
|
||||||
|
"code":
|
||||||
|
{
|
||||||
|
"coding":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"system": "http://loinc.org",
|
||||||
|
"code": "28397-8",
|
||||||
|
"display": "pharyngitis"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
"text": "pharyngitis"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -35,7 +35,7 @@
|
||||||
<property name="persistenceUnitName" value="FHIR_UT" />
|
<property name="persistenceUnitName" value="FHIR_UT" />
|
||||||
<property name="jpaVendorAdapter">
|
<property name="jpaVendorAdapter">
|
||||||
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
|
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
|
||||||
<property name="showSql" value="true" />
|
<property name="showSql" value="false" />
|
||||||
<property name="generateDdl" value="true" />
|
<property name="generateDdl" value="true" />
|
||||||
<!-- <property name="databasePlatform" value="org.hibernate.dialect.HSQLDialect" /> -->
|
<!-- <property name="databasePlatform" value="org.hibernate.dialect.HSQLDialect" /> -->
|
||||||
<property name="databasePlatform" value="org.hibernate.dialect.DerbyTenSevenDialect" />
|
<property name="databasePlatform" value="org.hibernate.dialect.DerbyTenSevenDialect" />
|
||||||
|
|
|
@ -268,7 +268,7 @@ public class Dstu2BundleFactory implements IVersionSpecificBundleFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBaseResource getResourceBundle() {
|
public IResource getResourceBundle() {
|
||||||
return myBundle;
|
return myBundle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -123,6 +123,9 @@
|
||||||
the main focus resource if it was referred to in a deep chain. Thanks
|
the main focus resource if it was referred to in a deep chain. Thanks
|
||||||
to David Hay for reporting!
|
to David Hay for reporting!
|
||||||
</action>
|
</action>
|
||||||
|
<action type="add" issue="148">
|
||||||
|
JPA Server $everything operation now allows a _count parameter
|
||||||
|
</action>
|
||||||
</release>
|
</release>
|
||||||
<release version="0.9" date="2015-Mar-14">
|
<release version="0.9" date="2015-Mar-14">
|
||||||
<action type="add">
|
<action type="add">
|
||||||
|
|
Loading…
Reference in New Issue