Work on adding conditional HTTP operations to client and JPA server
This commit is contained in:
parent
f76a875bc4
commit
315ad439e4
|
@ -72,6 +72,7 @@ import ca.uhn.fhir.validation.FhirValidator;
|
|||
public class FhirContext {
|
||||
|
||||
private static final List<Class<? extends IBaseResource>> EMPTY_LIST = Collections.emptyList();
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirContext.class);
|
||||
private volatile Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> myClassToElementDefinition = Collections.emptyMap();
|
||||
private volatile Map<String, RuntimeResourceDefinition> myIdToResourceDefinition = Collections.emptyMap();
|
||||
private HapiLocalizer myLocalizer = new HapiLocalizer();
|
||||
|
@ -81,6 +82,7 @@ public class FhirContext {
|
|||
private volatile IRestfulClientFactory myRestfulClientFactory;
|
||||
private volatile RuntimeChildUndeclaredExtensionDefinition myRuntimeChildUndeclaredExtensionDefinition;
|
||||
private final IFhirVersion myVersion;
|
||||
|
||||
private Map<FhirVersionEnum, Map<String, Class<? extends IBaseResource>>> myVersionToNameToResourceType = Collections.emptyMap();
|
||||
|
||||
/**
|
||||
|
@ -124,6 +126,8 @@ public class FhirContext {
|
|||
throw new IllegalStateException(getLocalizer().getMessage(FhirContext.class, "noStructures"));
|
||||
}
|
||||
|
||||
ourLog.info("Creating new FHIR context for FHIR version [{}]", myVersion.getVersion().name());
|
||||
|
||||
scanResourceTypes(toElementList(theResourceTypes));
|
||||
}
|
||||
|
||||
|
@ -196,14 +200,14 @@ public class FhirContext {
|
|||
nameToType = new HashMap<String, Class<? extends IBaseResource>>();
|
||||
ModelScanner.scanVersionPropertyFile(null, nameToType, theVersion);
|
||||
|
||||
Map<FhirVersionEnum, Map<String, Class<? extends IBaseResource>>> newVersionToNameToResourceType = new HashMap<FhirVersionEnum, Map<String,Class<? extends IBaseResource>>>();
|
||||
Map<FhirVersionEnum, Map<String, Class<? extends IBaseResource>>> newVersionToNameToResourceType = new HashMap<FhirVersionEnum, Map<String, Class<? extends IBaseResource>>>();
|
||||
newVersionToNameToResourceType.putAll(myVersionToNameToResourceType);
|
||||
newVersionToNameToResourceType.put(theVersion, nameToType);
|
||||
myVersionToNameToResourceType = newVersionToNameToResourceType;
|
||||
}
|
||||
|
||||
Class<? extends IBaseResource> resourceType = nameToType.get(theResourceName.toLowerCase());
|
||||
if (resourceType==null) {
|
||||
if (resourceType == null) {
|
||||
throw new DataFormatException(createUnknownResourceNameError(theResourceName, theVersion));
|
||||
}
|
||||
|
||||
|
@ -457,6 +461,10 @@ public class FhirContext {
|
|||
return new FhirContext(FhirVersionEnum.DSTU2);
|
||||
}
|
||||
|
||||
public static FhirContext forDstu2Hl7Org() {
|
||||
return new FhirContext(FhirVersionEnum.DSTU2_HL7ORG);
|
||||
}
|
||||
|
||||
private static Collection<Class<? extends IBaseResource>> toCollection(Class<? extends IBaseResource> theResourceType) {
|
||||
ArrayList<Class<? extends IBaseResource>> retVal = new ArrayList<Class<? extends IBaseResource>>(1);
|
||||
retVal.add(theResourceType);
|
||||
|
@ -475,8 +483,4 @@ public class FhirContext {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
public static FhirContext forDstu2Hl7Org() {
|
||||
return new FhirContext(FhirVersionEnum.DSTU2_HL7ORG);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -216,7 +216,7 @@ class ModelScanner {
|
|||
|
||||
long time = System.currentTimeMillis() - start;
|
||||
int size = myClassToElementDefinitions.size() - startSize;
|
||||
ourLog.info("Done scanning FHIR library, found {} model entries in {}ms", size, time);
|
||||
ourLog.debug("Done scanning FHIR library, found {} model entries in {}ms", size, time);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -113,6 +113,18 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String> {
|
|||
this(theResourceType, toPlainStringWithNpeThrowIfNeeded(theIdPart));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param theResourceType
|
||||
* The resource type (e.g. "Patient")
|
||||
* @param theIdPart
|
||||
* The ID (e.g. "123")
|
||||
*/
|
||||
public IdDt(String theResourceType, Long theIdPart) {
|
||||
this(theResourceType, toPlainStringWithNpeThrowIfNeeded(theIdPart));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
|
@ -515,6 +527,13 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String> {
|
|||
return theIdPart.toPlainString();
|
||||
}
|
||||
|
||||
private static String toPlainStringWithNpeThrowIfNeeded(Long theIdPart) {
|
||||
if (theIdPart == null) {
|
||||
throw new NullPointerException("Long ID can not be null");
|
||||
}
|
||||
return theIdPart.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return isBlank(getValue());
|
||||
|
|
|
@ -146,8 +146,9 @@ public class MethodOutcome {
|
|||
* If not null, indicates whether the resource was created (as opposed to being updated). This is generally not needed, since the server can assume based on the method being called
|
||||
* whether the result was a creation or an update. However, it can be useful if you are implementing an update method that does a create if the ID doesn't already exist.
|
||||
*/
|
||||
public void setCreated(Boolean theCreated) {
|
||||
public MethodOutcome setCreated(Boolean theCreated) {
|
||||
myCreated = theCreated;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -182,8 +182,13 @@ public abstract class BaseClient {
|
|||
}
|
||||
|
||||
try {
|
||||
ContentType ct = ContentType.get(response.getEntity());
|
||||
String mimeType = ct != null ? ct.getMimeType() : null;
|
||||
String mimeType;
|
||||
if (Constants.STATUS_HTTP_204_NO_CONTENT == response.getStatusLine().getStatusCode()) {
|
||||
mimeType = null;
|
||||
} else {
|
||||
ContentType ct = ContentType.get(response.getEntity());
|
||||
mimeType = ct != null ? ct.getMimeType() : null;
|
||||
}
|
||||
|
||||
Map<String, List<String>> headers = new HashMap<String, List<String>>();
|
||||
if (response.getAllHeaders() != null) {
|
||||
|
@ -398,7 +403,9 @@ public abstract class BaseClient {
|
|||
charset = ct.getCharset();
|
||||
}
|
||||
if (charset == null) {
|
||||
ourLog.warn("Response did not specify a charset.");
|
||||
if (Constants.STATUS_HTTP_204_NO_CONTENT != theResponse.getStatusLine().getStatusCode()) {
|
||||
ourLog.warn("Response did not specify a charset.");
|
||||
}
|
||||
charset = Charset.forName("UTF-8");
|
||||
}
|
||||
|
||||
|
|
|
@ -59,6 +59,9 @@ public abstract class BaseHttpClientInvocation {
|
|||
public abstract HttpRequestBase asHttpRequest(String theUrlBase, Map<String, List<String>> theExtraParams, EncodingEnum theEncoding);
|
||||
|
||||
protected static void appendExtraParamsWithQuestionMark(Map<String, List<String>> theExtraParams, StringBuilder theUrlBuilder, boolean theWithQuestionMark) {
|
||||
if (theExtraParams==null) {
|
||||
return;
|
||||
}
|
||||
boolean first = theWithQuestionMark;
|
||||
|
||||
if (theExtraParams != null && theExtraParams.isEmpty() == false) {
|
||||
|
|
|
@ -56,10 +56,14 @@ import ca.uhn.fhir.rest.client.exceptions.NonFhirResponseException;
|
|||
import ca.uhn.fhir.rest.gclient.IClientExecutable;
|
||||
import ca.uhn.fhir.rest.gclient.ICreate;
|
||||
import ca.uhn.fhir.rest.gclient.ICreateTyped;
|
||||
import ca.uhn.fhir.rest.gclient.ICreateWithQuery;
|
||||
import ca.uhn.fhir.rest.gclient.ICreateWithQueryTyped;
|
||||
import ca.uhn.fhir.rest.gclient.ICriterion;
|
||||
import ca.uhn.fhir.rest.gclient.ICriterionInternal;
|
||||
import ca.uhn.fhir.rest.gclient.IDelete;
|
||||
import ca.uhn.fhir.rest.gclient.IDeleteTyped;
|
||||
import ca.uhn.fhir.rest.gclient.IDeleteWithQuery;
|
||||
import ca.uhn.fhir.rest.gclient.IDeleteWithQueryTyped;
|
||||
import ca.uhn.fhir.rest.gclient.IGetPage;
|
||||
import ca.uhn.fhir.rest.gclient.IGetPageTyped;
|
||||
import ca.uhn.fhir.rest.gclient.IGetTags;
|
||||
|
@ -76,6 +80,8 @@ import ca.uhn.fhir.rest.gclient.IUntypedQuery;
|
|||
import ca.uhn.fhir.rest.gclient.IUpdate;
|
||||
import ca.uhn.fhir.rest.gclient.IUpdateExecutable;
|
||||
import ca.uhn.fhir.rest.gclient.IUpdateTyped;
|
||||
import ca.uhn.fhir.rest.gclient.IUpdateWithQuery;
|
||||
import ca.uhn.fhir.rest.gclient.IUpdateWithQueryTyped;
|
||||
import ca.uhn.fhir.rest.method.DeleteMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.HistoryMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.HttpDeleteClientInvocation;
|
||||
|
@ -237,10 +243,10 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
return new LoadPageInternal();
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public <T extends IBaseResource> T read(final Class<T> theType, IdDt theId) {
|
||||
// return doReadOrVRead(theType, theId, false, null, null);
|
||||
// }
|
||||
// @Override
|
||||
// public <T extends IBaseResource> T read(final Class<T> theType, IdDt theId) {
|
||||
// return doReadOrVRead(theType, theId, false, null, null);
|
||||
// }
|
||||
|
||||
@Override
|
||||
public <T extends IBaseResource> T read(Class<T> theType, String theId) {
|
||||
|
@ -249,7 +255,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
|
||||
@Override
|
||||
public <T extends IBaseResource> T read(final Class<T> theType, UriDt theUrl) {
|
||||
IdDt id = theUrl instanceof IdDt ? ((IdDt)theUrl) : new IdDt(theUrl);
|
||||
IdDt id = theUrl instanceof IdDt ? ((IdDt) theUrl) : new IdDt(theUrl);
|
||||
return doReadOrVRead(theType, id, false, null, null);
|
||||
}
|
||||
|
||||
|
@ -475,18 +481,18 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
return vread(theType, resId);
|
||||
}
|
||||
|
||||
private static void addParam(Map<String, List<String>> params, String parameterName, String parameterValue) {
|
||||
if (!params.containsKey(parameterName)) {
|
||||
params.put(parameterName, new ArrayList<String>());
|
||||
}
|
||||
params.get(parameterName).add(parameterValue);
|
||||
}
|
||||
|
||||
private abstract class BaseClientExecutable<T extends IClientExecutable<?, ?>, Y> implements IClientExecutable<T, Y> {
|
||||
private EncodingEnum myParamEncoding;
|
||||
private Boolean myPrettyPrint;
|
||||
private boolean myQueryLogRequestAndResponse;
|
||||
|
||||
protected void addParam(Map<String, List<String>> params, String parameterName, String parameterValue) {
|
||||
if (!params.containsKey(parameterName)) {
|
||||
params.put(parameterName, new ArrayList<String>());
|
||||
}
|
||||
params.get(parameterName).add(parameterValue);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public T andLogRequestAndResponse(boolean theLogRequestAndResponse) {
|
||||
|
@ -575,11 +581,13 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
}
|
||||
}
|
||||
|
||||
private class CreateInternal extends BaseClientExecutable<ICreateTyped, MethodOutcome> implements ICreate, ICreateTyped {
|
||||
private class CreateInternal extends BaseClientExecutable<ICreateTyped, MethodOutcome> implements ICreate, ICreateTyped, ICreateWithQuery, ICreateWithQueryTyped {
|
||||
|
||||
private String myId;
|
||||
private IResource myResource;
|
||||
private String myResourceBody;
|
||||
private String mySearchUrl;
|
||||
private CriterionList myCriterionList;
|
||||
|
||||
@Override
|
||||
public MethodOutcome execute() {
|
||||
|
@ -593,7 +601,14 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
myResourceBody = null;
|
||||
}
|
||||
|
||||
BaseHttpClientInvocation invocation = MethodUtil.createCreateInvocation(myResource, myResourceBody, myId, myContext);
|
||||
BaseHttpClientInvocation invocation;
|
||||
if (mySearchUrl != null) {
|
||||
invocation = MethodUtil.createCreateInvocation(myResource, myResourceBody, myId, myContext, mySearchUrl);
|
||||
} else if (myCriterionList != null) {
|
||||
invocation = MethodUtil.createCreateInvocation(myResource, myResourceBody, myId, myContext, myCriterionList.toParamList());
|
||||
} else {
|
||||
invocation = MethodUtil.createCreateInvocation(myResource, myResourceBody, myId, myContext);
|
||||
}
|
||||
|
||||
RuntimeResourceDefinition def = myContext.getResourceDefinition(myResource);
|
||||
final String resourceName = def.getName();
|
||||
|
@ -631,15 +646,50 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICreateTyped conditionalByUrl(String theSearchUrl) {
|
||||
mySearchUrl = theSearchUrl;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICreateWithQuery conditional() {
|
||||
myCriterionList = new CriterionList();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICreateWithQueryTyped where(ICriterion<?> theCriterion) {
|
||||
myCriterionList.add((ICriterionInternal) theCriterion);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICreateWithQueryTyped and(ICriterion<?> theCriterion) {
|
||||
myCriterionList.add((ICriterionInternal) theCriterion);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class DeleteInternal extends BaseClientExecutable<IDeleteTyped, BaseOperationOutcome> implements IDelete, IDeleteTyped {
|
||||
private class DeleteInternal extends BaseClientExecutable<IDeleteTyped, BaseOperationOutcome> implements IDelete, IDeleteTyped, IDeleteWithQuery, IDeleteWithQueryTyped {
|
||||
|
||||
private IdDt myId;
|
||||
private String mySearchUrl;
|
||||
private String myResourceType;
|
||||
private CriterionList myCriterionList;
|
||||
|
||||
@Override
|
||||
public BaseOperationOutcome execute() {
|
||||
HttpDeleteClientInvocation invocation = DeleteMethodBinding.createDeleteInvocation(myId);
|
||||
HttpDeleteClientInvocation invocation;
|
||||
if (myId != null) {
|
||||
invocation = DeleteMethodBinding.createDeleteInvocation(myId);
|
||||
} else if (myCriterionList != null) {
|
||||
Map<String, List<String>> params = myCriterionList.toParamList();
|
||||
invocation = DeleteMethodBinding.createDeleteInvocation(myResourceType, params);
|
||||
} else {
|
||||
invocation = DeleteMethodBinding.createDeleteInvocation(mySearchUrl);
|
||||
}
|
||||
OperationOutcomeResponseHandler binding = new OperationOutcomeResponseHandler();
|
||||
Map<String, List<String>> params = new HashMap<String, List<String>>();
|
||||
return invoke(params, binding, invocation);
|
||||
|
@ -680,6 +730,56 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
myId = new IdDt(theResourceType, theLogicalId);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IDeleteTyped resourceConditionalByUrl(String theSearchUrl) {
|
||||
Validate.notBlank(theSearchUrl, "theSearchUrl can not be blank/null");
|
||||
mySearchUrl = theSearchUrl;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IDeleteWithQuery resourceConditionalByType(String theResourceType) {
|
||||
Validate.notBlank(theResourceType, "theResourceType can not be blank/null");
|
||||
if (myContext.getResourceDefinition(theResourceType) == null) {
|
||||
throw new IllegalArgumentException("Unknown resource type: " + theResourceType);
|
||||
}
|
||||
myResourceType = theResourceType;
|
||||
myCriterionList = new CriterionList();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IDeleteWithQueryTyped where(ICriterion<?> theCriterion) {
|
||||
myCriterionList.add((ICriterionInternal) theCriterion);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IDeleteWithQueryTyped and(ICriterion<?> theCriterion) {
|
||||
myCriterionList.add((ICriterionInternal) theCriterion);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
private static class CriterionList extends ArrayList<ICriterionInternal> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public void populateParamList(Map<String, List<String>> theParams) {
|
||||
for (ICriterionInternal next : this) {
|
||||
String parameterName = next.getParameterName();
|
||||
String parameterValue = next.getParameterValue();
|
||||
addParam(theParams, parameterName, parameterValue);
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, List<String>> toParamList() {
|
||||
LinkedHashMap<String, List<String>> retVal = new LinkedHashMap<String, List<String>>();
|
||||
populateParamList(retVal);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class GetPageInternal extends BaseClientExecutable<IGetPageTyped, Bundle> implements IGetPageTyped {
|
||||
|
@ -996,7 +1096,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
private class SearchInternal extends BaseClientExecutable<IQuery, Bundle> implements IQuery, IUntypedQuery {
|
||||
|
||||
private String myCompartmentName;
|
||||
private List<ICriterionInternal> myCriterion = new ArrayList<ICriterionInternal>();
|
||||
private CriterionList myCriterion = new CriterionList();
|
||||
private List<Include> myInclude = new ArrayList<Include>();
|
||||
private Integer myParamLimit;
|
||||
private String myResourceId;
|
||||
|
@ -1025,11 +1125,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
// params.putAll(initial);
|
||||
// }
|
||||
|
||||
for (ICriterionInternal next : myCriterion) {
|
||||
String parameterName = next.getParameterName();
|
||||
String parameterValue = next.getParameterValue();
|
||||
addParam(params, parameterName, parameterValue);
|
||||
}
|
||||
myCriterion.populateParamList(params);
|
||||
|
||||
for (Include next : myInclude) {
|
||||
addParam(params, Constants.PARAM_INCLUDE, next.getValue());
|
||||
|
@ -1224,30 +1320,39 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
|
||||
}
|
||||
|
||||
private class UpdateInternal extends BaseClientExecutable<IUpdateExecutable, MethodOutcome> implements IUpdate, IUpdateTyped, IUpdateExecutable {
|
||||
private class UpdateInternal extends BaseClientExecutable<IUpdateExecutable, MethodOutcome> implements IUpdate, IUpdateTyped, IUpdateExecutable, IUpdateWithQuery, IUpdateWithQueryTyped {
|
||||
|
||||
private IdDt myId;
|
||||
private IResource myResource;
|
||||
private String myResourceBody;
|
||||
private String mySearchUrl;
|
||||
private CriterionList myCriterionList;
|
||||
|
||||
@Override
|
||||
public MethodOutcome execute() {
|
||||
if (myResource == null) {
|
||||
myResource = parseResourceBody(myResourceBody);
|
||||
}
|
||||
if (myId == null) {
|
||||
myId = myResource.getId();
|
||||
}
|
||||
if (myId == null || myId.hasIdPart() == false) {
|
||||
throw new InvalidRequestException("No ID supplied for resource to update, can not invoke server");
|
||||
}
|
||||
|
||||
// If an explicit encoding is chosen, we will re-serialize to ensure the right encoding
|
||||
if (getParamEncoding() != null) {
|
||||
myResourceBody = null;
|
||||
}
|
||||
|
||||
BaseHttpClientInvocation invocation = MethodUtil.createUpdateInvocation(myResource, myResourceBody, myId, myContext);
|
||||
BaseHttpClientInvocation invocation;
|
||||
if (mySearchUrl != null) {
|
||||
invocation = MethodUtil.createUpdateInvocation(myContext, myResource, myResourceBody, mySearchUrl);
|
||||
} else if (myCriterionList != null) {
|
||||
invocation = MethodUtil.createUpdateInvocation(myContext, myResource, myResourceBody, myCriterionList.toParamList());
|
||||
} else {
|
||||
if (myId == null) {
|
||||
myId = myResource.getId();
|
||||
}
|
||||
if (myId == null || myId.hasIdPart() == false) {
|
||||
throw new InvalidRequestException("No ID supplied for resource to update, can not invoke server");
|
||||
}
|
||||
invocation = MethodUtil.createUpdateInvocation(myResource, myResourceBody, myId, myContext);
|
||||
}
|
||||
|
||||
RuntimeResourceDefinition def = myContext.getResourceDefinition(myResource);
|
||||
final String resourceName = def.getName();
|
||||
|
@ -1297,6 +1402,30 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IUpdateTyped conditionalByUrl(String theSearchUrl) {
|
||||
mySearchUrl = theSearchUrl;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IUpdateWithQuery conditional() {
|
||||
myCriterionList = new CriterionList();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IUpdateWithQueryTyped where(ICriterion<?> theCriterion) {
|
||||
myCriterionList.add((ICriterionInternal) theCriterion);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IUpdateWithQueryTyped and(ICriterion<?> theCriterion) {
|
||||
myCriterionList.add((ICriterionInternal) theCriterion);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
package ca.uhn.fhir.rest.gclient;
|
||||
|
||||
public interface IBaseQuery<T> {
|
||||
|
||||
T where(ICriterion<?> theCriterion);
|
||||
|
||||
T and(ICriterion<?> theCriterion);
|
||||
|
||||
}
|
|
@ -37,4 +37,20 @@ public interface ICreateTyped extends IClientExecutable<ICreateTyped, MethodOutc
|
|||
*/
|
||||
ICreateTyped withId(IdDt theId);
|
||||
|
||||
/**
|
||||
* Specifies that the create should be performed as a conditional create
|
||||
* against a given search URL.
|
||||
*
|
||||
* @param theSearchUrl The search URL to use. The format of this URL should be of the form <code>[ResourceType]?[Parameters]</code>,
|
||||
* for example: <code>Patient?name=Smith&identifier=13.2.4.11.4%7C847366</code>
|
||||
*
|
||||
* @since HAPI 0.9 / FHIR DSTU 2
|
||||
*/
|
||||
ICreateTyped conditionalByUrl(String theSearchUrl);
|
||||
|
||||
/**
|
||||
* @since HAPI 0.9 / FHIR DSTU 2
|
||||
*/
|
||||
ICreateWithQuery conditional();
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
package ca.uhn.fhir.rest.gclient;
|
||||
|
||||
|
||||
public interface ICreateWithQuery extends IBaseQuery<ICreateWithQueryTyped> {
|
||||
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package ca.uhn.fhir.rest.gclient;
|
||||
|
||||
public interface ICreateWithQueryTyped extends ICreateTyped, ICreateWithQuery {
|
||||
|
||||
}
|
|
@ -31,4 +31,20 @@ public interface IDelete {
|
|||
|
||||
IDeleteTyped resourceById(String theResourceType, String theLogicalId);
|
||||
|
||||
/**
|
||||
* Specifies that the delete should be performed as a conditional delete
|
||||
* against a given search URL.
|
||||
*
|
||||
* @param theSearchUrl The search URL to use. The format of this URL should be of the form <code>[ResourceType]?[Parameters]</code>,
|
||||
* for example: <code>Patient?name=Smith&identifier=13.2.4.11.4%7C847366</code>
|
||||
*
|
||||
* @since HAPI 0.9 / FHIR DSTU 2
|
||||
*/
|
||||
IDeleteTyped resourceConditionalByUrl(String theSearchUrl);
|
||||
|
||||
/**
|
||||
* @since HAPI 0.9 / FHIR DSTU 2
|
||||
*/
|
||||
IDeleteWithQuery resourceConditionalByType(String theResourceType);
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
package ca.uhn.fhir.rest.gclient;
|
||||
|
||||
public interface IDeleteWithQuery extends IBaseQuery<IDeleteWithQueryTyped> {
|
||||
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package ca.uhn.fhir.rest.gclient;
|
||||
|
||||
public interface IDeleteWithQueryTyped extends IDeleteTyped, IDeleteWithQuery {
|
||||
|
||||
}
|
|
@ -24,11 +24,7 @@ import ca.uhn.fhir.model.api.Bundle;
|
|||
import ca.uhn.fhir.model.api.Include;
|
||||
import ca.uhn.fhir.rest.method.SearchStyleEnum;
|
||||
|
||||
public interface IQuery extends IClientExecutable<IQuery,Bundle> {
|
||||
|
||||
IQuery where(ICriterion<?> theCriterion);
|
||||
|
||||
IQuery and(ICriterion<?> theCriterion);
|
||||
public interface IQuery extends IClientExecutable<IQuery,Bundle>, IBaseQuery<IQuery> {
|
||||
|
||||
IQuery include(Include theIncludeManagingorganization);
|
||||
|
||||
|
|
|
@ -28,4 +28,20 @@ public interface IUpdateTyped extends IUpdateExecutable {
|
|||
|
||||
IUpdateExecutable withId(String theId);
|
||||
|
||||
/**
|
||||
* Specifies that the update should be performed as a conditional create
|
||||
* against a given search URL.
|
||||
*
|
||||
* @param theSearchUrl The search URL to use. The format of this URL should be of the form <code>[ResourceType]?[Parameters]</code>,
|
||||
* for example: <code>Patient?name=Smith&identifier=13.2.4.11.4%7C847366</code>
|
||||
*
|
||||
* @since HAPI 0.9 / FHIR DSTU 2
|
||||
*/
|
||||
IUpdateTyped conditionalByUrl(String theSearchUrl);
|
||||
|
||||
/**
|
||||
* @since HAPI 0.9 / FHIR DSTU 2
|
||||
*/
|
||||
IUpdateWithQuery conditional();
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
package ca.uhn.fhir.rest.gclient;
|
||||
|
||||
|
||||
public interface IUpdateWithQuery extends IBaseQuery<IUpdateWithQueryTyped> {
|
||||
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package ca.uhn.fhir.rest.gclient;
|
||||
|
||||
public interface IUpdateWithQueryTyped extends IUpdateTyped, IUpdateWithQuery {
|
||||
|
||||
}
|
|
@ -143,29 +143,55 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
|
|||
myBundleType = null;
|
||||
}
|
||||
|
||||
public BaseHttpClientInvocationWithContents(FhirContext theContext, String theContents, Map<String, List<String>> theParams, String... theUrlPath) {
|
||||
myContext = theContext;
|
||||
myResource = null;
|
||||
myTagList = null;
|
||||
myUrlPath = StringUtils.join(theUrlPath, '/');
|
||||
myResources = null;
|
||||
myBundle = null;
|
||||
myContents = theContents;
|
||||
myContentsIsBundle = false;
|
||||
myParams = theParams;
|
||||
myBundleType = null;
|
||||
}
|
||||
|
||||
public BaseHttpClientInvocationWithContents(FhirContext theContext, IResource theResource, Map<String, List<String>> theParams, String... theUrlPath) {
|
||||
myContext = theContext;
|
||||
myResource = theResource;
|
||||
myTagList = null;
|
||||
myUrlPath = StringUtils.join(theUrlPath, '/');
|
||||
myResources = null;
|
||||
myBundle = null;
|
||||
myContents = null;
|
||||
myContentsIsBundle = false;
|
||||
myParams = theParams;
|
||||
myBundleType = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpRequestBase asHttpRequest(String theUrlBase, Map<String, List<String>> theExtraParams, EncodingEnum theEncoding) throws DataFormatException {
|
||||
StringBuilder b = new StringBuilder();
|
||||
StringBuilder url = new StringBuilder();
|
||||
|
||||
if (myUrlPath == null) {
|
||||
b.append(theUrlBase);
|
||||
url.append(theUrlBase);
|
||||
} else {
|
||||
if (!myUrlPath.contains("://")) {
|
||||
b.append(theUrlBase);
|
||||
url.append(theUrlBase);
|
||||
if (!theUrlBase.endsWith("/")) {
|
||||
b.append('/');
|
||||
url.append('/');
|
||||
}
|
||||
}
|
||||
b.append(myUrlPath);
|
||||
url.append(myUrlPath);
|
||||
}
|
||||
|
||||
appendExtraParamsWithQuestionMark(theExtraParams, b, b.indexOf("?") == -1);
|
||||
String url = b.toString();
|
||||
appendExtraParamsWithQuestionMark(theExtraParams, url, url.indexOf("?") == -1);
|
||||
|
||||
if (myResource != null && BaseBinary.class.isAssignableFrom(myResource.getClass())) {
|
||||
BaseBinary binary = (BaseBinary) myResource;
|
||||
ByteArrayEntity entity = new ByteArrayEntity(binary.getContent(), ContentType.parse(binary.getContentType()));
|
||||
HttpRequestBase retVal = createRequest(url, entity);
|
||||
addMatchHeaders(retVal, url);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
@ -187,11 +213,11 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
|
|||
|
||||
AbstractHttpEntity entity;
|
||||
if (myParams != null) {
|
||||
contentType= null;
|
||||
contentType = null;
|
||||
List<NameValuePair> parameters = new ArrayList<NameValuePair>();
|
||||
for (Entry<String, List<String>> nextParam : myParams.entrySet()) {
|
||||
List<String> value = nextParam.getValue();
|
||||
for(String s: value){
|
||||
for (String s : value) {
|
||||
parameters.add(new BasicNameValuePair(nextParam.getKey(), s));
|
||||
}
|
||||
}
|
||||
|
@ -228,6 +254,7 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
|
|||
|
||||
HttpRequestBase retVal = createRequest(url, entity);
|
||||
super.addHeadersToRequest(retVal);
|
||||
addMatchHeaders(retVal, url);
|
||||
|
||||
if (contentType != null) {
|
||||
retVal.addHeader(Constants.HEADER_CONTENT_TYPE, contentType + Constants.HEADER_SUFFIX_CT_UTF_8);
|
||||
|
@ -236,6 +263,41 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
|
|||
return retVal;
|
||||
}
|
||||
|
||||
protected abstract HttpRequestBase createRequest(String url, AbstractHttpEntity theEntity);
|
||||
private void addMatchHeaders(HttpRequestBase theHttpRequest, StringBuilder theUrlBase) {
|
||||
if (myIfNoneExistParams != null) {
|
||||
StringBuilder b = newHeaderBuilder(theUrlBase);
|
||||
appendExtraParamsWithQuestionMark(myIfNoneExistParams, b, b.indexOf("?") == -1);
|
||||
theHttpRequest.addHeader(Constants.HEADER_IF_NONE_EXIST, b.toString());
|
||||
}
|
||||
|
||||
if (myIfNoneExistString != null) {
|
||||
StringBuilder b = newHeaderBuilder(theUrlBase);
|
||||
b.append(b.indexOf("?") == -1 ? '?' : '&');
|
||||
b.append(myIfNoneExistString.substring(myIfNoneExistString.indexOf('?') + 1));
|
||||
theHttpRequest.addHeader(Constants.HEADER_IF_NONE_EXIST, b.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private StringBuilder newHeaderBuilder(StringBuilder theUrlBase) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append(theUrlBase);
|
||||
if (theUrlBase.length() > 0 && theUrlBase.charAt(theUrlBase.length() - 1) == '/') {
|
||||
b.deleteCharAt(b.length() - 1);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
protected abstract HttpRequestBase createRequest(StringBuilder theUrl, AbstractHttpEntity theEntity);
|
||||
|
||||
private Map<String, List<String>> myIfNoneExistParams;
|
||||
private String myIfNoneExistString;
|
||||
|
||||
public void setIfNoneExistParams(Map<String, List<String>> theIfNoneExist) {
|
||||
myIfNoneExistParams = theIfNoneExist;
|
||||
}
|
||||
|
||||
public void setIfNoneExistString(String theIfNoneExistString) {
|
||||
myIfNoneExistString = theIfNoneExistString;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,6 +22,8 @@ package ca.uhn.fhir.rest.method;
|
|||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
|
@ -154,5 +156,14 @@ public class DeleteMethodBinding extends BaseOutcomeReturningMethodBinding {
|
|||
return null;
|
||||
}
|
||||
|
||||
public static HttpDeleteClientInvocation createDeleteInvocation(String theSearchUrl) {
|
||||
HttpDeleteClientInvocation retVal = new HttpDeleteClientInvocation(theSearchUrl);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static HttpDeleteClientInvocation createDeleteInvocation(String theResourceType, Map<String, List<String>> theParams) {
|
||||
return new HttpDeleteClientInvocation(theResourceType, theParams);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -33,12 +33,22 @@ import ca.uhn.fhir.rest.server.EncodingEnum;
|
|||
public class HttpDeleteClientInvocation extends BaseHttpClientInvocation {
|
||||
|
||||
private String myUrlPath;
|
||||
private Map<String, List<String>> myParams;
|
||||
|
||||
public HttpDeleteClientInvocation(IdDt theId) {
|
||||
super();
|
||||
myUrlPath = theId.toUnqualifiedVersionless().getValue();
|
||||
}
|
||||
|
||||
public HttpDeleteClientInvocation(String theSearchUrl) {
|
||||
myUrlPath = theSearchUrl;
|
||||
}
|
||||
|
||||
public HttpDeleteClientInvocation(String theResourceType, Map<String, List<String>> theParams) {
|
||||
myUrlPath = theResourceType;
|
||||
myParams = theParams;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpRequestBase asHttpRequest(String theUrlBase, Map<String, List<String>> theExtraParams, EncodingEnum theEncoding) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
|
@ -48,12 +58,12 @@ public class HttpDeleteClientInvocation extends BaseHttpClientInvocation {
|
|||
}
|
||||
b.append(myUrlPath);
|
||||
|
||||
appendExtraParamsWithQuestionMark(theExtraParams, b,b.indexOf("?") == -1);
|
||||
appendExtraParamsWithQuestionMark(myParams, b, b.indexOf("?") == -1);
|
||||
appendExtraParamsWithQuestionMark(theExtraParams, b, b.indexOf("?") == -1);
|
||||
|
||||
HttpDelete retVal = new HttpDelete(b.toString());
|
||||
super.addHeadersToRequest(retVal);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -34,38 +34,34 @@ import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
|||
|
||||
public class HttpPostClientInvocation extends BaseHttpClientInvocationWithContents {
|
||||
|
||||
|
||||
public HttpPostClientInvocation(FhirContext theContext, IResource theResource, String theUrlExtension) {
|
||||
super(theContext, theResource, theUrlExtension);
|
||||
}
|
||||
|
||||
|
||||
public HttpPostClientInvocation(FhirContext theContext, TagList theTagList, String... theUrlExtension) {
|
||||
super(theContext, theTagList, theUrlExtension);
|
||||
}
|
||||
|
||||
|
||||
public HttpPostClientInvocation(FhirContext theContext, List<IResource> theResources, BundleTypeEnum theBundleType) {
|
||||
super(theContext, theResources, theBundleType);
|
||||
}
|
||||
|
||||
|
||||
public HttpPostClientInvocation(FhirContext theContext, Bundle theBundle) {
|
||||
super(theContext,theBundle);
|
||||
super(theContext, theBundle);
|
||||
}
|
||||
|
||||
public HttpPostClientInvocation(FhirContext theContext, String theContents, boolean theIsBundle, String theUrlExtension) {
|
||||
super(theContext,theContents, theIsBundle, theUrlExtension);
|
||||
super(theContext, theContents, theIsBundle, theUrlExtension);
|
||||
}
|
||||
|
||||
|
||||
public HttpPostClientInvocation(FhirContext theContext, Map<String, List<String>> theParams, String... theUrlExtension) {
|
||||
super(theContext, theParams, theUrlExtension);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected HttpPost createRequest(String url, AbstractHttpEntity theEntity) {
|
||||
HttpPost retVal = new HttpPost(url);
|
||||
protected HttpPost createRequest(StringBuilder theUrlBase, AbstractHttpEntity theEntity) {
|
||||
HttpPost retVal = new HttpPost(theUrlBase.toString());
|
||||
retVal.setEntity(theEntity);
|
||||
return retVal;
|
||||
}
|
||||
|
|
|
@ -34,15 +34,14 @@ public class HttpPutClientInvocation extends BaseHttpClientInvocationWithContent
|
|||
}
|
||||
|
||||
public HttpPutClientInvocation(FhirContext theContext, String theContents, boolean theIsBundle, String theUrlExtension) {
|
||||
super(theContext,theContents, theIsBundle, theUrlExtension);
|
||||
super(theContext, theContents, theIsBundle, theUrlExtension);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected HttpRequestBase createRequest(String url, AbstractHttpEntity theEntity) {
|
||||
HttpPut retVal = new HttpPut(url);
|
||||
protected HttpRequestBase createRequest(StringBuilder theUrl, AbstractHttpEntity theEntity) {
|
||||
HttpPut retVal = new HttpPut(theUrl.toString());
|
||||
retVal.setEntity(theEntity);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -5,14 +5,17 @@ import static org.apache.commons.lang3.StringUtils.*;
|
|||
import java.io.IOException;
|
||||
import java.io.PushbackReader;
|
||||
import java.io.Reader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
|
@ -95,9 +98,65 @@ import ca.uhn.fhir.util.ReflectionUtil;
|
|||
|
||||
public class MethodUtil {
|
||||
private static final String LABEL = "label=\"";
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(MethodUtil.class);
|
||||
|
||||
private static final String SCHEME = "scheme=\"";
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(MethodUtil.class);
|
||||
static void addTagsToPostOrPut(IResource resource, BaseHttpClientInvocation retVal) {
|
||||
TagList list = (TagList) resource.getResourceMetadata().get(ResourceMetadataKeyEnum.TAG_LIST);
|
||||
if (list != null) {
|
||||
for (Tag tag : list) {
|
||||
if (StringUtils.isNotBlank(tag.getTerm())) {
|
||||
retVal.addHeader(Constants.HEADER_CATEGORY, tag.toHeaderValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static HttpGetClientInvocation createConformanceInvocation() {
|
||||
return new HttpGetClientInvocation("metadata");
|
||||
}
|
||||
|
||||
public static HttpPostClientInvocation createCreateInvocation(IResource theResource, FhirContext theContext) {
|
||||
return createCreateInvocation(theResource, null, null, theContext);
|
||||
}
|
||||
|
||||
public static HttpPostClientInvocation createCreateInvocation(IResource theResource, String theResourceBody, String theId, FhirContext theContext) {
|
||||
RuntimeResourceDefinition def = theContext.getResourceDefinition(theResource);
|
||||
String resourceName = def.getName();
|
||||
|
||||
StringBuilder urlExtension = new StringBuilder();
|
||||
urlExtension.append(resourceName);
|
||||
|
||||
if (StringUtils.isNotBlank(theId)) {
|
||||
urlExtension.append('/');
|
||||
urlExtension.append(theId);
|
||||
}
|
||||
|
||||
HttpPostClientInvocation retVal;
|
||||
if (StringUtils.isBlank(theResourceBody)) {
|
||||
retVal = new HttpPostClientInvocation(theContext, theResource, urlExtension.toString());
|
||||
} else {
|
||||
retVal = new HttpPostClientInvocation(theContext, theResourceBody, false, urlExtension.toString());
|
||||
}
|
||||
addTagsToPostOrPut(theResource, retVal);
|
||||
|
||||
// addContentTypeHeaderBasedOnDetectedType(retVal, theResourceBody);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static HttpPostClientInvocation createCreateInvocation(IResource theResource, String theResourceBody, String theId, FhirContext theContext, Map<String, List<String>> theIfNoneExistParams) {
|
||||
HttpPostClientInvocation retVal = createCreateInvocation(theResource, theResourceBody, theId, theContext);
|
||||
retVal.setIfNoneExistParams(theIfNoneExistParams);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static HttpPostClientInvocation createCreateInvocation(IResource theResource, String theResourceBody, String theId, FhirContext theContext, String theIfNoneExistUrl) {
|
||||
HttpPostClientInvocation retVal = createCreateInvocation(theResource, theResourceBody, theId, theContext);
|
||||
retVal.setIfNoneExistString(theIfNoneExistUrl);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static HttpPutClientInvocation createUpdateInvocation(IResource theResource, String theResourceBody, IdDt theId, FhirContext theContext) {
|
||||
String resourceName = theContext.getResourceDefinition(theResource).getName();
|
||||
|
@ -105,9 +164,9 @@ public class MethodUtil {
|
|||
urlBuilder.append(resourceName);
|
||||
urlBuilder.append('/');
|
||||
urlBuilder.append(theId.getIdPart());
|
||||
String urlExtension = urlBuilder.toString();
|
||||
|
||||
HttpPutClientInvocation retVal;
|
||||
String urlExtension = urlBuilder.toString();
|
||||
if (StringUtils.isBlank(theResourceBody)) {
|
||||
retVal = new HttpPutClientInvocation(theContext, theResource, urlExtension);
|
||||
} else {
|
||||
|
@ -135,203 +194,49 @@ public class MethodUtil {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
public static void parseClientRequestResourceHeaders(IdDt theRequestedId, Map<String, List<String>> theHeaders, IBaseResource resource) {
|
||||
List<String> lmHeaders = theHeaders.get(Constants.HEADER_LAST_MODIFIED_LOWERCASE);
|
||||
if (lmHeaders != null && lmHeaders.size() > 0 && StringUtils.isNotBlank(lmHeaders.get(0))) {
|
||||
String headerValue = lmHeaders.get(0);
|
||||
Date headerDateValue;
|
||||
try {
|
||||
headerDateValue = DateUtils.parseDate(headerValue);
|
||||
if (resource instanceof IResource) {
|
||||
InstantDt lmValue = new InstantDt(headerDateValue);
|
||||
((IResource) resource).getResourceMetadata().put(ResourceMetadataKeyEnum.UPDATED, lmValue);
|
||||
} else if (resource instanceof IAnyResource) {
|
||||
((IAnyResource) resource).getMeta().setLastUpdated(headerDateValue);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
ourLog.warn("Unable to parse date string '{}'. Error is: {}", headerValue, e.toString());
|
||||
}
|
||||
}
|
||||
public static HttpPutClientInvocation createUpdateInvocation(FhirContext theContext, IResource theResource, String theResourceBody, Map<String, List<String>> theMatchParams) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
|
||||
List<String> clHeaders = theHeaders.get(Constants.HEADER_CONTENT_LOCATION_LC);
|
||||
if (clHeaders != null && clHeaders.size() > 0 && StringUtils.isNotBlank(clHeaders.get(0))) {
|
||||
String headerValue = clHeaders.get(0);
|
||||
if (isNotBlank(headerValue)) {
|
||||
new IdDt(headerValue).applyTo(resource);
|
||||
}
|
||||
}
|
||||
String resourceType = theContext.getResourceDefinition(theResource).getName();
|
||||
b.append(resourceType);
|
||||
|
||||
IdDt existing = IdDt.of(resource);
|
||||
|
||||
List<String> eTagHeaders = theHeaders.get(Constants.HEADER_ETAG_LC);
|
||||
String eTagVersion = null;
|
||||
if (eTagHeaders != null && eTagHeaders.size() > 0) {
|
||||
eTagVersion = parseETagValue(eTagHeaders.get(0));
|
||||
}
|
||||
if (isNotBlank(eTagVersion)) {
|
||||
if (existing == null || existing.isEmpty()) {
|
||||
if (theRequestedId != null) {
|
||||
theRequestedId.withVersion(eTagVersion).applyTo(resource);
|
||||
}
|
||||
} else if (existing.hasVersionIdPart() == false) {
|
||||
existing.withVersion(eTagVersion).applyTo(resource);
|
||||
}
|
||||
} else if (existing == null || existing.isEmpty()) {
|
||||
if (theRequestedId != null) {
|
||||
theRequestedId.applyTo(resource);
|
||||
}
|
||||
}
|
||||
|
||||
List<String> categoryHeaders = theHeaders.get(Constants.HEADER_CATEGORY_LC);
|
||||
if (categoryHeaders != null && categoryHeaders.size() > 0 && StringUtils.isNotBlank(categoryHeaders.get(0))) {
|
||||
TagList tagList = new TagList();
|
||||
for (String header : categoryHeaders) {
|
||||
parseTagValue(tagList, header);
|
||||
}
|
||||
if (resource instanceof IResource) {
|
||||
ResourceMetadataKeyEnum.TAG_LIST.put((IResource) resource, tagList);
|
||||
} else if (resource instanceof IAnyResource) {
|
||||
IMetaType meta = ((IAnyResource) resource).getMeta();
|
||||
for (Tag next : tagList) {
|
||||
meta.addTag().setSystem(next.getScheme()).setCode(next.getTerm()).setDisplay(next.getLabel());
|
||||
boolean haveQuestionMark=false;
|
||||
for (Entry<String, List<String>> nextEntry : theMatchParams.entrySet()) {
|
||||
for (String nextValue : nextEntry.getValue()) {
|
||||
b.append(haveQuestionMark ? '&' : '?');
|
||||
haveQuestionMark = true;
|
||||
try {
|
||||
b.append(URLEncoder.encode(nextEntry.getKey(), "UTF-8"));
|
||||
b.append('=');
|
||||
b.append(URLEncoder.encode(nextValue, "UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new ConfigurationException("UTF-8 not supported on this platform");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String parseETagValue(String value) {
|
||||
String eTagVersion;
|
||||
value = value.trim();
|
||||
if (value.length() > 1) {
|
||||
if (value.charAt(value.length() - 1) == '"') {
|
||||
if (value.charAt(0) == '"') {
|
||||
eTagVersion = value.substring(1, value.length() - 1);
|
||||
} else if (value.length() > 3 && value.charAt(0) == 'W' && value.charAt(1) == '/' && value.charAt(2) == '"') {
|
||||
eTagVersion = value.substring(3, value.length() - 1);
|
||||
} else {
|
||||
eTagVersion = value;
|
||||
}
|
||||
} else {
|
||||
eTagVersion = value;
|
||||
}
|
||||
} else {
|
||||
eTagVersion = value;
|
||||
}
|
||||
return eTagVersion;
|
||||
}
|
||||
|
||||
public static void parseTagValue(TagList tagList, String nextTagComplete) {
|
||||
StringBuilder next = new StringBuilder(nextTagComplete);
|
||||
parseTagValue(tagList, nextTagComplete, next);
|
||||
}
|
||||
|
||||
private static void parseTagValue(TagList theTagList, String theCompleteHeaderValue, StringBuilder theBuffer) {
|
||||
int firstSemicolon = theBuffer.indexOf(";");
|
||||
int deleteTo;
|
||||
if (firstSemicolon == -1) {
|
||||
firstSemicolon = theBuffer.indexOf(",");
|
||||
if (firstSemicolon == -1) {
|
||||
firstSemicolon = theBuffer.length();
|
||||
deleteTo = theBuffer.length();
|
||||
} else {
|
||||
deleteTo = firstSemicolon;
|
||||
}
|
||||
} else {
|
||||
deleteTo = firstSemicolon + 1;
|
||||
}
|
||||
|
||||
String term = theBuffer.substring(0, firstSemicolon);
|
||||
String scheme = null;
|
||||
String label = null;
|
||||
if (isBlank(term)) {
|
||||
return;
|
||||
}
|
||||
|
||||
theBuffer.delete(0, deleteTo);
|
||||
while (theBuffer.length() > 0 && theBuffer.charAt(0) == ' ') {
|
||||
theBuffer.deleteCharAt(0);
|
||||
}
|
||||
|
||||
while (theBuffer.length() > 0) {
|
||||
boolean foundSomething = false;
|
||||
if (theBuffer.length() > SCHEME.length() && theBuffer.substring(0, SCHEME.length()).equals(SCHEME)) {
|
||||
int closeIdx = theBuffer.indexOf("\"", SCHEME.length());
|
||||
scheme = theBuffer.substring(SCHEME.length(), closeIdx);
|
||||
theBuffer.delete(0, closeIdx + 1);
|
||||
foundSomething = true;
|
||||
}
|
||||
if (theBuffer.length() > LABEL.length() && theBuffer.substring(0, LABEL.length()).equals(LABEL)) {
|
||||
int closeIdx = theBuffer.indexOf("\"", LABEL.length());
|
||||
label = theBuffer.substring(LABEL.length(), closeIdx);
|
||||
theBuffer.delete(0, closeIdx + 1);
|
||||
foundSomething = true;
|
||||
}
|
||||
// TODO: support enc2231-string as described in
|
||||
// http://tools.ietf.org/html/draft-johnston-http-category-header-02
|
||||
// TODO: support multiple tags in one header as described in
|
||||
// http://hl7.org/implement/standards/fhir/http.html#tags
|
||||
|
||||
while (theBuffer.length() > 0 && (theBuffer.charAt(0) == ' ' || theBuffer.charAt(0) == ';')) {
|
||||
theBuffer.deleteCharAt(0);
|
||||
}
|
||||
|
||||
if (!foundSomething) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (theBuffer.length() > 0 && theBuffer.charAt(0) == ',') {
|
||||
theBuffer.deleteCharAt(0);
|
||||
while (theBuffer.length() > 0 && theBuffer.charAt(0) == ' ') {
|
||||
theBuffer.deleteCharAt(0);
|
||||
}
|
||||
theTagList.add(new Tag(scheme, term, label));
|
||||
parseTagValue(theTagList, theCompleteHeaderValue, theBuffer);
|
||||
} else {
|
||||
theTagList.add(new Tag(scheme, term, label));
|
||||
}
|
||||
|
||||
if (theBuffer.length() > 0) {
|
||||
ourLog.warn("Ignoring extra text at the end of " + Constants.HEADER_CATEGORY + " tag '" + theBuffer.toString() + "' - Complete tag value was: " + theCompleteHeaderValue);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void addTagsToPostOrPut(IResource resource, BaseHttpClientInvocation retVal) {
|
||||
TagList list = (TagList) resource.getResourceMetadata().get(ResourceMetadataKeyEnum.TAG_LIST);
|
||||
if (list != null) {
|
||||
for (Tag tag : list) {
|
||||
if (StringUtils.isNotBlank(tag.getTerm())) {
|
||||
retVal.addHeader(Constants.HEADER_CATEGORY, tag.toHeaderValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static HttpPostClientInvocation createCreateInvocation(IResource theResource, FhirContext theContext) {
|
||||
return createCreateInvocation(theResource, null, null, theContext);
|
||||
}
|
||||
|
||||
public static HttpPostClientInvocation createCreateInvocation(IResource theResource, String theResourceBody, String theId, FhirContext theContext) {
|
||||
RuntimeResourceDefinition def = theContext.getResourceDefinition(theResource);
|
||||
String resourceName = def.getName();
|
||||
|
||||
StringBuilder urlExtension = new StringBuilder();
|
||||
urlExtension.append(resourceName);
|
||||
if (StringUtils.isNotBlank(theId)) {
|
||||
urlExtension.append('/');
|
||||
urlExtension.append(theId);
|
||||
}
|
||||
|
||||
HttpPostClientInvocation retVal;
|
||||
HttpPutClientInvocation retVal;
|
||||
if (StringUtils.isBlank(theResourceBody)) {
|
||||
retVal = new HttpPostClientInvocation(theContext, theResource, urlExtension.toString());
|
||||
retVal = new HttpPutClientInvocation(theContext, theResource, b.toString());
|
||||
} else {
|
||||
retVal = new HttpPostClientInvocation(theContext, theResourceBody, false, urlExtension.toString());
|
||||
retVal = new HttpPutClientInvocation(theContext, theResourceBody, false, b.toString());
|
||||
}
|
||||
|
||||
addTagsToPostOrPut(theResource, retVal);
|
||||
|
||||
// addContentTypeHeaderBasedOnDetectedType(retVal, theResourceBody);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static HttpPutClientInvocation createUpdateInvocation(FhirContext theContext, IResource theResource, String theResourceBody, String theMatchUrl) {
|
||||
HttpPutClientInvocation retVal;
|
||||
if (StringUtils.isBlank(theResourceBody)) {
|
||||
retVal = new HttpPutClientInvocation(theContext, theResource, theMatchUrl);
|
||||
} else {
|
||||
retVal = new HttpPutClientInvocation(theContext, theResourceBody, false,theMatchUrl);
|
||||
}
|
||||
|
||||
addTagsToPostOrPut(theResource, retVal);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
@ -348,57 +253,21 @@ public class MethodUtil {
|
|||
return EncodingEnum.XML;
|
||||
}
|
||||
|
||||
public static HttpGetClientInvocation createConformanceInvocation() {
|
||||
return new HttpGetClientInvocation("metadata");
|
||||
}
|
||||
|
||||
public static MethodOutcome process2xxResponse(FhirContext theContext, String theResourceName, int theResponseStatusCode, String theResponseMimeType, Reader theResponseReader, Map<String, List<String>> theHeaders) {
|
||||
List<String> locationHeaders = new ArrayList<String>();
|
||||
List<String> lh = theHeaders.get(Constants.HEADER_LOCATION_LC);
|
||||
if (lh != null) {
|
||||
locationHeaders.addAll(lh);
|
||||
}
|
||||
List<String> clh = theHeaders.get(Constants.HEADER_CONTENT_LOCATION_LC);
|
||||
if (clh != null) {
|
||||
locationHeaders.addAll(clh);
|
||||
}
|
||||
|
||||
MethodOutcome retVal = new MethodOutcome();
|
||||
if (locationHeaders != null && locationHeaders.size() > 0) {
|
||||
String locationHeader = locationHeaders.get(0);
|
||||
BaseOutcomeReturningMethodBinding.parseContentLocation(retVal, theResourceName, locationHeader);
|
||||
}
|
||||
if (theResponseStatusCode != Constants.STATUS_HTTP_204_NO_CONTENT) {
|
||||
EncodingEnum ct = EncodingEnum.forContentType(theResponseMimeType);
|
||||
if (ct != null) {
|
||||
PushbackReader reader = new PushbackReader(theResponseReader);
|
||||
|
||||
try {
|
||||
int firstByte = reader.read();
|
||||
if (firstByte == -1) {
|
||||
BaseOutcomeReturningMethodBinding.ourLog.debug("No content in response, not going to read");
|
||||
reader = null;
|
||||
} else {
|
||||
reader.unread(firstByte);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
BaseOutcomeReturningMethodBinding.ourLog.debug("No content in response, not going to read", e);
|
||||
reader = null;
|
||||
public static void extractDescription(SearchParameter theParameter, Annotation[] theAnnotations) {
|
||||
for (Annotation annotation : theAnnotations) {
|
||||
if (annotation instanceof Description) {
|
||||
Description desc = (Description) annotation;
|
||||
if (isNotBlank(desc.formalDefinition())) {
|
||||
theParameter.setDescription(desc.formalDefinition());
|
||||
} else {
|
||||
theParameter.setDescription(desc.shortDefinition());
|
||||
}
|
||||
|
||||
if (reader != null) {
|
||||
IParser parser = ct.newParser(theContext);
|
||||
IResource outcome = parser.parseResource(reader);
|
||||
if (outcome instanceof BaseOperationOutcome) {
|
||||
retVal.setOperationOutcome((BaseOperationOutcome) outcome);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
BaseOutcomeReturningMethodBinding.ourLog.debug("Ignoring response content of type: {}", theResponseMimeType);
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static Integer findIdParameterIndex(Method theMethod) {
|
||||
return MethodUtil.findParamAnnotationIndex(theMethod, IdParam.class);
|
||||
}
|
||||
|
||||
public static Integer findParamAnnotationIndex(Method theMethod, Class<?> toFind) {
|
||||
|
@ -416,38 +285,8 @@ public class MethodUtil {
|
|||
return null;
|
||||
}
|
||||
|
||||
public static void extractDescription(SearchParameter theParameter, Annotation[] theAnnotations) {
|
||||
for (Annotation annotation : theAnnotations) {
|
||||
if (annotation instanceof Description) {
|
||||
Description desc = (Description) annotation;
|
||||
if (isNotBlank(desc.formalDefinition())) {
|
||||
theParameter.setDescription(desc.formalDefinition());
|
||||
} else {
|
||||
theParameter.setDescription(desc.shortDefinition());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static IQueryParameterOr<?> singleton(final IQueryParameterType theParam) {
|
||||
return new IQueryParameterOr<IQueryParameterType>() {
|
||||
|
||||
@Override
|
||||
public void setValuesAsQueryTokens(QualifiedParamList theParameters) {
|
||||
if (theParameters.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (theParameters.size() > 1) {
|
||||
throw new IllegalArgumentException("Type " + theParam.getClass().getCanonicalName() + " does not support multiple values");
|
||||
}
|
||||
theParam.setValueAsQueryToken(theParameters.getQualifier(), theParameters.get(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IQueryParameterType> getValuesAsQueryTokens() {
|
||||
return Collections.singletonList(theParam);
|
||||
}
|
||||
};
|
||||
public static Integer findTagListParameterIndex(Method theMethod) {
|
||||
return MethodUtil.findParamAnnotationIndex(theMethod, TagListParam.class);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
|
@ -455,46 +294,6 @@ public class MethodUtil {
|
|||
return MethodUtil.findParamAnnotationIndex(theMethod, VersionIdParam.class);
|
||||
}
|
||||
|
||||
public static Integer findIdParameterIndex(Method theMethod) {
|
||||
return MethodUtil.findParamAnnotationIndex(theMethod, IdParam.class);
|
||||
}
|
||||
|
||||
public static Integer findTagListParameterIndex(Method theMethod) {
|
||||
return MethodUtil.findParamAnnotationIndex(theMethod, TagListParam.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a utility method intended provided to help the JPA module.
|
||||
*/
|
||||
public static IQueryParameterAnd<?> parseQueryParams(RuntimeSearchParam theParamDef, String theUnqualifiedParamName, List<QualifiedParamList> theParameters) {
|
||||
QueryParameterAndBinder binder = null;
|
||||
switch (theParamDef.getParamType()) {
|
||||
case COMPOSITE:
|
||||
throw new UnsupportedOperationException();
|
||||
case DATE:
|
||||
binder = new QueryParameterAndBinder(DateAndListParam.class, Collections.<Class<? extends IQueryParameterType>>emptyList());
|
||||
break;
|
||||
case NUMBER:
|
||||
binder = new QueryParameterAndBinder(NumberAndListParam.class, Collections.<Class<? extends IQueryParameterType>>emptyList());
|
||||
break;
|
||||
case QUANTITY:
|
||||
binder = new QueryParameterAndBinder(QuantityAndListParam.class, Collections.<Class<? extends IQueryParameterType>>emptyList());
|
||||
break;
|
||||
case REFERENCE:
|
||||
binder = new QueryParameterAndBinder(ReferenceAndListParam.class, Collections.<Class<? extends IQueryParameterType>>emptyList());
|
||||
break;
|
||||
case STRING:
|
||||
binder = new QueryParameterAndBinder(StringAndListParam.class, Collections.<Class<? extends IQueryParameterType>>emptyList());
|
||||
break;
|
||||
case TOKEN:
|
||||
binder = new QueryParameterAndBinder(TokenAndListParam.class, Collections.<Class<? extends IQueryParameterType>>emptyList());
|
||||
break;
|
||||
}
|
||||
|
||||
return binder.parse(theUnqualifiedParamName, theParameters);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static List<IParameter> getResourceParameters(FhirContext theContext, Method theMethod, Object theProvider) {
|
||||
List<IParameter> parameters = new ArrayList<IParameter>();
|
||||
|
@ -612,4 +411,267 @@ public class MethodUtil {
|
|||
return parameters;
|
||||
}
|
||||
|
||||
public static void parseClientRequestResourceHeaders(IdDt theRequestedId, Map<String, List<String>> theHeaders, IBaseResource resource) {
|
||||
List<String> lmHeaders = theHeaders.get(Constants.HEADER_LAST_MODIFIED_LOWERCASE);
|
||||
if (lmHeaders != null && lmHeaders.size() > 0 && StringUtils.isNotBlank(lmHeaders.get(0))) {
|
||||
String headerValue = lmHeaders.get(0);
|
||||
Date headerDateValue;
|
||||
try {
|
||||
headerDateValue = DateUtils.parseDate(headerValue);
|
||||
if (resource instanceof IResource) {
|
||||
InstantDt lmValue = new InstantDt(headerDateValue);
|
||||
((IResource) resource).getResourceMetadata().put(ResourceMetadataKeyEnum.UPDATED, lmValue);
|
||||
} else if (resource instanceof IAnyResource) {
|
||||
((IAnyResource) resource).getMeta().setLastUpdated(headerDateValue);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
ourLog.warn("Unable to parse date string '{}'. Error is: {}", headerValue, e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
List<String> clHeaders = theHeaders.get(Constants.HEADER_CONTENT_LOCATION_LC);
|
||||
if (clHeaders != null && clHeaders.size() > 0 && StringUtils.isNotBlank(clHeaders.get(0))) {
|
||||
String headerValue = clHeaders.get(0);
|
||||
if (isNotBlank(headerValue)) {
|
||||
new IdDt(headerValue).applyTo(resource);
|
||||
}
|
||||
}
|
||||
|
||||
IdDt existing = IdDt.of(resource);
|
||||
|
||||
List<String> eTagHeaders = theHeaders.get(Constants.HEADER_ETAG_LC);
|
||||
String eTagVersion = null;
|
||||
if (eTagHeaders != null && eTagHeaders.size() > 0) {
|
||||
eTagVersion = parseETagValue(eTagHeaders.get(0));
|
||||
}
|
||||
if (isNotBlank(eTagVersion)) {
|
||||
if (existing == null || existing.isEmpty()) {
|
||||
if (theRequestedId != null) {
|
||||
theRequestedId.withVersion(eTagVersion).applyTo(resource);
|
||||
}
|
||||
} else if (existing.hasVersionIdPart() == false) {
|
||||
existing.withVersion(eTagVersion).applyTo(resource);
|
||||
}
|
||||
} else if (existing == null || existing.isEmpty()) {
|
||||
if (theRequestedId != null) {
|
||||
theRequestedId.applyTo(resource);
|
||||
}
|
||||
}
|
||||
|
||||
List<String> categoryHeaders = theHeaders.get(Constants.HEADER_CATEGORY_LC);
|
||||
if (categoryHeaders != null && categoryHeaders.size() > 0 && StringUtils.isNotBlank(categoryHeaders.get(0))) {
|
||||
TagList tagList = new TagList();
|
||||
for (String header : categoryHeaders) {
|
||||
parseTagValue(tagList, header);
|
||||
}
|
||||
if (resource instanceof IResource) {
|
||||
ResourceMetadataKeyEnum.TAG_LIST.put((IResource) resource, tagList);
|
||||
} else if (resource instanceof IAnyResource) {
|
||||
IMetaType meta = ((IAnyResource) resource).getMeta();
|
||||
for (Tag next : tagList) {
|
||||
meta.addTag().setSystem(next.getScheme()).setCode(next.getTerm()).setDisplay(next.getLabel());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String parseETagValue(String value) {
|
||||
String eTagVersion;
|
||||
value = value.trim();
|
||||
if (value.length() > 1) {
|
||||
if (value.charAt(value.length() - 1) == '"') {
|
||||
if (value.charAt(0) == '"') {
|
||||
eTagVersion = value.substring(1, value.length() - 1);
|
||||
} else if (value.length() > 3 && value.charAt(0) == 'W' && value.charAt(1) == '/' && value.charAt(2) == '"') {
|
||||
eTagVersion = value.substring(3, value.length() - 1);
|
||||
} else {
|
||||
eTagVersion = value;
|
||||
}
|
||||
} else {
|
||||
eTagVersion = value;
|
||||
}
|
||||
} else {
|
||||
eTagVersion = value;
|
||||
}
|
||||
return eTagVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a utility method intended provided to help the JPA module.
|
||||
*/
|
||||
public static IQueryParameterAnd<?> parseQueryParams(RuntimeSearchParam theParamDef, String theUnqualifiedParamName, List<QualifiedParamList> theParameters) {
|
||||
QueryParameterAndBinder binder = null;
|
||||
switch (theParamDef.getParamType()) {
|
||||
case COMPOSITE:
|
||||
throw new UnsupportedOperationException();
|
||||
case DATE:
|
||||
binder = new QueryParameterAndBinder(DateAndListParam.class, Collections.<Class<? extends IQueryParameterType>> emptyList());
|
||||
break;
|
||||
case NUMBER:
|
||||
binder = new QueryParameterAndBinder(NumberAndListParam.class, Collections.<Class<? extends IQueryParameterType>> emptyList());
|
||||
break;
|
||||
case QUANTITY:
|
||||
binder = new QueryParameterAndBinder(QuantityAndListParam.class, Collections.<Class<? extends IQueryParameterType>> emptyList());
|
||||
break;
|
||||
case REFERENCE:
|
||||
binder = new QueryParameterAndBinder(ReferenceAndListParam.class, Collections.<Class<? extends IQueryParameterType>> emptyList());
|
||||
break;
|
||||
case STRING:
|
||||
binder = new QueryParameterAndBinder(StringAndListParam.class, Collections.<Class<? extends IQueryParameterType>> emptyList());
|
||||
break;
|
||||
case TOKEN:
|
||||
binder = new QueryParameterAndBinder(TokenAndListParam.class, Collections.<Class<? extends IQueryParameterType>> emptyList());
|
||||
break;
|
||||
}
|
||||
|
||||
return binder.parse(theUnqualifiedParamName, theParameters);
|
||||
}
|
||||
|
||||
public static void parseTagValue(TagList tagList, String nextTagComplete) {
|
||||
StringBuilder next = new StringBuilder(nextTagComplete);
|
||||
parseTagValue(tagList, nextTagComplete, next);
|
||||
}
|
||||
|
||||
private static void parseTagValue(TagList theTagList, String theCompleteHeaderValue, StringBuilder theBuffer) {
|
||||
int firstSemicolon = theBuffer.indexOf(";");
|
||||
int deleteTo;
|
||||
if (firstSemicolon == -1) {
|
||||
firstSemicolon = theBuffer.indexOf(",");
|
||||
if (firstSemicolon == -1) {
|
||||
firstSemicolon = theBuffer.length();
|
||||
deleteTo = theBuffer.length();
|
||||
} else {
|
||||
deleteTo = firstSemicolon;
|
||||
}
|
||||
} else {
|
||||
deleteTo = firstSemicolon + 1;
|
||||
}
|
||||
|
||||
String term = theBuffer.substring(0, firstSemicolon);
|
||||
String scheme = null;
|
||||
String label = null;
|
||||
if (isBlank(term)) {
|
||||
return;
|
||||
}
|
||||
|
||||
theBuffer.delete(0, deleteTo);
|
||||
while (theBuffer.length() > 0 && theBuffer.charAt(0) == ' ') {
|
||||
theBuffer.deleteCharAt(0);
|
||||
}
|
||||
|
||||
while (theBuffer.length() > 0) {
|
||||
boolean foundSomething = false;
|
||||
if (theBuffer.length() > SCHEME.length() && theBuffer.substring(0, SCHEME.length()).equals(SCHEME)) {
|
||||
int closeIdx = theBuffer.indexOf("\"", SCHEME.length());
|
||||
scheme = theBuffer.substring(SCHEME.length(), closeIdx);
|
||||
theBuffer.delete(0, closeIdx + 1);
|
||||
foundSomething = true;
|
||||
}
|
||||
if (theBuffer.length() > LABEL.length() && theBuffer.substring(0, LABEL.length()).equals(LABEL)) {
|
||||
int closeIdx = theBuffer.indexOf("\"", LABEL.length());
|
||||
label = theBuffer.substring(LABEL.length(), closeIdx);
|
||||
theBuffer.delete(0, closeIdx + 1);
|
||||
foundSomething = true;
|
||||
}
|
||||
// TODO: support enc2231-string as described in
|
||||
// http://tools.ietf.org/html/draft-johnston-http-category-header-02
|
||||
// TODO: support multiple tags in one header as described in
|
||||
// http://hl7.org/implement/standards/fhir/http.html#tags
|
||||
|
||||
while (theBuffer.length() > 0 && (theBuffer.charAt(0) == ' ' || theBuffer.charAt(0) == ';')) {
|
||||
theBuffer.deleteCharAt(0);
|
||||
}
|
||||
|
||||
if (!foundSomething) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (theBuffer.length() > 0 && theBuffer.charAt(0) == ',') {
|
||||
theBuffer.deleteCharAt(0);
|
||||
while (theBuffer.length() > 0 && theBuffer.charAt(0) == ' ') {
|
||||
theBuffer.deleteCharAt(0);
|
||||
}
|
||||
theTagList.add(new Tag(scheme, term, label));
|
||||
parseTagValue(theTagList, theCompleteHeaderValue, theBuffer);
|
||||
} else {
|
||||
theTagList.add(new Tag(scheme, term, label));
|
||||
}
|
||||
|
||||
if (theBuffer.length() > 0) {
|
||||
ourLog.warn("Ignoring extra text at the end of " + Constants.HEADER_CATEGORY + " tag '" + theBuffer.toString() + "' - Complete tag value was: " + theCompleteHeaderValue);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static MethodOutcome process2xxResponse(FhirContext theContext, String theResourceName, int theResponseStatusCode, String theResponseMimeType, Reader theResponseReader, Map<String, List<String>> theHeaders) {
|
||||
List<String> locationHeaders = new ArrayList<String>();
|
||||
List<String> lh = theHeaders.get(Constants.HEADER_LOCATION_LC);
|
||||
if (lh != null) {
|
||||
locationHeaders.addAll(lh);
|
||||
}
|
||||
List<String> clh = theHeaders.get(Constants.HEADER_CONTENT_LOCATION_LC);
|
||||
if (clh != null) {
|
||||
locationHeaders.addAll(clh);
|
||||
}
|
||||
|
||||
MethodOutcome retVal = new MethodOutcome();
|
||||
if (locationHeaders != null && locationHeaders.size() > 0) {
|
||||
String locationHeader = locationHeaders.get(0);
|
||||
BaseOutcomeReturningMethodBinding.parseContentLocation(retVal, theResourceName, locationHeader);
|
||||
}
|
||||
if (theResponseStatusCode != Constants.STATUS_HTTP_204_NO_CONTENT) {
|
||||
EncodingEnum ct = EncodingEnum.forContentType(theResponseMimeType);
|
||||
if (ct != null) {
|
||||
PushbackReader reader = new PushbackReader(theResponseReader);
|
||||
|
||||
try {
|
||||
int firstByte = reader.read();
|
||||
if (firstByte == -1) {
|
||||
BaseOutcomeReturningMethodBinding.ourLog.debug("No content in response, not going to read");
|
||||
reader = null;
|
||||
} else {
|
||||
reader.unread(firstByte);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
BaseOutcomeReturningMethodBinding.ourLog.debug("No content in response, not going to read", e);
|
||||
reader = null;
|
||||
}
|
||||
|
||||
if (reader != null) {
|
||||
IParser parser = ct.newParser(theContext);
|
||||
IResource outcome = parser.parseResource(reader);
|
||||
if (outcome instanceof BaseOperationOutcome) {
|
||||
retVal.setOperationOutcome((BaseOperationOutcome) outcome);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
BaseOutcomeReturningMethodBinding.ourLog.debug("Ignoring response content of type: {}", theResponseMimeType);
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static IQueryParameterOr<?> singleton(final IQueryParameterType theParam) {
|
||||
return new IQueryParameterOr<IQueryParameterType>() {
|
||||
|
||||
@Override
|
||||
public List<IQueryParameterType> getValuesAsQueryTokens() {
|
||||
return Collections.singletonList(theParam);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValuesAsQueryTokens(QualifiedParamList theParameters) {
|
||||
if (theParameters.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (theParameters.size() > 1) {
|
||||
throw new IllegalArgumentException("Type " + theParam.getClass().getCanonicalName() + " does not support multiple values");
|
||||
}
|
||||
theParam.setValueAsQueryToken(theParameters.getQualifier(), theParameters.get(0));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -111,6 +111,8 @@ public class Constants {
|
|||
public static final int STATUS_HTTP_501_NOT_IMPLEMENTED = 501;
|
||||
public static final String URL_TOKEN_HISTORY = "_history";
|
||||
public static final String URL_TOKEN_METADATA = "metadata";
|
||||
public static final String HEADER_IF_NONE_EXIST = "If-None-Exist";
|
||||
public static final String HEADER_IF_NONE_EXIST_LC = HEADER_IF_NONE_EXIST.toLowerCase();
|
||||
|
||||
static {
|
||||
Map<String, EncodingEnum> valToEncoding = new HashMap<String, EncodingEnum>();
|
||||
|
|
|
@ -24,7 +24,16 @@ ca.uhn.fhir.validation.FhirValidator.noPhlocError=Phloc-schematron library not f
|
|||
|
||||
# JPA Messages
|
||||
|
||||
ca.uhn.fhir.jpa.dao.BaseFhirSystemDao.incomingNoopInTransaction=Transaction contains resource with operation NOOP. This is only valid as a response operation, not in a request.
|
||||
ca.uhn.fhir.jpa.dao.BaseFhirSystemDao.transactionOperationWithMultipleMatchFailure=Failed to {0} resource with match URL "{1}" because this search matched {2} resources
|
||||
ca.uhn.fhir.jpa.dao.BaseFhirSystemDao.transactionOperationFailedNoId=Failed to {0} resource in transaction because no ID was provided
|
||||
ca.uhn.fhir.jpa.dao.BaseFhirSystemDao.transactionOperationFailedUnknownId=Failed to {0} resource in transaction because no resource could be found with ID {1}
|
||||
ca.uhn.fhir.jpa.dao.BaseFhirDao.incomingNoopInTransaction=Transaction contains resource with operation NOOP. This is only valid as a response operation, not in a request.
|
||||
ca.uhn.fhir.jpa.dao.BaseFhirDao.transactionOperationWithMultipleMatchFailure=Failed to {0} resource with match URL "{1}" because this search matched {2} resources
|
||||
ca.uhn.fhir.jpa.dao.BaseFhirDao.transactionOperationFailedNoId=Failed to {0} resource in transaction because no ID was provided
|
||||
ca.uhn.fhir.jpa.dao.BaseFhirDao.transactionOperationFailedUnknownId=Failed to {0} resource in transaction because no resource could be found with ID {1}
|
||||
|
||||
ca.uhn.fhir.jpa.dao.BaseFhirSystemDao.transactionContainsMultipleWithDuplicateId=Transaction bundle contains multiple resources with ID: {0}
|
||||
ca.uhn.fhir.jpa.dao.BaseFhirSystemDao.transactionEntryHasInvalidVerb=Transaction bundle entry has missing or invalid HTTP Verb specified in Bundle.entry.transaction.method. Found value: "{0}"
|
||||
ca.uhn.fhir.jpa.dao.BaseFhirSystemDao.transactionMissingUrl=Unable to perform {0}, no URL provided.
|
||||
ca.uhn.fhir.jpa.dao.BaseFhirSystemDao.transactionInvalidUrl=Unable to perform {0}, URL provided is invalid: {1}
|
||||
|
||||
ca.uhn.fhir.jpa.dao.FhirResourceDao.duplicateCreateForcedId=Can not create entity with ID[{0}], a resource with this ID already exists
|
||||
ca.uhn.fhir.jpa.dao.FhirResourceDao.failedToCreateWithClientAssignedNumericId=Can not create entity with ID[{0}], this server does not allow clients to assign numeric IDs
|
||||
ca.uhn.fhir.jpa.dao.FhirResourceDao.unableToDeleteNotFound=Unable to find resource matching URL "{0}". Deletion failed.
|
||||
|
|
|
@ -7,9 +7,9 @@ org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nul
|
|||
org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||
org.eclipse.jdt.core.compiler.compliance=1.7
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||
|
@ -97,4 +97,4 @@ org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
|
|||
org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
|
||||
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
|
||||
org.eclipse.jdt.core.compiler.source=1.7
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
||||
|
|
|
@ -23,6 +23,8 @@ package ca.uhn.fhir.jpa.dao;
|
|||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.text.Normalizer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
@ -48,6 +50,8 @@ import javax.persistence.criteria.Root;
|
|||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.client.utils.URLEncodedUtils;
|
||||
import org.hl7.fhir.instance.model.IBaseResource;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
@ -77,6 +81,7 @@ import ca.uhn.fhir.jpa.entity.ResourceTable;
|
|||
import ca.uhn.fhir.jpa.entity.ResourceTag;
|
||||
import ca.uhn.fhir.jpa.entity.TagDefinition;
|
||||
import ca.uhn.fhir.jpa.util.StopWatch;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterAnd;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.api.Tag;
|
||||
|
@ -87,6 +92,8 @@ import ca.uhn.fhir.model.primitive.IdDt;
|
|||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.method.MethodUtil;
|
||||
import ca.uhn.fhir.rest.method.QualifiedParamList;
|
||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
@ -95,15 +102,16 @@ import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
|||
import ca.uhn.fhir.util.FhirTerser;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.Collections2;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
public abstract class BaseFhirDao implements IDao {
|
||||
|
||||
public static final String UCUM_NS = "http://unitsofmeasure.org";
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseFhirDao.class);
|
||||
|
||||
private static final Map<FhirVersionEnum, FhirContext> ourRetrievalContexts = new HashMap<FhirVersionEnum, FhirContext>();
|
||||
public static final String UCUM_NS = "http://unitsofmeasure.org";
|
||||
|
||||
@Autowired(required = true)
|
||||
private DaoConfig myConfig;
|
||||
|
@ -114,8 +122,6 @@ public abstract class BaseFhirDao implements IDao {
|
|||
private EntityManager myEntityManager;
|
||||
|
||||
private List<IDaoListener> myListeners = new ArrayList<IDaoListener>();
|
||||
private ISearchParamExtractor mySearchParamExtractor;
|
||||
|
||||
@Autowired
|
||||
private PlatformTransactionManager myPlatformTransactionManager;
|
||||
|
||||
|
@ -124,6 +130,8 @@ public abstract class BaseFhirDao implements IDao {
|
|||
|
||||
private Map<Class<? extends IBaseResource>, IFhirResourceDao<?>> myResourceTypeToDao;
|
||||
|
||||
private ISearchParamExtractor mySearchParamExtractor;
|
||||
|
||||
protected void createForcedIdIfNeeded(ResourceTable entity, IdDt id) {
|
||||
if (id.isEmpty() == false && id.hasIdPart()) {
|
||||
if (isValidPid(id)) {
|
||||
|
@ -508,19 +516,6 @@ public abstract class BaseFhirDao implements IDao {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
protected static String normalizeString(String theString) {
|
||||
char[] out = new char[theString.length()];
|
||||
theString = Normalizer.normalize(theString, Normalizer.Form.NFD);
|
||||
int j = 0;
|
||||
for (int i = 0, n = theString.length(); i < n; ++i) {
|
||||
char c = theString.charAt(i);
|
||||
if (c <= '\u007F') {
|
||||
out[j++] = c;
|
||||
}
|
||||
}
|
||||
return new String(out).toUpperCase();
|
||||
}
|
||||
|
||||
protected void notifyWriteCompleted() {
|
||||
for (IDaoListener next : myListeners) {
|
||||
next.writeCompleted();
|
||||
|
@ -579,6 +574,58 @@ public abstract class BaseFhirDao implements IDao {
|
|||
|
||||
}
|
||||
|
||||
protected Set<Long> processMatchUrl(String theMatchUrl, Class<? extends IBaseResource> theResourceType) {
|
||||
RuntimeResourceDefinition resourceDef = getContext().getResourceDefinition(theResourceType);
|
||||
|
||||
SearchParameterMap paramMap = translateMatchUrl(theMatchUrl, resourceDef);
|
||||
|
||||
IFhirResourceDao<? extends IResource> dao = getDao(theResourceType);
|
||||
Set<Long> ids = dao.searchForIdsWithAndOr(paramMap);
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
protected SearchParameterMap translateMatchUrl(String theMatchUrl, RuntimeResourceDefinition resourceDef) {
|
||||
SearchParameterMap paramMap = new SearchParameterMap();
|
||||
List<NameValuePair> parameters;
|
||||
try {
|
||||
parameters = URLEncodedUtils.parse(new URI(theMatchUrl), "UTF-8");
|
||||
} catch (URISyntaxException e) {
|
||||
throw new InvalidRequestException("Failed to parse match URL[" + theMatchUrl + "] - Error was: " + e.toString());
|
||||
}
|
||||
|
||||
ArrayListMultimap<String, QualifiedParamList> nameToParamLists = ArrayListMultimap.create();
|
||||
for (NameValuePair next : parameters) {
|
||||
String paramName = next.getName();
|
||||
String qualifier = null;
|
||||
for (int i = 0; i < paramMap.size(); i++) {
|
||||
switch (paramName.charAt(i)) {
|
||||
case '.':
|
||||
case ':':
|
||||
qualifier = paramName.substring(i);
|
||||
paramName = paramName.substring(0, i);
|
||||
i = Integer.MAX_VALUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QualifiedParamList paramList = QualifiedParamList.splitQueryStringByCommasIgnoreEscape(qualifier, next.getValue());
|
||||
nameToParamLists.put(paramName, paramList);
|
||||
}
|
||||
|
||||
for (String nextParamName : nameToParamLists.keySet()) {
|
||||
RuntimeSearchParam paramDef = resourceDef.getSearchParam(nextParamName);
|
||||
if (paramDef == null) {
|
||||
throw new InvalidRequestException("Failed to parse match URL[" + theMatchUrl + "] - Resource type " + resourceDef.getName() + " does not have a parameter with name: " + nextParamName);
|
||||
}
|
||||
|
||||
List<QualifiedParamList> paramList = nameToParamLists.get(nextParamName);
|
||||
IQueryParameterAnd<?> param = MethodUtil.parseQueryParams(paramDef, nextParamName, paramList);
|
||||
paramMap.add(nextParamName, param);
|
||||
}
|
||||
return paramMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerDaoListener(IDaoListener theListener) {
|
||||
Validate.notNull(theListener, "theListener");
|
||||
|
@ -832,7 +879,20 @@ public abstract class BaseFhirDao implements IDao {
|
|||
}
|
||||
}
|
||||
|
||||
protected String translatePidIdToForcedId(Long theId) {
|
||||
ForcedId forcedId = myEntityManager.find(ForcedId.class, theId);
|
||||
if (forcedId != null) {
|
||||
return forcedId.getForcedId();
|
||||
} else {
|
||||
return theId.toString();
|
||||
}
|
||||
}
|
||||
|
||||
protected ResourceTable updateEntity(final IResource theResource, ResourceTable entity, boolean theUpdateHistory, Date theDeletedTimestampOrNull) {
|
||||
return updateEntity(theResource, entity, theUpdateHistory, theDeletedTimestampOrNull, true,true);
|
||||
}
|
||||
|
||||
protected ResourceTable updateEntity(final IResource theResource, ResourceTable entity, boolean theUpdateHistory, Date theDeletedTimestampOrNull, boolean thePerformIndexing, boolean theUpdateVersion) {
|
||||
if (entity.getPublished() == null) {
|
||||
entity.setPublished(new Date());
|
||||
}
|
||||
|
@ -849,7 +909,9 @@ public abstract class BaseFhirDao implements IDao {
|
|||
myEntityManager.persist(historyEntry);
|
||||
}
|
||||
|
||||
entity.setVersion(entity.getVersion() + 1);
|
||||
if (theUpdateVersion) {
|
||||
entity.setVersion(entity.getVersion() + 1);
|
||||
}
|
||||
|
||||
Collection<ResourceIndexedSearchParamString> paramsString = new ArrayList<ResourceIndexedSearchParamString>(entity.getParamsString());
|
||||
Collection<ResourceIndexedSearchParamToken> paramsToken = new ArrayList<ResourceIndexedSearchParamToken>(entity.getParamsToken());
|
||||
|
@ -858,12 +920,13 @@ public abstract class BaseFhirDao implements IDao {
|
|||
Collection<ResourceIndexedSearchParamDate> paramsDate = new ArrayList<ResourceIndexedSearchParamDate>(entity.getParamsDate());
|
||||
Collection<ResourceLink> resourceLinks = new ArrayList<ResourceLink>(entity.getResourceLinks());
|
||||
|
||||
final List<ResourceIndexedSearchParamString> stringParams;
|
||||
final List<ResourceIndexedSearchParamToken> tokenParams;
|
||||
final List<ResourceIndexedSearchParamNumber> numberParams;
|
||||
final List<ResourceIndexedSearchParamQuantity> quantityParams;
|
||||
final List<ResourceIndexedSearchParamDate> dateParams;
|
||||
final List<ResourceLink> links;
|
||||
List<ResourceIndexedSearchParamString> stringParams = null;
|
||||
List<ResourceIndexedSearchParamToken> tokenParams = null;
|
||||
List<ResourceIndexedSearchParamNumber> numberParams = null;
|
||||
List<ResourceIndexedSearchParamQuantity> quantityParams = null;
|
||||
List<ResourceIndexedSearchParamDate> dateParams = null;
|
||||
List<ResourceLink> links = null;
|
||||
|
||||
if (theDeletedTimestampOrNull != null) {
|
||||
|
||||
stringParams = Collections.emptyList();
|
||||
|
@ -875,7 +938,7 @@ public abstract class BaseFhirDao implements IDao {
|
|||
entity.setDeleted(theDeletedTimestampOrNull);
|
||||
entity.setUpdated(theDeletedTimestampOrNull);
|
||||
|
||||
} else {
|
||||
} else if (thePerformIndexing) {
|
||||
|
||||
stringParams = extractSearchParamStrings(entity, theResource);
|
||||
numberParams = extractSearchParamNumber(entity, theResource);
|
||||
|
@ -893,7 +956,6 @@ public abstract class BaseFhirDao implements IDao {
|
|||
|
||||
links = extractResourceLinks(entity, theResource);
|
||||
populateResourceIntoEntity(theResource, entity);
|
||||
|
||||
entity.setUpdated(new Date());
|
||||
entity.setLanguage(theResource.getLanguage().getValue());
|
||||
entity.setParamsString(stringParams);
|
||||
|
@ -909,6 +971,12 @@ public abstract class BaseFhirDao implements IDao {
|
|||
entity.setResourceLinks(links);
|
||||
entity.setHasLinks(links.isEmpty() == false);
|
||||
|
||||
} else {
|
||||
|
||||
populateResourceIntoEntity(theResource, entity);
|
||||
entity.setUpdated(new Date());
|
||||
entity.setLanguage(theResource.getLanguage().getValue());
|
||||
|
||||
}
|
||||
|
||||
if (entity.getId() == null) {
|
||||
|
@ -922,59 +990,63 @@ public abstract class BaseFhirDao implements IDao {
|
|||
entity = myEntityManager.merge(entity);
|
||||
}
|
||||
|
||||
if (entity.isParamsStringPopulated()) {
|
||||
for (ResourceIndexedSearchParamString next : paramsString) {
|
||||
myEntityManager.remove(next);
|
||||
}
|
||||
}
|
||||
for (ResourceIndexedSearchParamString next : stringParams) {
|
||||
myEntityManager.persist(next);
|
||||
}
|
||||
if (thePerformIndexing) {
|
||||
|
||||
if (entity.isParamsTokenPopulated()) {
|
||||
for (ResourceIndexedSearchParamToken next : paramsToken) {
|
||||
myEntityManager.remove(next);
|
||||
if (entity.isParamsStringPopulated()) {
|
||||
for (ResourceIndexedSearchParamString next : paramsString) {
|
||||
myEntityManager.remove(next);
|
||||
}
|
||||
}
|
||||
for (ResourceIndexedSearchParamString next : stringParams) {
|
||||
myEntityManager.persist(next);
|
||||
}
|
||||
}
|
||||
for (ResourceIndexedSearchParamToken next : tokenParams) {
|
||||
myEntityManager.persist(next);
|
||||
}
|
||||
|
||||
if (entity.isParamsNumberPopulated()) {
|
||||
for (ResourceIndexedSearchParamNumber next : paramsNumber) {
|
||||
myEntityManager.remove(next);
|
||||
if (entity.isParamsTokenPopulated()) {
|
||||
for (ResourceIndexedSearchParamToken next : paramsToken) {
|
||||
myEntityManager.remove(next);
|
||||
}
|
||||
}
|
||||
for (ResourceIndexedSearchParamToken next : tokenParams) {
|
||||
myEntityManager.persist(next);
|
||||
}
|
||||
}
|
||||
for (ResourceIndexedSearchParamNumber next : numberParams) {
|
||||
myEntityManager.persist(next);
|
||||
}
|
||||
|
||||
if (entity.isParamsQuantityPopulated()) {
|
||||
for (ResourceIndexedSearchParamQuantity next : paramsQuantity) {
|
||||
myEntityManager.remove(next);
|
||||
if (entity.isParamsNumberPopulated()) {
|
||||
for (ResourceIndexedSearchParamNumber next : paramsNumber) {
|
||||
myEntityManager.remove(next);
|
||||
}
|
||||
}
|
||||
for (ResourceIndexedSearchParamNumber next : numberParams) {
|
||||
myEntityManager.persist(next);
|
||||
}
|
||||
}
|
||||
for (ResourceIndexedSearchParamQuantity next : quantityParams) {
|
||||
myEntityManager.persist(next);
|
||||
}
|
||||
|
||||
if (entity.isParamsDatePopulated()) {
|
||||
for (ResourceIndexedSearchParamDate next : paramsDate) {
|
||||
myEntityManager.remove(next);
|
||||
if (entity.isParamsQuantityPopulated()) {
|
||||
for (ResourceIndexedSearchParamQuantity next : paramsQuantity) {
|
||||
myEntityManager.remove(next);
|
||||
}
|
||||
}
|
||||
for (ResourceIndexedSearchParamQuantity next : quantityParams) {
|
||||
myEntityManager.persist(next);
|
||||
}
|
||||
}
|
||||
for (ResourceIndexedSearchParamDate next : dateParams) {
|
||||
myEntityManager.persist(next);
|
||||
}
|
||||
|
||||
if (entity.isHasLinks()) {
|
||||
for (ResourceLink next : resourceLinks) {
|
||||
myEntityManager.remove(next);
|
||||
if (entity.isParamsDatePopulated()) {
|
||||
for (ResourceIndexedSearchParamDate next : paramsDate) {
|
||||
myEntityManager.remove(next);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (ResourceLink next : links) {
|
||||
myEntityManager.persist(next);
|
||||
}
|
||||
for (ResourceIndexedSearchParamDate next : dateParams) {
|
||||
myEntityManager.persist(next);
|
||||
}
|
||||
|
||||
if (entity.isHasLinks()) {
|
||||
for (ResourceLink next : resourceLinks) {
|
||||
myEntityManager.remove(next);
|
||||
}
|
||||
}
|
||||
for (ResourceLink next : links) {
|
||||
myEntityManager.persist(next);
|
||||
}
|
||||
|
||||
} // if thePerformIndexing
|
||||
|
||||
myEntityManager.flush();
|
||||
|
||||
|
@ -985,4 +1057,17 @@ public abstract class BaseFhirDao implements IDao {
|
|||
return entity;
|
||||
}
|
||||
|
||||
protected static String normalizeString(String theString) {
|
||||
char[] out = new char[theString.length()];
|
||||
theString = Normalizer.normalize(theString, Normalizer.Form.NFD);
|
||||
int j = 0;
|
||||
for (int i = 0, n = theString.length(); i < n; ++i) {
|
||||
char c = theString.charAt(i);
|
||||
if (c <= '\u007F') {
|
||||
out[j++] = c;
|
||||
}
|
||||
}
|
||||
return new String(out).toUpperCase();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,11 +20,8 @@ package ca.uhn.fhir.jpa.dao;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -36,27 +33,14 @@ import javax.persistence.criteria.CriteriaBuilder;
|
|||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.client.utils.URLEncodedUtils;
|
||||
import org.hl7.fhir.instance.model.IBaseResource;
|
||||
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.util.StopWatch;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterAnd;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.rest.method.MethodUtil;
|
||||
import ca.uhn.fhir.rest.method.QualifiedParamList;
|
||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
|
||||
public abstract class BaseFhirSystemDao<T> extends BaseFhirDao implements IFhirSystemDao<T> {
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseFhirSystemDao.class);
|
||||
|
||||
|
@ -82,53 +66,6 @@ public abstract class BaseFhirSystemDao<T> extends BaseFhirDao implements IFhirS
|
|||
return myEntityManager.find(ResourceTable.class, candidateMatches.iterator().next());
|
||||
}
|
||||
|
||||
protected Set<Long> processMatchUrl(String theMatchUrl, Class<? extends IBaseResource> theResourceType) {
|
||||
RuntimeResourceDefinition resourceDef = getContext().getResourceDefinition(theResourceType);
|
||||
|
||||
SearchParameterMap paramMap = new SearchParameterMap();
|
||||
List<NameValuePair> parameters;
|
||||
try {
|
||||
parameters = URLEncodedUtils.parse(new URI(theMatchUrl), "UTF-8");
|
||||
} catch (URISyntaxException e) {
|
||||
throw new InvalidRequestException("Failed to parse match URL[" + theMatchUrl + "] - Error was: " + e.toString());
|
||||
}
|
||||
|
||||
ArrayListMultimap<String, QualifiedParamList> nameToParamLists = ArrayListMultimap.create();
|
||||
for (NameValuePair next : parameters) {
|
||||
String paramName = next.getName();
|
||||
String qualifier = null;
|
||||
for (int i = 0; i < paramMap.size(); i++) {
|
||||
switch (paramName.charAt(i)) {
|
||||
case '.':
|
||||
case ':':
|
||||
qualifier = paramName.substring(i);
|
||||
paramName = paramName.substring(0, i);
|
||||
i = Integer.MAX_VALUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QualifiedParamList paramList = QualifiedParamList.splitQueryStringByCommasIgnoreEscape(qualifier, next.getValue());
|
||||
nameToParamLists.put(paramName, paramList);
|
||||
}
|
||||
|
||||
for (String nextParamName : nameToParamLists.keySet()) {
|
||||
RuntimeSearchParam paramDef = resourceDef.getSearchParam(nextParamName);
|
||||
if (paramDef == null) {
|
||||
throw new InvalidRequestException("Failed to parse match URL[" + theMatchUrl + "] - Resource type " + resourceDef.getName() + " does not have a parameter with name: " + nextParamName);
|
||||
}
|
||||
|
||||
List<QualifiedParamList> paramList = nameToParamLists.get(nextParamName);
|
||||
IQueryParameterAnd<?> param = MethodUtil.parseQueryParams(paramDef, nextParamName, paramList);
|
||||
paramMap.add(nextParamName, param);
|
||||
}
|
||||
|
||||
IFhirResourceDao<? extends IResource> dao = getDao(theResourceType);
|
||||
Set<Long> ids = dao.searchForIdsWithAndOr(paramMap);
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBundleProvider history(Date theSince) {
|
||||
StopWatch w = new StopWatch();
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
|
||||
public class DaoMethodOutcome extends MethodOutcome {
|
||||
|
||||
private ResourceTable myEntity;
|
||||
private IResource myResource;
|
||||
|
||||
public ResourceTable getEntity() {
|
||||
return myEntity;
|
||||
}
|
||||
|
||||
public IResource getResource() {
|
||||
return myResource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DaoMethodOutcome setCreated(Boolean theCreated) {
|
||||
super.setCreated(theCreated);
|
||||
return this;
|
||||
}
|
||||
|
||||
public DaoMethodOutcome setEntity(ResourceTable theEntity) {
|
||||
myEntity = theEntity;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DaoMethodOutcome setResource(IResource theResource) {
|
||||
myResource = theResource;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -20,229 +20,516 @@ package ca.uhn.fhir.jpa.dao;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle.EntryTransactionResponse;
|
||||
import ca.uhn.fhir.model.dstu2.resource.OperationOutcome;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.IssueSeverityEnum;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.util.FhirTerser;
|
||||
|
||||
public class FhirSystemDaoDstu2 extends BaseFhirSystemDao<Bundle> {
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirSystemDaoDstu2.class);
|
||||
|
||||
private UrlParts parseUrl(String theAction, String theUrl) {
|
||||
UrlParts retVal = new UrlParts();
|
||||
|
||||
//@formatter:off
|
||||
/*
|
||||
* We assume that the URL passed in is in one of the following forms:
|
||||
* [Resource Type]?[Search Params]
|
||||
* [Resource Type]/[Resource ID]
|
||||
* [Resource Type]/[Resource ID]/_history/[Version ID]
|
||||
*/
|
||||
//@formatter:on
|
||||
int nextStart = 0;
|
||||
boolean nextIsHistory = false;
|
||||
|
||||
for (int idx = 0; idx < theUrl.length(); idx++) {
|
||||
char nextChar = theUrl.charAt(idx);
|
||||
boolean atEnd = (idx + 1) == theUrl.length();
|
||||
if (nextChar == '?' || nextChar == '/' || atEnd) {
|
||||
int endIdx = atEnd ? idx + 1 : idx;
|
||||
String nextSubstring = theUrl.substring(nextStart, endIdx);
|
||||
if (retVal.getResourceType() == null) {
|
||||
retVal.setResourceType(nextSubstring);
|
||||
} else if (retVal.getResourceId() == null) {
|
||||
retVal.setResourceId(nextSubstring);
|
||||
} else if (nextIsHistory) {
|
||||
retVal.setVersionId(nextSubstring);
|
||||
} else {
|
||||
if (nextSubstring.equals(Constants.URL_TOKEN_HISTORY)) {
|
||||
nextIsHistory = true;
|
||||
} else {
|
||||
String msg = getContext().getLocalizer().getMessage(BaseFhirSystemDao.class, "transactionInvalidUrl", theAction, theUrl);
|
||||
throw new InvalidRequestException(msg);
|
||||
}
|
||||
}
|
||||
if (nextChar == '?') {
|
||||
if (theUrl.length() > idx + 1) {
|
||||
retVal.setParams(theUrl.substring(idx + 1, theUrl.length()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
nextStart = idx + 1;
|
||||
}
|
||||
}
|
||||
|
||||
RuntimeResourceDefinition resType = getContext().getResourceDefinition(retVal.getResourceType());
|
||||
IFhirResourceDao<? extends IResource> dao = null;
|
||||
if (resType != null) {
|
||||
dao = getDao(resType.getImplementingClass());
|
||||
}
|
||||
if (dao == null) {
|
||||
String msg = getContext().getLocalizer().getMessage(BaseFhirSystemDao.class, "transactionInvalidUrl", theAction, theUrl);
|
||||
throw new InvalidRequestException(msg);
|
||||
}
|
||||
retVal.setDao(dao);
|
||||
|
||||
if (retVal.getResourceId() == null && retVal.getParams() == null) {
|
||||
String msg = getContext().getLocalizer().getMessage(BaseFhirSystemDao.class, "transactionInvalidUrl", theAction, theUrl);
|
||||
throw new InvalidRequestException(msg);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Transactional(propagation = Propagation.REQUIRED)
|
||||
@Override
|
||||
public Bundle transaction(Bundle theResources) {
|
||||
ourLog.info("Beginning transaction with {} resources", theResources.getEntry().size());
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
// Set<IdDt> allIds = new HashSet<IdDt>();
|
||||
//
|
||||
// for (int i = 0; i < theResources.size(); i++) {
|
||||
// IResource res = theResources.get(i);
|
||||
// if (res.getId().hasIdPart() && !res.getId().hasResourceType()) {
|
||||
// res.setId(new IdDt(toResourceName(res.getClass()), res.getId().getIdPart()));
|
||||
// }
|
||||
//
|
||||
// /*
|
||||
// * Ensure that the bundle doesn't have any duplicates, since this causes all kinds of weirdness
|
||||
// */
|
||||
// if (res.getId().hasResourceType() && res.getId().hasIdPart()) {
|
||||
// IdDt nextId = res.getId().toUnqualifiedVersionless();
|
||||
// if (!allIds.add(nextId)) {
|
||||
// throw new InvalidRequestException("Transaction bundle contains multiple resources with ID: " + nextId);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// FhirTerser terser = getContext().newTerser();
|
||||
//
|
||||
// int creations = 0;
|
||||
// int updates = 0;
|
||||
//
|
||||
// Map<IdDt, IdDt> idConversions = new HashMap<IdDt, IdDt>();
|
||||
//
|
||||
// List<ResourceTable> persistedResources = new ArrayList<ResourceTable>();
|
||||
//
|
||||
// List<IResource> retVal = new ArrayList<IResource>();
|
||||
// OperationOutcome oo = new OperationOutcome();
|
||||
// retVal.add(oo);
|
||||
//
|
||||
// for (int resourceIdx = 0; resourceIdx < theResources.size(); resourceIdx++) {
|
||||
// IResource nextResource = theResources.get(resourceIdx);
|
||||
//
|
||||
// IdDt nextId = nextResource.getId();
|
||||
// if (nextId == null) {
|
||||
// nextId = new IdDt();
|
||||
// }
|
||||
//
|
||||
// String resourceName = toResourceName(nextResource);
|
||||
// BundleEntryTransactionOperationEnum nextResouceOperationIn = ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(nextResource);
|
||||
// if (nextResouceOperationIn == null && hasValue(ResourceMetadataKeyEnum.DELETED_AT.get(nextResource))) {
|
||||
// nextResouceOperationIn = BundleEntryTransactionOperationEnum.DELETE;
|
||||
// }
|
||||
//
|
||||
// String matchUrl = ResourceMetadataKeyEnum.LINK_SEARCH.get(nextResource);
|
||||
// Set<Long> candidateMatches = null;
|
||||
// if (StringUtils.isNotBlank(matchUrl)) {
|
||||
// candidateMatches = processMatchUrl(matchUrl, nextResource.getClass());
|
||||
// }
|
||||
//
|
||||
// ResourceTable entity;
|
||||
// if (nextResouceOperationIn == BundleEntryTransactionOperationEnum.CREATE) {
|
||||
// entity = null;
|
||||
// } else if (nextResouceOperationIn == BundleEntryTransactionOperationEnum.UPDATE || nextResouceOperationIn == BundleEntryTransactionOperationEnum.DELETE) {
|
||||
// if (candidateMatches == null || candidateMatches.size() == 0) {
|
||||
// if (nextId == null || StringUtils.isBlank(nextId.getIdPart())) {
|
||||
// throw new InvalidRequestException(getContext().getLocalizer().getMessage(FhirSystemDaoDstu2.class, "transactionOperationFailedNoId", nextResouceOperationIn.name()));
|
||||
// }
|
||||
// entity = tryToLoadEntity(nextId);
|
||||
// if (entity == null) {
|
||||
// if (nextResouceOperationIn == BundleEntryTransactionOperationEnum.UPDATE) {
|
||||
// ourLog.debug("Attempting to UPDATE resource with unknown ID '{}', will CREATE instead", nextId);
|
||||
// } else if (candidateMatches == null) {
|
||||
// throw new InvalidRequestException(getContext().getLocalizer().getMessage(FhirSystemDaoDstu2.class, "transactionOperationFailedUnknownId", nextResouceOperationIn.name(), nextId));
|
||||
// } else {
|
||||
// ourLog.debug("Resource with match URL [{}] already exists, will be NOOP", matchUrl);
|
||||
// ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(nextResource, BundleEntryTransactionOperationEnum.NOOP);
|
||||
// persistedResources.add(null);
|
||||
// retVal.add(nextResource);
|
||||
// continue;
|
||||
// }
|
||||
// }
|
||||
// } else if (candidateMatches.size() == 1) {
|
||||
// entity = loadFirstEntityFromCandidateMatches(candidateMatches);
|
||||
// } else {
|
||||
// throw new InvalidRequestException(getContext().getLocalizer().getMessage(FhirSystemDaoDstu2.class, "transactionOperationWithMultipleMatchFailure", nextResouceOperationIn.name(), matchUrl, candidateMatches.size()));
|
||||
// }
|
||||
// } else if (nextResouceOperationIn == BundleEntryTransactionOperationEnum.NOOP) {
|
||||
// throw new InvalidRequestException(getContext().getLocalizer().getMessage(FhirSystemDaoDstu2.class, "incomingNoopInTransaction"));
|
||||
// } else if (nextId.isEmpty()) {
|
||||
// entity = null;
|
||||
// } else {
|
||||
// entity = tryToLoadEntity(nextId);
|
||||
// }
|
||||
//
|
||||
// BundleEntryTransactionOperationEnum nextResouceOperationOut;
|
||||
// if (entity == null) {
|
||||
// nextResouceOperationOut = BundleEntryTransactionOperationEnum.CREATE;
|
||||
// entity = toEntity(nextResource);
|
||||
// if (nextId.isEmpty() == false && nextId.getIdPart().startsWith("cid:")) {
|
||||
// ourLog.debug("Resource in transaction has ID[{}], will replace with server assigned ID", nextId.getIdPart());
|
||||
// } else if (nextResouceOperationIn == BundleEntryTransactionOperationEnum.CREATE) {
|
||||
// if (nextId.isEmpty() == false) {
|
||||
// ourLog.debug("Resource in transaction has ID[{}] but is marked for CREATE, will ignore ID", nextId.getIdPart());
|
||||
// }
|
||||
// if (candidateMatches != null) {
|
||||
// if (candidateMatches.size() == 1) {
|
||||
// ourLog.debug("Resource with match URL [{}] already exists, will be NOOP", matchUrl);
|
||||
// BaseHasResource existingEntity = loadFirstEntityFromCandidateMatches(candidateMatches);
|
||||
// IResource existing = (IResource) toResource(existingEntity);
|
||||
// ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(existing, BundleEntryTransactionOperationEnum.NOOP);
|
||||
// persistedResources.add(null);
|
||||
// retVal.add(existing);
|
||||
// continue;
|
||||
// }
|
||||
// if (candidateMatches.size() > 1) {
|
||||
// throw new InvalidRequestException(getContext().getLocalizer().getMessage(FhirSystemDaoDstu2.class, "transactionOperationWithMultipleMatchFailure", BundleEntryTransactionOperationEnum.CREATE.name(), matchUrl, candidateMatches.size()));
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// createForcedIdIfNeeded(entity, nextId);
|
||||
// }
|
||||
// myEntityManager.persist(entity);
|
||||
// if (entity.getForcedId() != null) {
|
||||
// myEntityManager.persist(entity.getForcedId());
|
||||
// }
|
||||
// creations++;
|
||||
// ourLog.info("Resource Type[{}] with ID[{}] does not exist, creating it", resourceName, nextId);
|
||||
// } else {
|
||||
// nextResouceOperationOut = nextResouceOperationIn;
|
||||
// if (nextResouceOperationOut == null) {
|
||||
// nextResouceOperationOut = BundleEntryTransactionOperationEnum.UPDATE;
|
||||
// }
|
||||
// updates++;
|
||||
// ourLog.info("Resource Type[{}] with ID[{}] exists, updating it", resourceName, nextId);
|
||||
// }
|
||||
//
|
||||
// persistedResources.add(entity);
|
||||
// retVal.add(nextResource);
|
||||
// ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(nextResource, nextResouceOperationOut);
|
||||
// }
|
||||
//
|
||||
// ourLog.info("Flushing transaction to database");
|
||||
// myEntityManager.flush();
|
||||
//
|
||||
// for (int i = 0; i < persistedResources.size(); i++) {
|
||||
// ResourceTable entity = persistedResources.get(i);
|
||||
//
|
||||
// String resourceName = toResourceName(theResources.get(i));
|
||||
// IdDt nextId = theResources.get(i).getId();
|
||||
//
|
||||
// IdDt newId;
|
||||
//
|
||||
// if (entity == null) {
|
||||
// newId = retVal.get(i + 1).getId().toUnqualifiedVersionless();
|
||||
// } else {
|
||||
// newId = entity.getIdDt().toUnqualifiedVersionless();
|
||||
// }
|
||||
//
|
||||
// if (nextId == null || nextId.isEmpty()) {
|
||||
// ourLog.info("Transaction resource (with no preexisting ID) has been assigned new ID[{}]", nextId, newId);
|
||||
// } else {
|
||||
// if (nextId.toUnqualifiedVersionless().equals(newId)) {
|
||||
// ourLog.info("Transaction resource ID[{}] is being updated", newId);
|
||||
// } else {
|
||||
// if (!nextId.getIdPart().startsWith("#")) {
|
||||
// nextId = new IdDt(resourceName + '/' + nextId.getIdPart());
|
||||
// ourLog.info("Transaction resource ID[{}] has been assigned new ID[{}]", nextId, newId);
|
||||
// idConversions.put(nextId, newId);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// for (IResource nextResource : theResources) {
|
||||
// List<BaseResourceReferenceDt> allRefs = terser.getAllPopulatedChildElementsOfType(nextResource, BaseResourceReferenceDt.class);
|
||||
// for (BaseResourceReferenceDt nextRef : allRefs) {
|
||||
// IdDt nextId = nextRef.getReference();
|
||||
// if (idConversions.containsKey(nextId)) {
|
||||
// IdDt newId = idConversions.get(nextId);
|
||||
// ourLog.info(" * Replacing resource ref {} with {}", nextId, newId);
|
||||
// nextRef.setReference(newId);
|
||||
// } else {
|
||||
// ourLog.debug(" * Reference [{}] does not exist in bundle", nextId);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// ourLog.info("Re-flushing updated resource references and extracting search criteria");
|
||||
//
|
||||
// for (int i = 0; i < theResources.size(); i++) {
|
||||
// IResource resource = theResources.get(i);
|
||||
// ResourceTable table = persistedResources.get(i);
|
||||
// if (table == null) {
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
// InstantDt deletedInstantOrNull = ResourceMetadataKeyEnum.DELETED_AT.get(resource);
|
||||
// Date deletedTimestampOrNull = deletedInstantOrNull != null ? deletedInstantOrNull.getValue() : null;
|
||||
// if (deletedInstantOrNull == null && ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(resource) == BundleEntryTransactionOperationEnum.DELETE) {
|
||||
// deletedTimestampOrNull = new Date();
|
||||
// ResourceMetadataKeyEnum.DELETED_AT.put(resource, new InstantDt(deletedTimestampOrNull));
|
||||
// }
|
||||
//
|
||||
// updateEntity(resource, table, table.getId() != null, deletedTimestampOrNull);
|
||||
// }
|
||||
//
|
||||
// long delay = System.currentTimeMillis() - start;
|
||||
// ourLog.info("Transaction completed in {}ms with {} creations and {} updates", new Object[] { delay, creations, updates });
|
||||
//
|
||||
// oo.addIssue().setSeverity(IssueSeverityEnum.INFORMATION).setDetails("Transaction completed in " + delay + "ms with " + creations + " creations and " + updates + " updates");
|
||||
//
|
||||
// notifyWriteCompleted();
|
||||
Set<IdDt> allIds = new HashSet<IdDt>();
|
||||
Map<IdDt, IdDt> idSubstitutions = new HashMap<IdDt, IdDt>();
|
||||
Map<IdDt, DaoMethodOutcome> idToPersistedOutcome = new HashMap<IdDt, DaoMethodOutcome>();
|
||||
|
||||
return null;
|
||||
Bundle response = new Bundle();
|
||||
OperationOutcome oo = new OperationOutcome();
|
||||
response.addEntry().setResource(oo);
|
||||
|
||||
for (int i = 0; i < theResources.getEntry().size(); i++) {
|
||||
Entry nextEntry = theResources.getEntry().get(i);
|
||||
IResource res = nextEntry.getResource();
|
||||
IdDt nextResourceId = null;
|
||||
if (res != null) {
|
||||
|
||||
nextResourceId = res.getId();
|
||||
if (nextResourceId.hasIdPart() && !nextResourceId.hasResourceType()) {
|
||||
nextResourceId = new IdDt(toResourceName(res.getClass()), nextResourceId.getIdPart());
|
||||
res.setId(nextResourceId);
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure that the bundle doesn't have any duplicates, since this causes all kinds of weirdness
|
||||
*/
|
||||
if (nextResourceId.hasResourceType() && nextResourceId.hasIdPart()) {
|
||||
IdDt nextId = nextResourceId.toUnqualifiedVersionless();
|
||||
if (!allIds.add(nextId)) {
|
||||
throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseFhirSystemDao.class, "transactionContainsMultipleWithDuplicateId", nextId));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
HTTPVerbEnum verb = nextEntry.getTransaction().getMethodElement().getValueAsEnum();
|
||||
if (verb == null) {
|
||||
throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseFhirSystemDao.class, "transactionEntryHasInvalidVerb", nextEntry.getTransaction().getMethod()));
|
||||
}
|
||||
|
||||
switch (verb) {
|
||||
case POST: {
|
||||
// CREATE
|
||||
@SuppressWarnings("rawtypes")
|
||||
IFhirResourceDao resourceDao = getDao(res.getClass());
|
||||
res.setId(null);
|
||||
DaoMethodOutcome outcome;
|
||||
Entry newEntry = response.addEntry();
|
||||
outcome = resourceDao.create(res, nextEntry.getTransaction().getIfNoneExist(), false);
|
||||
handleTransactionCreateOrUpdateOutcome(idSubstitutions, idToPersistedOutcome, nextResourceId, outcome, newEntry);
|
||||
break;
|
||||
}
|
||||
case DELETE: {
|
||||
// DELETE
|
||||
Entry newEntry = response.addEntry();
|
||||
String url = extractTransactionUrlOrThrowException(nextEntry, verb);
|
||||
UrlParts parts = parseUrl(verb.getCode(), url);
|
||||
if (parts.getResourceId() != null) {
|
||||
parts.getDao().delete(new IdDt(parts.getResourceType(), parts.getResourceId()));
|
||||
} else {
|
||||
parts.getDao().deleteByUrl(parts.getResourceType() + '?' + parts.getParams());
|
||||
}
|
||||
|
||||
newEntry.getTransactionResponse().setStatus(Integer.toString(Constants.STATUS_HTTP_204_NO_CONTENT));
|
||||
break;
|
||||
}
|
||||
case PUT: {
|
||||
// UPDATE
|
||||
@SuppressWarnings("rawtypes")
|
||||
IFhirResourceDao resourceDao = getDao(res.getClass());
|
||||
|
||||
DaoMethodOutcome outcome;
|
||||
Entry newEntry = response.addEntry();
|
||||
|
||||
String url = extractTransactionUrlOrThrowException(nextEntry, verb);
|
||||
|
||||
UrlParts parts = parseUrl(verb.getCode(), url);
|
||||
if (parts.getResourceId() != null) {
|
||||
res.setId(new IdDt(parts.getResourceType(), parts.getResourceId()));
|
||||
outcome = resourceDao.update(res, null, false);
|
||||
} else {
|
||||
res.setId(null);
|
||||
outcome = resourceDao.update(res, parts.getResourceType() + '?' + parts.getParams(), false);
|
||||
}
|
||||
|
||||
handleTransactionCreateOrUpdateOutcome(idSubstitutions, idToPersistedOutcome, nextResourceId, outcome, newEntry);
|
||||
break;
|
||||
}
|
||||
case GET: {
|
||||
// SEARCH/READ/VREAD
|
||||
String url = extractTransactionUrlOrThrowException(nextEntry, verb);
|
||||
UrlParts parts = parseUrl(verb.getCode(), url);
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
IFhirResourceDao resourceDao = parts.getDao();
|
||||
|
||||
if (parts.getResourceId() != null && parts.getParams() == null) {
|
||||
IResource found;
|
||||
if (parts.getVersionId() != null) {
|
||||
found = resourceDao.read(new IdDt(parts.getResourceType(), parts.getResourceId(), parts.getVersionId()));
|
||||
} else {
|
||||
found = resourceDao.read(new IdDt(parts.getResourceType(), parts.getResourceId()));
|
||||
}
|
||||
EntryTransactionResponse resp = response.addEntry().setResource(found).getTransactionResponse();
|
||||
resp.setLocation(found.getId().toUnqualified().getValue());
|
||||
resp.addEtag(found.getId().getVersionIdPart());
|
||||
} else if (parts.getParams() != null) {
|
||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(parts.getDao().getResourceType());
|
||||
SearchParameterMap params = translateMatchUrl(url, def);
|
||||
IBundleProvider bundle = parts.getDao().search(params);
|
||||
|
||||
Bundle searchBundle = new Bundle();
|
||||
searchBundle.setTotal(bundle.size());
|
||||
|
||||
int configuredMax = 100; // this should probably be configurable or something
|
||||
if (bundle.size() > configuredMax) {
|
||||
oo.addIssue().setSeverity(IssueSeverityEnum.WARNING).setDetails("Search nested within transaction found more than " + configuredMax + " matches, but paging is not supported in nested transactions");
|
||||
}
|
||||
List<IResource> resourcesToAdd = bundle.getResources(0, Math.min(bundle.size(), configuredMax));
|
||||
for (IResource next : resourcesToAdd) {
|
||||
searchBundle.addEntry().setResource(next);
|
||||
}
|
||||
|
||||
response.addEntry().setResource(searchBundle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
FhirTerser terser = getContext().newTerser();
|
||||
|
||||
// int creations = 0;
|
||||
// int updates = 0;
|
||||
//
|
||||
// Map<IdDt, IdDt> idConversions = new HashMap<IdDt, IdDt>();
|
||||
//
|
||||
// List<ResourceTable> persistedResources = new ArrayList<ResourceTable>();
|
||||
//
|
||||
// List<IResource> retVal = new ArrayList<IResource>();
|
||||
// OperationOutcome oo = new OperationOutcome();
|
||||
// retVal.add(oo);
|
||||
//
|
||||
// for (int resourceIdx = 0; resourceIdx < theResources.size(); resourceIdx++) {
|
||||
// IResource nextResource = theResources.get(resourceIdx);
|
||||
//
|
||||
// IdDt nextId = nextResource.getId();
|
||||
// if (nextId == null) {
|
||||
// nextId = new IdDt();
|
||||
// }
|
||||
//
|
||||
// String resourceName = toResourceName(nextResource);
|
||||
// BundleEntryTransactionOperationEnum nextResouceOperationIn =
|
||||
// ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(nextResource);
|
||||
// if (nextResouceOperationIn == null && hasValue(ResourceMetadataKeyEnum.DELETED_AT.get(nextResource))) {
|
||||
// nextResouceOperationIn = BundleEntryTransactionOperationEnum.DELETE;
|
||||
// }
|
||||
//
|
||||
// String matchUrl = ResourceMetadataKeyEnum.LINK_SEARCH.get(nextResource);
|
||||
// Set<Long> candidateMatches = null;
|
||||
// if (StringUtils.isNotBlank(matchUrl)) {
|
||||
// candidateMatches = processMatchUrl(matchUrl, nextResource.getClass());
|
||||
// }
|
||||
//
|
||||
// ResourceTable entity;
|
||||
// if (nextResouceOperationIn == BundleEntryTransactionOperationEnum.CREATE) {
|
||||
// entity = null;
|
||||
// } else if (nextResouceOperationIn == BundleEntryTransactionOperationEnum.UPDATE || nextResouceOperationIn ==
|
||||
// BundleEntryTransactionOperationEnum.DELETE) {
|
||||
// if (candidateMatches == null || candidateMatches.size() == 0) {
|
||||
// if (nextId == null || StringUtils.isBlank(nextId.getIdPart())) {
|
||||
// throw new InvalidRequestException(getContext().getLocalizer().getMessage(FhirSystemDaoDstu2.class,
|
||||
// "transactionOperationFailedNoId", nextResouceOperationIn.name()));
|
||||
// }
|
||||
// entity = tryToLoadEntity(nextId);
|
||||
// if (entity == null) {
|
||||
// if (nextResouceOperationIn == BundleEntryTransactionOperationEnum.UPDATE) {
|
||||
// ourLog.debug("Attempting to UPDATE resource with unknown ID '{}', will CREATE instead", nextId);
|
||||
// } else if (candidateMatches == null) {
|
||||
// throw new InvalidRequestException(getContext().getLocalizer().getMessage(FhirSystemDaoDstu2.class,
|
||||
// "transactionOperationFailedUnknownId", nextResouceOperationIn.name(), nextId));
|
||||
// } else {
|
||||
// ourLog.debug("Resource with match URL [{}] already exists, will be NOOP", matchUrl);
|
||||
// ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(nextResource,
|
||||
// BundleEntryTransactionOperationEnum.NOOP);
|
||||
// persistedResources.add(null);
|
||||
// retVal.add(nextResource);
|
||||
// continue;
|
||||
// }
|
||||
// }
|
||||
// } else if (candidateMatches.size() == 1) {
|
||||
// entity = loadFirstEntityFromCandidateMatches(candidateMatches);
|
||||
// } else {
|
||||
// throw new InvalidRequestException(getContext().getLocalizer().getMessage(FhirSystemDaoDstu2.class,
|
||||
// "transactionOperationWithMultipleMatchFailure", nextResouceOperationIn.name(), matchUrl,
|
||||
// candidateMatches.size()));
|
||||
// }
|
||||
// } else if (nextResouceOperationIn == BundleEntryTransactionOperationEnum.NOOP) {
|
||||
// throw new InvalidRequestException(getContext().getLocalizer().getMessage(FhirSystemDaoDstu2.class,
|
||||
// "incomingNoopInTransaction"));
|
||||
// } else if (nextId.isEmpty()) {
|
||||
// entity = null;
|
||||
// } else {
|
||||
// entity = tryToLoadEntity(nextId);
|
||||
// }
|
||||
//
|
||||
// BundleEntryTransactionOperationEnum nextResouceOperationOut;
|
||||
// if (entity == null) {
|
||||
// nextResouceOperationOut = BundleEntryTransactionOperationEnum.CREATE;
|
||||
// entity = toEntity(nextResource);
|
||||
// if (nextId.isEmpty() == false && nextId.getIdPart().startsWith("cid:")) {
|
||||
// ourLog.debug("Resource in transaction has ID[{}], will replace with server assigned ID", nextId.getIdPart());
|
||||
// } else if (nextResouceOperationIn == BundleEntryTransactionOperationEnum.CREATE) {
|
||||
// if (nextId.isEmpty() == false) {
|
||||
// ourLog.debug("Resource in transaction has ID[{}] but is marked for CREATE, will ignore ID",
|
||||
// nextId.getIdPart());
|
||||
// }
|
||||
// if (candidateMatches != null) {
|
||||
// if (candidateMatches.size() == 1) {
|
||||
// ourLog.debug("Resource with match URL [{}] already exists, will be NOOP", matchUrl);
|
||||
// BaseHasResource existingEntity = loadFirstEntityFromCandidateMatches(candidateMatches);
|
||||
// IResource existing = (IResource) toResource(existingEntity);
|
||||
// ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(existing, BundleEntryTransactionOperationEnum.NOOP);
|
||||
// persistedResources.add(null);
|
||||
// retVal.add(existing);
|
||||
// continue;
|
||||
// }
|
||||
// if (candidateMatches.size() > 1) {
|
||||
// throw new InvalidRequestException(getContext().getLocalizer().getMessage(FhirSystemDaoDstu2.class,
|
||||
// "transactionOperationWithMultipleMatchFailure", BundleEntryTransactionOperationEnum.CREATE.name(), matchUrl,
|
||||
// candidateMatches.size()));
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// createForcedIdIfNeeded(entity, nextId);
|
||||
// }
|
||||
// myEntityManager.persist(entity);
|
||||
// if (entity.getForcedId() != null) {
|
||||
// myEntityManager.persist(entity.getForcedId());
|
||||
// }
|
||||
// creations++;
|
||||
// ourLog.info("Resource Type[{}] with ID[{}] does not exist, creating it", resourceName, nextId);
|
||||
// } else {
|
||||
// nextResouceOperationOut = nextResouceOperationIn;
|
||||
// if (nextResouceOperationOut == null) {
|
||||
// nextResouceOperationOut = BundleEntryTransactionOperationEnum.UPDATE;
|
||||
// }
|
||||
// updates++;
|
||||
// ourLog.info("Resource Type[{}] with ID[{}] exists, updating it", resourceName, nextId);
|
||||
// }
|
||||
//
|
||||
// persistedResources.add(entity);
|
||||
// retVal.add(nextResource);
|
||||
// ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(nextResource, nextResouceOperationOut);
|
||||
// }
|
||||
//
|
||||
// ourLog.info("Flushing transaction to database");
|
||||
// myEntityManager.flush();
|
||||
//
|
||||
// for (int i = 0; i < persistedResources.size(); i++) {
|
||||
// ResourceTable entity = persistedResources.get(i);
|
||||
//
|
||||
// String resourceName = toResourceName(theResources.get(i));
|
||||
// IdDt nextId = theResources.get(i).getId();
|
||||
//
|
||||
// IdDt newId;
|
||||
//
|
||||
// if (entity == null) {
|
||||
// newId = retVal.get(i + 1).getId().toUnqualifiedVersionless();
|
||||
// } else {
|
||||
// newId = entity.getIdDt().toUnqualifiedVersionless();
|
||||
// }
|
||||
//
|
||||
// if (nextId == null || nextId.isEmpty()) {
|
||||
// ourLog.info("Transaction resource (with no preexisting ID) has been assigned new ID[{}]", nextId, newId);
|
||||
// } else {
|
||||
// if (nextId.toUnqualifiedVersionless().equals(newId)) {
|
||||
// ourLog.info("Transaction resource ID[{}] is being updated", newId);
|
||||
// } else {
|
||||
// if (!nextId.getIdPart().startsWith("#")) {
|
||||
// nextId = new IdDt(resourceName + '/' + nextId.getIdPart());
|
||||
// ourLog.info("Transaction resource ID[{}] has been assigned new ID[{}]", nextId, newId);
|
||||
// idConversions.put(nextId, newId);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
for (DaoMethodOutcome nextOutcome : idToPersistedOutcome.values()) {
|
||||
IResource nextResource = nextOutcome.getResource();
|
||||
if (nextResource == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
List<BaseResourceReferenceDt> allRefs = terser.getAllPopulatedChildElementsOfType(nextResource, BaseResourceReferenceDt.class);
|
||||
for (BaseResourceReferenceDt nextRef : allRefs) {
|
||||
IdDt nextId = nextRef.getReference();
|
||||
if (idSubstitutions.containsKey(nextId)) {
|
||||
IdDt newId = idSubstitutions.get(nextId);
|
||||
ourLog.info(" * Replacing resource ref {} with {}", nextId, newId);
|
||||
nextRef.setReference(newId);
|
||||
} else {
|
||||
ourLog.debug(" * Reference [{}] does not exist in bundle", nextId);
|
||||
}
|
||||
}
|
||||
|
||||
InstantDt deletedInstantOrNull = ResourceMetadataKeyEnum.DELETED_AT.get(nextResource);
|
||||
Date deletedTimestampOrNull = deletedInstantOrNull != null ? deletedInstantOrNull.getValue() : null;
|
||||
updateEntity(nextResource, nextOutcome.getEntity(), false, deletedTimestampOrNull, true, false);
|
||||
}
|
||||
//
|
||||
// ourLog.info("Re-flushing updated resource references and extracting search criteria");
|
||||
//
|
||||
// for (int i = 0; i < theResources.size(); i++) {
|
||||
// IResource resource = theResources.get(i);
|
||||
// ResourceTable table = persistedResources.get(i);
|
||||
// if (table == null) {
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
// InstantDt deletedInstantOrNull = ResourceMetadataKeyEnum.DELETED_AT.get(resource);
|
||||
// Date deletedTimestampOrNull = deletedInstantOrNull != null ? deletedInstantOrNull.getValue() : null;
|
||||
// if (deletedInstantOrNull == null && ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(resource) ==
|
||||
// BundleEntryTransactionOperationEnum.DELETE) {
|
||||
// deletedTimestampOrNull = new Date();
|
||||
// ResourceMetadataKeyEnum.DELETED_AT.put(resource, new InstantDt(deletedTimestampOrNull));
|
||||
// }
|
||||
//
|
||||
// updateEntity(resource, table, table.getId() != null, deletedTimestampOrNull);
|
||||
// }
|
||||
|
||||
long delay = System.currentTimeMillis() - start;
|
||||
ourLog.info("Transaction completed in {}ms", new Object[] { delay });
|
||||
|
||||
oo.addIssue().setSeverity(IssueSeverityEnum.INFORMATION).setDetails("Transaction completed in " + delay + "ms");
|
||||
|
||||
notifyWriteCompleted();
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
private void handleTransactionCreateOrUpdateOutcome(Map<IdDt, IdDt> idSubstitutions, Map<IdDt, DaoMethodOutcome> idToPersistedOutcome, IdDt nextResourceId, DaoMethodOutcome outcome, Entry newEntry) {
|
||||
IdDt newId = outcome.getId().toUnqualifiedVersionless();
|
||||
if (newId.equals(nextResourceId) == false) {
|
||||
idSubstitutions.put(nextResourceId, newId);
|
||||
}
|
||||
idToPersistedOutcome.put(newId, outcome);
|
||||
if (outcome.getCreated().booleanValue()) {
|
||||
newEntry.getTransactionResponse().setStatus(Long.toString(Constants.STATUS_HTTP_201_CREATED));
|
||||
} else {
|
||||
newEntry.getTransactionResponse().setStatus(Long.toString(Constants.STATUS_HTTP_200_OK));
|
||||
}
|
||||
newEntry.getTransactionResponse().setLocation(outcome.getId().toUnqualified().getValue());
|
||||
newEntry.getTransactionResponse().addEtag().setValue(outcome.getId().getVersionIdPart());
|
||||
}
|
||||
|
||||
private String extractTransactionUrlOrThrowException(Entry nextEntry, HTTPVerbEnum verb) {
|
||||
String url = nextEntry.getTransaction().getUrl();
|
||||
if (isBlank(url)) {
|
||||
throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseFhirSystemDao.class, "transactionMissingUrl", verb.name()));
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
private static class UrlParts {
|
||||
private IFhirResourceDao<? extends IResource> myDao;
|
||||
private String myParams;
|
||||
private String myResourceId;
|
||||
private String myResourceType;
|
||||
private String myVersionId;
|
||||
|
||||
public IFhirResourceDao<? extends IResource> getDao() {
|
||||
return myDao;
|
||||
}
|
||||
|
||||
public void setVersionId(String theVersionId) {
|
||||
myVersionId = theVersionId;
|
||||
}
|
||||
|
||||
public String getVersionId() {
|
||||
return myVersionId;
|
||||
}
|
||||
|
||||
public String getParams() {
|
||||
return myParams;
|
||||
}
|
||||
|
||||
public String getResourceId() {
|
||||
return myResourceId;
|
||||
}
|
||||
|
||||
public String getResourceType() {
|
||||
return myResourceType;
|
||||
}
|
||||
|
||||
public void setDao(IFhirResourceDao<? extends IResource> theDao) {
|
||||
myDao = theDao;
|
||||
}
|
||||
|
||||
public void setParams(String theParams) {
|
||||
myParams = theParams;
|
||||
}
|
||||
|
||||
public void setResourceId(String theResourceId) {
|
||||
myResourceId = theResourceId;
|
||||
}
|
||||
|
||||
public void setResourceType(String theResourceType) {
|
||||
myResourceType = theResourceType;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ import ca.uhn.fhir.model.api.IQueryParameterType;
|
|||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
|
||||
|
@ -37,9 +36,20 @@ public interface IFhirResourceDao<T extends IResource> extends IDao {
|
|||
|
||||
void addTag(IdDt theId, String theScheme, String theTerm, String theLabel);
|
||||
|
||||
MethodOutcome create(T theResource);
|
||||
DaoMethodOutcome create(T theResource);
|
||||
|
||||
MethodOutcome delete(IdDt theResource);
|
||||
DaoMethodOutcome create(T theResource, String theIfNoneExist);
|
||||
|
||||
/**
|
||||
* @param thePerformIndexing
|
||||
* Use with caution! If you set this to false, you need to manually perform indexing or your resources
|
||||
* won't be indexed and searches won't work.
|
||||
*/
|
||||
DaoMethodOutcome create(T theResource, String theIfNoneExist, boolean thePerformIndexing);
|
||||
|
||||
DaoMethodOutcome delete(IdDt theResource);
|
||||
|
||||
DaoMethodOutcome deleteByUrl(String theString);
|
||||
|
||||
TagList getAllResourceTags();
|
||||
|
||||
|
@ -49,7 +59,7 @@ public interface IFhirResourceDao<T extends IResource> extends IDao {
|
|||
|
||||
IBundleProvider history(Date theSince);
|
||||
|
||||
IBundleProvider history(IdDt theId,Date theSince);
|
||||
IBundleProvider history(IdDt theId, Date theSince);
|
||||
|
||||
IBundleProvider history(Long theId, Date theSince);
|
||||
|
||||
|
@ -57,12 +67,20 @@ public interface IFhirResourceDao<T extends IResource> extends IDao {
|
|||
*
|
||||
* @param theId
|
||||
* @return
|
||||
* @throws ResourceNotFoundException If the ID is not known to the server
|
||||
* @throws ResourceNotFoundException
|
||||
* If the ID is not known to the server
|
||||
*/
|
||||
T read(IdDt theId);
|
||||
|
||||
BaseHasResource readEntity(IdDt theId);
|
||||
|
||||
/**
|
||||
* @param theCheckForForcedId
|
||||
* If true, this method should fail if the requested ID contains a numeric PID which exists, but is
|
||||
* obscured by a "forced ID" so should not exist as far as the outside world is concerned.
|
||||
*/
|
||||
BaseHasResource readEntity(IdDt theId, boolean theCheckForForcedId);
|
||||
|
||||
void removeTag(IdDt theId, String theScheme, String theTerm);
|
||||
|
||||
IBundleProvider search(Map<String, IQueryParameterType> theParams);
|
||||
|
@ -75,15 +93,17 @@ public interface IFhirResourceDao<T extends IResource> extends IDao {
|
|||
|
||||
Set<Long> searchForIds(String theParameterName, IQueryParameterType theValue);
|
||||
|
||||
MethodOutcome update(T theResource, IdDt theId);
|
||||
|
||||
Set<Long> searchForIdsWithAndOr(SearchParameterMap theParams);
|
||||
|
||||
DaoMethodOutcome update(T theResource);
|
||||
|
||||
DaoMethodOutcome update(T theResource, String theMatchUrl);
|
||||
|
||||
/**
|
||||
* @param theCheckForForcedId If true, this method should fail if the requested ID contains
|
||||
* a numeric PID which exists, but is obscured by a "forced ID" so should not exist as
|
||||
* far as the outside world is concerned.
|
||||
* @param thePerformIndexing
|
||||
* Use with caution! If you set this to false, you need to manually perform indexing or your resources
|
||||
* won't be indexed and searches won't work.
|
||||
*/
|
||||
BaseHasResource readEntity(IdDt theId, boolean theCheckForForcedId);
|
||||
DaoMethodOutcome update(T theResource, String theMatchUrl, boolean thePerformIndexing);
|
||||
|
||||
}
|
||||
|
|
|
@ -32,9 +32,15 @@ import javax.persistence.OneToOne;
|
|||
import javax.persistence.Table;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
|
||||
//@formatter:off
|
||||
@Entity()
|
||||
@Table(name = "HFJ_FORCED_ID", uniqueConstraints = { @UniqueConstraint(name = "IDX_FORCEDID", columnNames = { "FORCED_ID" }) })
|
||||
@NamedQueries(@NamedQuery(name = "Q_GET_FORCED_ID", query = "SELECT f FROM ForcedId f WHERE myForcedId = :ID"))
|
||||
@Table(name = "HFJ_FORCED_ID", uniqueConstraints = {
|
||||
@UniqueConstraint(name = "IDX_FORCEDID", columnNames = { "FORCED_ID" })
|
||||
})
|
||||
@NamedQueries(value= {
|
||||
@NamedQuery(name = "Q_GET_FORCED_ID", query = "SELECT f FROM ForcedId f WHERE myForcedId = :ID")
|
||||
})
|
||||
//@formatter:on
|
||||
public class ForcedId {
|
||||
|
||||
public static final int MAX_FORCED_ID_LENGTH = 100;
|
||||
|
|
|
@ -27,6 +27,7 @@ import ca.uhn.fhir.context.FhirContext;
|
|||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.dstu.resource.Conformance;
|
||||
import ca.uhn.fhir.model.dstu.resource.Conformance.Rest;
|
||||
import ca.uhn.fhir.model.dstu.resource.Conformance.RestResource;
|
||||
|
@ -44,11 +45,11 @@ import javax.servlet.http.HttpServletRequest;
|
|||
public class JpaConformanceProviderDstu1 extends ServerConformanceProvider {
|
||||
|
||||
private String myImplementationDescription;
|
||||
private IFhirSystemDao mySystemDao;
|
||||
private IFhirSystemDao<List<IResource>> mySystemDao;
|
||||
private volatile Conformance myCachedValue;
|
||||
private RestfulServer myRestfulServer;
|
||||
|
||||
public JpaConformanceProviderDstu1(RestfulServer theRestfulServer, IFhirSystemDao theSystemDao) {
|
||||
public JpaConformanceProviderDstu1(RestfulServer theRestfulServer, IFhirSystemDao<List<IResource>> theSystemDao) {
|
||||
super(theRestfulServer);
|
||||
myRestfulServer = theRestfulServer;
|
||||
mySystemDao = theSystemDao;
|
||||
|
|
|
@ -29,6 +29,7 @@ import ca.uhn.fhir.context.FhirContext;
|
|||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Conformance;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Conformance.Rest;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Conformance.RestResource;
|
||||
|
@ -44,11 +45,11 @@ import ca.uhn.fhir.util.ExtensionConstants;
|
|||
public class JpaConformanceProviderDstu2 extends ServerConformanceProvider {
|
||||
|
||||
private String myImplementationDescription;
|
||||
private IFhirSystemDao mySystemDao;
|
||||
private IFhirSystemDao<Bundle> mySystemDao;
|
||||
private volatile Conformance myCachedValue;
|
||||
private RestfulServer myRestfulServer;
|
||||
|
||||
public JpaConformanceProviderDstu2(RestfulServer theRestfulServer, IFhirSystemDao theSystemDao) {
|
||||
public JpaConformanceProviderDstu2(RestfulServer theRestfulServer, IFhirSystemDao<Bundle> theSystemDao) {
|
||||
super(theRestfulServer);
|
||||
myRestfulServer = theRestfulServer;
|
||||
mySystemDao = theSystemDao;
|
||||
|
|
|
@ -162,13 +162,12 @@ public class JpaResourceProvider<T extends IResource> extends BaseJpaProvider im
|
|||
public MethodOutcome update(HttpServletRequest theRequest, @ResourceParam T theResource, @IdParam IdDt theId) {
|
||||
startRequest(theRequest);
|
||||
try {
|
||||
return myDao.update(theResource, theId);
|
||||
theResource.setId(theId);
|
||||
return myDao.update(theResource);
|
||||
} catch (ResourceNotFoundException e) {
|
||||
ourLog.info("Can't update resource with ID[" + theId.getValue() + "] because it doesn't exist, going to create it instead");
|
||||
theResource.setId(theId);
|
||||
MethodOutcome retVal = myDao.create(theResource);
|
||||
retVal.setCreated(true);
|
||||
return retVal;
|
||||
return myDao.create(theResource);
|
||||
} finally {
|
||||
endRequest(theRequest);
|
||||
}
|
||||
|
|
|
@ -1,17 +1,7 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.endsWith;
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
|
@ -40,6 +30,7 @@ import ca.uhn.fhir.model.dstu2.composite.IdentifierDt;
|
|||
import ca.uhn.fhir.model.dstu2.composite.PeriodDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.QuantityDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Device;
|
||||
import ca.uhn.fhir.model.dstu2.resource.DiagnosticReport;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Encounter;
|
||||
|
@ -47,7 +38,9 @@ import ca.uhn.fhir.model.dstu2.resource.Location;
|
|||
import ca.uhn.fhir.model.dstu2.resource.Observation;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Organization;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.AdministrativeGenderEnum;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.QuantityComparatorEnum;
|
||||
import ca.uhn.fhir.model.primitive.DateDt;
|
||||
import ca.uhn.fhir.model.primitive.DateTimeDt;
|
||||
|
@ -65,8 +58,10 @@ import ca.uhn.fhir.rest.param.ReferenceParam;
|
|||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import ca.uhn.fhir.rest.param.TokenOrListParam;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||
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.ResourceNotFoundException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||
|
@ -84,6 +79,150 @@ public class FhirResourceDaoTest {
|
|||
private static IFhirResourceDao<Organization> ourOrganizationDao;
|
||||
private static IFhirResourceDao<Patient> ourPatientDao;
|
||||
|
||||
@Test
|
||||
public void testCreateDuplicateIdFails() {
|
||||
String methodName = "testCreateDuplocateIdFailsText";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.setId("Patient/" + methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
try {
|
||||
ourPatientDao.create(p);
|
||||
fail();
|
||||
} catch (UnprocessableEntityException e) {
|
||||
assertThat(e.getMessage(), containsString("Can not create entity with ID[" + methodName + "], a resource with this ID already exists"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateByUrl() {
|
||||
String methodName = "testUpdateByUrl";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
|
||||
ourPatientDao.update(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
p = ourPatientDao.read(id.toVersionless());
|
||||
assertThat(p.getId().toVersionless().toString(), not(containsString("test")));
|
||||
assertEquals(id.toVersionless(), p.getId().toVersionless());
|
||||
assertNotEquals(id, p.getId());
|
||||
assertThat(p.getId().toString(), endsWith("/_history/2"));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCreateNumericIdFails() {
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue("testCreateNumericIdFails");
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/123");
|
||||
try {
|
||||
ourPatientDao.create(p);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertThat(e.getMessage(), containsString("Can not create entity with ID[123], this server does not allow clients to assign numeric IDs"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testDeleteWithMatchUrl() {
|
||||
String methodName = "testDeleteWithMatchUrl";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
Bundle request = new Bundle();
|
||||
request.addEntry().setResource(p).getTransaction().setMethod(HTTPVerbEnum.DELETE).setUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
ourPatientDao.deleteByUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
try {
|
||||
ourPatientDao.read(id.toVersionless());
|
||||
fail();
|
||||
} catch (ResourceGoneException e) {
|
||||
// ok
|
||||
}
|
||||
|
||||
try {
|
||||
ourPatientDao.read(new IdDt("Patient/" + methodName));
|
||||
fail();
|
||||
} catch (ResourceNotFoundException e) {
|
||||
// ok
|
||||
}
|
||||
|
||||
IBundleProvider history = ourPatientDao.history(id, null);
|
||||
assertEquals(2, history.size());
|
||||
|
||||
assertNotNull(ResourceMetadataKeyEnum.DELETED_AT.get(history.getResources(0, 0).get(0)));
|
||||
assertNotNull(ResourceMetadataKeyEnum.DELETED_AT.get(history.getResources(0, 0).get(0)).getValue());
|
||||
assertNull(ResourceMetadataKeyEnum.DELETED_AT.get(history.getResources(1,1).get(0)));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCreateWithIfNoneExist() {
|
||||
String methodName = "testCreateWithIfNoneExist";
|
||||
MethodOutcome results;
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.setId("Patient/" + methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
results = ourPatientDao.create(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
assertEquals(id.getIdPart(), results.getId().getIdPart());
|
||||
assertFalse(results.getCreated().booleanValue());
|
||||
|
||||
// Now create a second one
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName + "DOESNTEXIST");
|
||||
results = ourPatientDao.create(p, "Patient?identifier=urn%3Asystem%7C" + methodName + "DOESNTEXIST");
|
||||
assertNotEquals(id.getIdPart(), results.getId().getIdPart());
|
||||
assertTrue(results.getCreated().booleanValue());
|
||||
|
||||
// Now try to create one with the original match URL and it should fail
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
try {
|
||||
ourPatientDao.create(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
fail();
|
||||
} catch (PreconditionFailedException e) {
|
||||
assertThat(e.getMessage(), containsString("Failed to CREATE"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChoiceParamConcept() {
|
||||
Observation o1 = new Observation();
|
||||
|
@ -216,7 +355,7 @@ public class FhirResourceDaoTest {
|
|||
public void testDatePeriodParamStartAndEnd() {
|
||||
{
|
||||
Encounter enc = new Encounter();
|
||||
enc.addIdentifier().setSystem("testDatePeriodParam").setValue( "03");
|
||||
enc.addIdentifier().setSystem("testDatePeriodParam").setValue("03");
|
||||
enc.getPeriod().getStartElement().setValueAsString("2001-01-02");
|
||||
enc.getPeriod().getEndElement().setValueAsString("2001-01-03");
|
||||
ourEncounterDao.create(enc);
|
||||
|
@ -329,7 +468,7 @@ public class FhirResourceDaoTest {
|
|||
{
|
||||
Patient patient = ourPatientDao.read(id2);
|
||||
patient.addIdentifier().setSystem("ZZZZZZZ").setValue("ZZZZZZZZZ");
|
||||
id2b = ourPatientDao.update(patient, id2).getId();
|
||||
id2b = ourPatientDao.update(patient).getId();
|
||||
}
|
||||
ourLog.info("ID1:{} ID2:{} ID2b:{}", new Object[] { id1, id2, id2b });
|
||||
|
||||
|
@ -373,7 +512,7 @@ public class FhirResourceDaoTest {
|
|||
@Test
|
||||
public void testIdParam() {
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "001");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("001");
|
||||
patient.addName().addFamily("Tester").addGiven("Joe");
|
||||
|
||||
MethodOutcome outcome = ourPatientDao.create(patient);
|
||||
|
@ -484,11 +623,11 @@ public class FhirResourceDaoTest {
|
|||
@Test
|
||||
public void testPersistResourceLink() {
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "testPersistResourceLink01");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("testPersistResourceLink01");
|
||||
IdDt patientId01 = ourPatientDao.create(patient).getId();
|
||||
|
||||
Patient patient02 = new Patient();
|
||||
patient02.addIdentifier().setSystem("urn:system").setValue( "testPersistResourceLink02");
|
||||
patient02.addIdentifier().setSystem("urn:system").setValue("testPersistResourceLink02");
|
||||
IdDt patientId02 = ourPatientDao.create(patient02).getId();
|
||||
|
||||
Observation obs01 = new Observation();
|
||||
|
@ -524,7 +663,7 @@ public class FhirResourceDaoTest {
|
|||
@Test
|
||||
public void testPersistSearchParamDate() {
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "001");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("001");
|
||||
patient.setBirthDate(new DateDt("2001-01-01"));
|
||||
|
||||
ourPatientDao.create(patient);
|
||||
|
@ -576,7 +715,7 @@ public class FhirResourceDaoTest {
|
|||
@Test
|
||||
public void testPersistSearchParams() {
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "001testPersistSearchParams");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("001testPersistSearchParams");
|
||||
patient.getGenderElement().setValueAsEnum(AdministrativeGenderEnum.MALE);
|
||||
patient.addName().addFamily("Tester").addGiven("JoetestPersistSearchParams");
|
||||
|
||||
|
@ -641,20 +780,20 @@ public class FhirResourceDaoTest {
|
|||
assertTrue(patients.size() >= 2);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testHistoryByForcedId() {
|
||||
IdDt idv1;
|
||||
IdDt idv2;
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "testHistoryByForcedId");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("testHistoryByForcedId");
|
||||
patient.addName().addFamily("Tester").addGiven("testHistoryByForcedId");
|
||||
patient.setId("Patient/testHistoryByForcedId");
|
||||
idv1 = ourPatientDao.create(patient).getId();
|
||||
|
||||
patient.addName().addFamily("Tester").addGiven("testHistoryByForcedIdName2");
|
||||
idv2 = ourPatientDao.update(patient, idv1.toUnqualifiedVersionless()).getId();
|
||||
patient.setId(patient.getId().toUnqualifiedVersionless());
|
||||
idv2 = ourPatientDao.update(patient).getId();
|
||||
}
|
||||
|
||||
List<Patient> patients = toList(ourPatientDao.history(idv1.toVersionless(), null));
|
||||
|
@ -676,7 +815,7 @@ public class FhirResourceDaoTest {
|
|||
IdDt id2;
|
||||
{
|
||||
Organization patient = new Organization();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "001");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("001");
|
||||
id2 = ourOrganizationDao.create(patient).getId();
|
||||
}
|
||||
|
||||
|
@ -769,14 +908,14 @@ public class FhirResourceDaoTest {
|
|||
IdDt id1;
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "001");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("001");
|
||||
patient.addName().addFamily("testSearchNameParam01Fam").addGiven("testSearchNameParam01Giv");
|
||||
ResourceMetadataKeyEnum.TITLE.put(patient, "P1TITLE");
|
||||
id1 = ourPatientDao.create(patient).getId();
|
||||
}
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "002");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("002");
|
||||
patient.addName().addFamily("testSearchNameParam02Fam").addGiven("testSearchNameParam02Giv");
|
||||
ourPatientDao.create(patient);
|
||||
}
|
||||
|
@ -816,12 +955,12 @@ public class FhirResourceDaoTest {
|
|||
@Test
|
||||
public void testSearchNumberParam() {
|
||||
Encounter e1 = new Encounter();
|
||||
e1.addIdentifier().setSystem("foo").setValue( "testSearchNumberParam01");
|
||||
e1.addIdentifier().setSystem("foo").setValue("testSearchNumberParam01");
|
||||
e1.getLength().setSystem(BaseFhirDao.UCUM_NS).setCode("min").setValue(4.0 * 24 * 60);
|
||||
IdDt id1 = ourEncounterDao.create(e1).getId();
|
||||
|
||||
Encounter e2 = new Encounter();
|
||||
e2.addIdentifier().setSystem("foo").setValue( "testSearchNumberParam02");
|
||||
e2.addIdentifier().setSystem("foo").setValue("testSearchNumberParam02");
|
||||
e2.getLength().setSystem(BaseFhirDao.UCUM_NS).setCode("year").setValue(2.0);
|
||||
IdDt id2 = ourEncounterDao.create(e2).getId();
|
||||
{
|
||||
|
@ -843,13 +982,13 @@ public class FhirResourceDaoTest {
|
|||
@Test
|
||||
public void testSearchResourceLinkWithChain() {
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "testSearchResourceLinkWithChainXX");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "testSearchResourceLinkWithChain01");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("testSearchResourceLinkWithChainXX");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("testSearchResourceLinkWithChain01");
|
||||
IdDt patientId01 = ourPatientDao.create(patient).getId();
|
||||
|
||||
Patient patient02 = new Patient();
|
||||
patient02.addIdentifier().setSystem("urn:system").setValue( "testSearchResourceLinkWithChainXX");
|
||||
patient02.addIdentifier().setSystem("urn:system").setValue( "testSearchResourceLinkWithChain02");
|
||||
patient02.addIdentifier().setSystem("urn:system").setValue("testSearchResourceLinkWithChainXX");
|
||||
patient02.addIdentifier().setSystem("urn:system").setValue("testSearchResourceLinkWithChain02");
|
||||
IdDt patientId02 = ourPatientDao.create(patient02).getId();
|
||||
|
||||
Observation obs01 = new Observation();
|
||||
|
@ -891,14 +1030,14 @@ public class FhirResourceDaoTest {
|
|||
public void testSearchResourceLinkWithTextLogicalId() {
|
||||
Patient patient = new Patient();
|
||||
patient.setId("testSearchResourceLinkWithTextLogicalId01");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "testSearchResourceLinkWithTextLogicalIdXX");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "testSearchResourceLinkWithTextLogicalId01");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("testSearchResourceLinkWithTextLogicalIdXX");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("testSearchResourceLinkWithTextLogicalId01");
|
||||
IdDt patientId01 = ourPatientDao.create(patient).getId();
|
||||
|
||||
Patient patient02 = new Patient();
|
||||
patient02.setId("testSearchResourceLinkWithTextLogicalId02");
|
||||
patient02.addIdentifier().setSystem("urn:system").setValue( "testSearchResourceLinkWithTextLogicalIdXX");
|
||||
patient02.addIdentifier().setSystem("urn:system").setValue( "testSearchResourceLinkWithTextLogicalId02");
|
||||
patient02.addIdentifier().setSystem("urn:system").setValue("testSearchResourceLinkWithTextLogicalIdXX");
|
||||
patient02.addIdentifier().setSystem("urn:system").setValue("testSearchResourceLinkWithTextLogicalId02");
|
||||
IdDt patientId02 = ourPatientDao.create(patient02).getId();
|
||||
|
||||
Observation obs01 = new Observation();
|
||||
|
@ -981,13 +1120,13 @@ public class FhirResourceDaoTest {
|
|||
public void testSearchStringParam() {
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "001");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("001");
|
||||
patient.addName().addFamily("Tester_testSearchStringParam").addGiven("Joe");
|
||||
ourPatientDao.create(patient);
|
||||
}
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "002");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("002");
|
||||
patient.addName().addFamily("Tester_testSearchStringParam").addGiven("John");
|
||||
ourPatientDao.create(patient);
|
||||
}
|
||||
|
@ -1009,7 +1148,7 @@ public class FhirResourceDaoTest {
|
|||
{
|
||||
Patient patient = new Patient();
|
||||
patient.getLanguage().setValue("en_CA");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "001");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("001");
|
||||
patient.addName().addFamily("testSearchLanguageParam").addGiven("Joe");
|
||||
id1 = ourPatientDao.create(patient).getId();
|
||||
}
|
||||
|
@ -1017,7 +1156,7 @@ public class FhirResourceDaoTest {
|
|||
{
|
||||
Patient patient = new Patient();
|
||||
patient.getLanguage().setValue("en_US");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "002");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("002");
|
||||
patient.addName().addFamily("testSearchLanguageParam").addGiven("John");
|
||||
id2 = ourPatientDao.create(patient).getId();
|
||||
}
|
||||
|
@ -1048,13 +1187,13 @@ public class FhirResourceDaoTest {
|
|||
public void testSearchStringParamWithNonNormalized() {
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "001");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("001");
|
||||
patient.addName().addGiven("testSearchStringParamWithNonNormalized_h\u00F6ra");
|
||||
ourPatientDao.create(patient);
|
||||
}
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "002");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("002");
|
||||
patient.addName().addGiven("testSearchStringParamWithNonNormalized_HORA");
|
||||
ourPatientDao.create(patient);
|
||||
}
|
||||
|
@ -1081,7 +1220,7 @@ public class FhirResourceDaoTest {
|
|||
ourPatientDao.create(patient);
|
||||
|
||||
patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "testSearchTokenParam002");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("testSearchTokenParam002");
|
||||
patient.addName().addFamily("Tester").addGiven("testSearchTokenParam2");
|
||||
ourPatientDao.create(patient);
|
||||
|
||||
|
@ -1147,14 +1286,14 @@ public class FhirResourceDaoTest {
|
|||
IdDt orgId = ourOrganizationDao.create(org).getId();
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "001");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("001");
|
||||
patient.addName().addFamily("Tester_testSearchWithIncludes_P1").addGiven("Joe");
|
||||
patient.getManagingOrganization().setReference(orgId);
|
||||
ourPatientDao.create(patient);
|
||||
}
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "002");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("002");
|
||||
patient.addName().addFamily("Tester_testSearchWithIncludes_P2").addGiven("John");
|
||||
ourPatientDao.create(patient);
|
||||
}
|
||||
|
@ -1221,7 +1360,7 @@ public class FhirResourceDaoTest {
|
|||
public void testStoreUtf8Characters() throws Exception {
|
||||
Organization org = new Organization();
|
||||
org.setName("測試醫院");
|
||||
org.addIdentifier().setSystem("urn:system").setValue( "testStoreUtf8Characters_01");
|
||||
org.addIdentifier().setSystem("urn:system").setValue("testStoreUtf8Characters_01");
|
||||
IdDt orgId = ourOrganizationDao.create(org).getId();
|
||||
|
||||
Organization returned = ourOrganizationDao.read(orgId);
|
||||
|
@ -1244,14 +1383,14 @@ public class FhirResourceDaoTest {
|
|||
assertThat(orgId.getValue(), endsWith("Organization/testSearchWithIncludesThatHaveTextId_id1/_history/1"));
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "001");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("001");
|
||||
patient.addName().addFamily("Tester_testSearchWithIncludesThatHaveTextId_P1").addGiven("Joe");
|
||||
patient.getManagingOrganization().setReference(orgId);
|
||||
ourPatientDao.create(patient);
|
||||
}
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "002");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("002");
|
||||
patient.addName().addFamily("Tester_testSearchWithIncludesThatHaveTextId_P2").addGiven("John");
|
||||
ourPatientDao.create(patient);
|
||||
}
|
||||
|
@ -1290,23 +1429,23 @@ public class FhirResourceDaoTest {
|
|||
@Test
|
||||
public void testSort() {
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue( "testSort001");
|
||||
p.addIdentifier().setSystem("urn:system").setValue("testSort001");
|
||||
p.addName().addFamily("testSortF1").addGiven("testSortG1");
|
||||
IdDt id1 = ourPatientDao.create(p).getId().toUnqualifiedVersionless();
|
||||
|
||||
// Create out of order
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue( "testSort001");
|
||||
p.addIdentifier().setSystem("urn:system").setValue("testSort001");
|
||||
p.addName().addFamily("testSortF3").addGiven("testSortG3");
|
||||
IdDt id3 = ourPatientDao.create(p).getId().toUnqualifiedVersionless();
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue( "testSort001");
|
||||
p.addIdentifier().setSystem("urn:system").setValue("testSort001");
|
||||
p.addName().addFamily("testSortF2").addGiven("testSortG2");
|
||||
IdDt id2 = ourPatientDao.create(p).getId().toUnqualifiedVersionless();
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue( "testSort001");
|
||||
p.addIdentifier().setSystem("urn:system").setValue("testSort001");
|
||||
IdDt id4 = ourPatientDao.create(p).getId().toUnqualifiedVersionless();
|
||||
|
||||
SearchParameterMap pm = new SearchParameterMap();
|
||||
|
@ -1367,7 +1506,7 @@ public class FhirResourceDaoTest {
|
|||
@Test
|
||||
public void testTagsWithCreateAndReadAndSearch() {
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "testTagsWithCreateAndReadAndSearch");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("testTagsWithCreateAndReadAndSearch");
|
||||
patient.addName().addFamily("Tester").addGiven("Joe");
|
||||
TagList tagList = new TagList();
|
||||
tagList.addTag(null, "Dog", "Puppies");
|
||||
|
@ -1458,7 +1597,7 @@ public class FhirResourceDaoTest {
|
|||
@Test
|
||||
public void testUpdateAndGetHistoryResource() throws InterruptedException {
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "001");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("001");
|
||||
patient.addName().addFamily("Tester").addGiven("Joe");
|
||||
|
||||
MethodOutcome outcome = ourPatientDao.create(patient);
|
||||
|
@ -1477,7 +1616,7 @@ public class FhirResourceDaoTest {
|
|||
Thread.sleep(1000);
|
||||
|
||||
retrieved.getIdentifierFirstRep().setValue("002");
|
||||
MethodOutcome outcome2 = ourPatientDao.update(retrieved, outcome.getId());
|
||||
MethodOutcome outcome2 = ourPatientDao.update(retrieved);
|
||||
assertEquals(outcome.getId().getIdPart(), outcome2.getId().getIdPart());
|
||||
assertNotEquals(outcome.getId().getVersionIdPart(), outcome2.getId().getVersionIdPart());
|
||||
|
||||
|
@ -1521,12 +1660,12 @@ public class FhirResourceDaoTest {
|
|||
@Test
|
||||
public void testUpdateMaintainsSearchParams() throws InterruptedException {
|
||||
Patient p1 = new Patient();
|
||||
p1.addIdentifier().setSystem("urn:system").setValue( "testUpdateMaintainsSearchParamsAAA");
|
||||
p1.addIdentifier().setSystem("urn:system").setValue("testUpdateMaintainsSearchParamsAAA");
|
||||
p1.addName().addFamily("Tester").addGiven("testUpdateMaintainsSearchParamsAAA");
|
||||
IdDt p1id = ourPatientDao.create(p1).getId();
|
||||
|
||||
Patient p2 = new Patient();
|
||||
p2.addIdentifier().setSystem("urn:system").setValue( "testUpdateMaintainsSearchParamsBBB");
|
||||
p2.addIdentifier().setSystem("urn:system").setValue("testUpdateMaintainsSearchParamsBBB");
|
||||
p2.addName().addFamily("Tester").addGiven("testUpdateMaintainsSearchParamsBBB");
|
||||
ourPatientDao.create(p2).getId();
|
||||
|
||||
|
@ -1536,7 +1675,7 @@ public class FhirResourceDaoTest {
|
|||
|
||||
// Update the name
|
||||
p1.getNameFirstRep().getGivenFirstRep().setValue("testUpdateMaintainsSearchParamsBBB");
|
||||
MethodOutcome update2 = ourPatientDao.update(p1, p1id);
|
||||
MethodOutcome update2 = ourPatientDao.update(p1);
|
||||
IdDt p1id2 = update2.getId();
|
||||
|
||||
ids = ourPatientDao.searchForIds(Patient.SP_GIVEN, new StringDt("testUpdateMaintainsSearchParamsAAA"));
|
||||
|
@ -1557,21 +1696,23 @@ public class FhirResourceDaoTest {
|
|||
@Test
|
||||
public void testUpdateRejectsInvalidTypes() throws InterruptedException {
|
||||
Patient p1 = new Patient();
|
||||
p1.addIdentifier().setSystem("urn:system").setValue( "testUpdateRejectsInvalidTypes");
|
||||
p1.addIdentifier().setSystem("urn:system").setValue("testUpdateRejectsInvalidTypes");
|
||||
p1.addName().addFamily("Tester").addGiven("testUpdateRejectsInvalidTypes");
|
||||
IdDt p1id = ourPatientDao.create(p1).getId();
|
||||
|
||||
Organization p2 = new Organization();
|
||||
p2.getNameElement().setValue("testUpdateRejectsInvalidTypes");
|
||||
try {
|
||||
ourOrganizationDao.update(p2, new IdDt("Organization/" + p1id.getIdPart()));
|
||||
p2.setId(new IdDt("Organization/" + p1id.getIdPart()));
|
||||
ourOrganizationDao.update(p2);
|
||||
fail();
|
||||
} catch (UnprocessableEntityException e) {
|
||||
// good
|
||||
}
|
||||
|
||||
try {
|
||||
ourOrganizationDao.update(p2, new IdDt("Patient/" + p1id.getIdPart()));
|
||||
p2.setId(new IdDt("Patient/" + p1id.getIdPart()));
|
||||
ourOrganizationDao.update(p2);
|
||||
fail();
|
||||
} catch (UnprocessableEntityException e) {
|
||||
// good
|
||||
|
@ -1589,7 +1730,7 @@ public class FhirResourceDaoTest {
|
|||
assertEquals("ABABA", p1id.getIdPart());
|
||||
|
||||
Patient p2 = new Patient();
|
||||
p2.addIdentifier().setSystem("urn:system").setValue( "testUpdateRejectsIdWhichPointsToForcedId02");
|
||||
p2.addIdentifier().setSystem("urn:system").setValue("testUpdateRejectsIdWhichPointsToForcedId02");
|
||||
p2.addName().addFamily("Tester").addGiven("testUpdateRejectsIdWhichPointsToForcedId02");
|
||||
IdDt p2id = ourPatientDao.create(p2).getId();
|
||||
long p1longId = p2id.getIdPartAsLong() - 1;
|
||||
|
@ -1602,7 +1743,8 @@ public class FhirResourceDaoTest {
|
|||
}
|
||||
|
||||
try {
|
||||
ourPatientDao.update(p1, new IdDt("Patient/" + p1longId));
|
||||
p1.setId(new IdDt("Patient/" + p1longId));
|
||||
ourPatientDao.update(p1);
|
||||
fail();
|
||||
} catch (ResourceNotFoundException e) {
|
||||
// good
|
||||
|
@ -1613,13 +1755,14 @@ public class FhirResourceDaoTest {
|
|||
@Test
|
||||
public void testReadForcedIdVersionHistory() throws InterruptedException {
|
||||
Patient p1 = new Patient();
|
||||
p1.addIdentifier().setSystem("urn:system").setValue( "testReadVorcedIdVersionHistory01");
|
||||
p1.addIdentifier().setSystem("urn:system").setValue("testReadVorcedIdVersionHistory01");
|
||||
p1.setId("testReadVorcedIdVersionHistory");
|
||||
IdDt p1id = ourPatientDao.create(p1).getId();
|
||||
assertEquals("testReadVorcedIdVersionHistory", p1id.getIdPart());
|
||||
|
||||
p1.addIdentifier().setSystem("urn:system").setValue( "testReadVorcedIdVersionHistory02");
|
||||
IdDt p1idv2 = ourPatientDao.update(p1, p1id).getId();
|
||||
p1.addIdentifier().setSystem("urn:system").setValue("testReadVorcedIdVersionHistory02");
|
||||
p1.setId(p1id);
|
||||
IdDt p1idv2 = ourPatientDao.update(p1).getId();
|
||||
assertEquals("testReadVorcedIdVersionHistory", p1idv2.getIdPart());
|
||||
|
||||
assertNotEquals(p1id.getValue(), p1idv2.getValue());
|
||||
|
|
|
@ -0,0 +1,414 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
|
||||
import ca.uhn.fhir.model.dstu.resource.Location;
|
||||
import ca.uhn.fhir.model.dstu.resource.Observation;
|
||||
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
public class FhirSystemDaoDstu1Test {
|
||||
|
||||
private static ClassPathXmlApplicationContext ourCtx;
|
||||
private static FhirContext ourFhirContext;
|
||||
private static IFhirResourceDao<Location> ourLocationDao;
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirSystemDaoDstu1Test.class);
|
||||
private static IFhirResourceDao<Observation> ourObservationDao;
|
||||
private static IFhirResourceDao<Patient> ourPatientDao;
|
||||
private static IFhirSystemDao<List<IResource>> ourSystemDao;
|
||||
|
||||
@Test
|
||||
public void testGetResourceCounts() {
|
||||
Observation obs = new Observation();
|
||||
obs.getName().addCoding().setSystem("urn:system").setCode("testGetResourceCountsO01");
|
||||
ourObservationDao.create(obs);
|
||||
|
||||
Map<String, Long> oldCounts = ourSystemDao.getResourceCounts();
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("testGetResourceCountsP01");
|
||||
patient.addName().addFamily("Tester").addGiven("Joe");
|
||||
ourPatientDao.create(patient);
|
||||
|
||||
Map<String, Long> newCounts = ourSystemDao.getResourceCounts();
|
||||
|
||||
if (oldCounts.containsKey("Patient")) {
|
||||
assertEquals(oldCounts.get("Patient") + 1, (long) newCounts.get("Patient"));
|
||||
} else {
|
||||
assertEquals(1L, (long) newCounts.get("Patient"));
|
||||
}
|
||||
|
||||
assertEquals((long) oldCounts.get("Observation"), (long) newCounts.get("Observation"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHistory() throws Exception {
|
||||
Date start = new Date();
|
||||
Thread.sleep(10);
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("testHistory");
|
||||
patient.addName().addFamily("Tester").addGiven("Joe");
|
||||
IdDt pid = ourPatientDao.create(patient).getId().toVersionless();
|
||||
|
||||
Thread.sleep(10);
|
||||
patient.setId(pid);
|
||||
IdDt newpid = ourPatientDao.update(patient).getId();
|
||||
|
||||
Thread.sleep(10);
|
||||
patient.setId(pid);
|
||||
IdDt newpid2 = ourPatientDao.update(patient).getId();
|
||||
|
||||
Thread.sleep(10);
|
||||
patient.setId(pid);
|
||||
IdDt newpid3 = ourPatientDao.update(patient).getId();
|
||||
|
||||
IBundleProvider values = ourSystemDao.history(start);
|
||||
assertEquals(4, values.size());
|
||||
|
||||
List<IResource> res = values.getResources(0, 4);
|
||||
assertEquals(newpid3, res.get(0).getId());
|
||||
assertEquals(newpid2, res.get(1).getId());
|
||||
assertEquals(newpid, res.get(2).getId());
|
||||
assertEquals(pid.toUnqualifiedVersionless(), res.get(3).getId().toUnqualifiedVersionless());
|
||||
|
||||
Location loc = new Location();
|
||||
loc.getAddress().addLine("AAA");
|
||||
IdDt lid = ourLocationDao.create(loc).getId();
|
||||
|
||||
Location loc2 = new Location();
|
||||
loc2.getAddress().addLine("AAA");
|
||||
ourLocationDao.create(loc2).getId();
|
||||
|
||||
Thread.sleep(2000);
|
||||
|
||||
values = ourLocationDao.history(start);
|
||||
assertEquals(2, values.size());
|
||||
|
||||
values = ourLocationDao.history(lid.getIdPartAsLong(), start);
|
||||
assertEquals(1, values.size());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPersistWithSimpleLink() {
|
||||
Patient patient = new Patient();
|
||||
patient.setId(new IdDt("Patient/testPersistWithSimpleLinkP01"));
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("testPersistWithSimpleLinkP01");
|
||||
patient.addName().addFamily("Tester").addGiven("Joe");
|
||||
|
||||
Observation obs = new Observation();
|
||||
obs.getName().addCoding().setSystem("urn:system").setCode("testPersistWithSimpleLinkO01");
|
||||
obs.setSubject(new ResourceReferenceDt("Patient/testPersistWithSimpleLinkP01"));
|
||||
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) patient, obs));
|
||||
|
||||
String patientId = (patient.getId().getIdPart());
|
||||
String obsId = (obs.getId().getIdPart());
|
||||
|
||||
// assertThat(patientId, greaterThan(0L));
|
||||
// assertEquals(patientVersion, 1L);
|
||||
// assertThat(obsId, greaterThan(patientId));
|
||||
// assertEquals(obsVersion, 1L);
|
||||
|
||||
// Try to search
|
||||
|
||||
IBundleProvider obsResults = ourObservationDao.search(Observation.SP_NAME, new IdentifierDt("urn:system", "testPersistWithSimpleLinkO01"));
|
||||
assertEquals(1, obsResults.size());
|
||||
|
||||
IBundleProvider patResults = ourPatientDao.search(Patient.SP_IDENTIFIER, new IdentifierDt("urn:system", "testPersistWithSimpleLinkP01"));
|
||||
assertEquals(1, obsResults.size());
|
||||
|
||||
IdDt foundPatientId = patResults.getResources(0, 1).get(0).getId();
|
||||
ResourceReferenceDt subject = obs.getSubject();
|
||||
assertEquals(foundPatientId.getIdPart(), subject.getReference().getIdPart());
|
||||
|
||||
// Update
|
||||
|
||||
patient = (Patient) patResults.getResources(0, 1).get(0);
|
||||
obs = (Observation) obsResults.getResources(0, 1).get(0);
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("testPersistWithSimpleLinkP02");
|
||||
obs.getName().addCoding().setSystem("urn:system").setCode("testPersistWithSimpleLinkO02");
|
||||
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) patient, obs));
|
||||
|
||||
String patientId2 = (patient.getId().getIdPart());
|
||||
String patientVersion2 = (patient.getId().getVersionIdPart());
|
||||
String obsId2 = (obs.getId().getIdPart());
|
||||
String obsVersion2 = (obs.getId().getVersionIdPart());
|
||||
|
||||
assertEquals(patientId, patientId2);
|
||||
assertEquals(patientVersion2, "2");
|
||||
assertEquals(obsId, obsId2);
|
||||
assertEquals(obsVersion2, "2");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPersistWithUnknownId() {
|
||||
Observation obs = new Observation();
|
||||
obs.getName().addCoding().setSystem("urn:system").setCode("testPersistWithSimpleLinkO01");
|
||||
obs.setSubject(new ResourceReferenceDt("Patient/999998888888"));
|
||||
|
||||
try {
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) obs));
|
||||
} catch (InvalidRequestException e) {
|
||||
assertThat(e.getMessage(), containsString("Resource Patient/999998888888 not found, specified in path: Observation.subject"));
|
||||
}
|
||||
|
||||
obs = new Observation();
|
||||
obs.getName().addCoding().setSystem("urn:system").setCode("testPersistWithSimpleLinkO01");
|
||||
obs.setSubject(new ResourceReferenceDt("Patient/1.2.3.4"));
|
||||
|
||||
try {
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) obs));
|
||||
} catch (InvalidRequestException e) {
|
||||
assertThat(e.getMessage(), containsString("Resource Patient/1.2.3.4 not found, specified in path: Observation.subject"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTagOperationss() throws Exception {
|
||||
|
||||
TagList preSystemTl = ourSystemDao.getAllTags();
|
||||
|
||||
TagList tl1 = new TagList();
|
||||
tl1.addTag("testGetAllTagsScheme1", "testGetAllTagsTerm1", "testGetAllTagsLabel1");
|
||||
Patient p1 = new Patient();
|
||||
p1.addIdentifier().setSystem("foo").setValue("testGetAllTags01");
|
||||
ResourceMetadataKeyEnum.TAG_LIST.put(p1, tl1);
|
||||
ourPatientDao.create(p1);
|
||||
|
||||
TagList tl2 = new TagList();
|
||||
tl2.addTag("testGetAllTagsScheme2", "testGetAllTagsTerm2", "testGetAllTagsLabel2");
|
||||
Observation o1 = new Observation();
|
||||
o1.getName().setText("testGetAllTags02");
|
||||
ResourceMetadataKeyEnum.TAG_LIST.put(o1, tl2);
|
||||
IdDt o1id = ourObservationDao.create(o1).getId();
|
||||
assertTrue(o1id.getVersionIdPart() != null);
|
||||
|
||||
TagList postSystemTl = ourSystemDao.getAllTags();
|
||||
assertEquals(preSystemTl.size() + 2, postSystemTl.size());
|
||||
assertEquals("testGetAllTagsLabel1", postSystemTl.getTag("testGetAllTagsScheme1", "testGetAllTagsTerm1").getLabel());
|
||||
|
||||
TagList tags = ourPatientDao.getAllResourceTags();
|
||||
assertEquals("testGetAllTagsLabel1", tags.getTag("testGetAllTagsScheme1", "testGetAllTagsTerm1").getLabel());
|
||||
assertNull(tags.getTag("testGetAllTagsScheme2", "testGetAllTagsTerm2"));
|
||||
|
||||
TagList tags2 = ourObservationDao.getTags(o1id);
|
||||
assertNull(tags2.getTag("testGetAllTagsScheme1", "testGetAllTagsTerm1"));
|
||||
assertEquals("testGetAllTagsLabel2", tags2.getTag("testGetAllTagsScheme2", "testGetAllTagsTerm2").getLabel());
|
||||
|
||||
o1.getResourceMetadata().remove(ResourceMetadataKeyEnum.TAG_LIST);
|
||||
o1.setId(o1id);
|
||||
IdDt o1id2 = ourObservationDao.update(o1).getId();
|
||||
assertTrue(o1id2.getVersionIdPart() != null);
|
||||
|
||||
tags2 = ourObservationDao.getTags(o1id);
|
||||
assertNull(tags2.getTag("testGetAllTagsScheme1", "testGetAllTagsTerm1"));
|
||||
assertEquals("testGetAllTagsLabel2", tags2.getTag("testGetAllTagsScheme2", "testGetAllTagsTerm2").getLabel());
|
||||
|
||||
tags2 = ourObservationDao.getTags(o1id2);
|
||||
assertNull(tags2.getTag("testGetAllTagsScheme1", "testGetAllTagsTerm1"));
|
||||
assertNotNull(tags2.getTag("testGetAllTagsScheme2", "testGetAllTagsTerm2"));
|
||||
|
||||
/*
|
||||
* Remove a tag from a version
|
||||
*/
|
||||
|
||||
ourObservationDao.removeTag(o1id2, "testGetAllTagsScheme2", "testGetAllTagsTerm2");
|
||||
tags2 = ourObservationDao.getTags(o1id2);
|
||||
assertNull(tags2.getTag("testGetAllTagsScheme1", "testGetAllTagsTerm1"));
|
||||
assertNull(tags2.getTag("testGetAllTagsScheme2", "testGetAllTagsTerm2"));
|
||||
|
||||
tags2 = ourObservationDao.getTags(o1id);
|
||||
assertNull(tags2.getTag("testGetAllTagsScheme1", "testGetAllTagsTerm1"));
|
||||
assertNotNull(tags2.getTag("testGetAllTagsScheme2", "testGetAllTagsTerm2"));
|
||||
|
||||
/*
|
||||
* Add a tag
|
||||
*/
|
||||
ourObservationDao.addTag(o1id2, "testGetAllTagsScheme3", "testGetAllTagsTerm3", "testGetAllTagsLabel3");
|
||||
tags2 = ourObservationDao.getTags(o1id2);
|
||||
assertNull(tags2.getTag("testGetAllTagsScheme1", "testGetAllTagsTerm1"));
|
||||
assertNull(tags2.getTag("testGetAllTagsScheme2", "testGetAllTagsTerm2"));
|
||||
assertNotNull(tags2.getTag("testGetAllTagsScheme3", "testGetAllTagsTerm3"));
|
||||
assertEquals("testGetAllTagsLabel3", tags2.getTag("testGetAllTagsScheme3", "testGetAllTagsTerm3").getLabel());
|
||||
|
||||
tags2 = ourObservationDao.getTags(o1id);
|
||||
assertNull(tags2.getTag("testGetAllTagsScheme1", "testGetAllTagsTerm1"));
|
||||
assertNotNull(tags2.getTag("testGetAllTagsScheme2", "testGetAllTagsTerm2"));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = InvalidRequestException.class)
|
||||
public void testTransactionFailsWithDuplicateIds() {
|
||||
Patient patient1 = new Patient();
|
||||
patient1.setId(new IdDt("Patient/testTransactionFailsWithDusplicateIds"));
|
||||
patient1.addIdentifier().setSystem("urn:system").setValue("testPersistWithSimpleLinkP01");
|
||||
|
||||
Patient patient2 = new Patient();
|
||||
patient2.setId(new IdDt("Patient/testTransactionFailsWithDusplicateIds"));
|
||||
patient2.addIdentifier().setSystem("urn:system").setValue("testPersistWithSimpleLinkP02");
|
||||
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) patient1, patient2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionFromBundle() throws Exception {
|
||||
|
||||
InputStream bundleRes = FhirSystemDaoDstu1Test.class.getResourceAsStream("/bundle-dstu1.xml");
|
||||
Bundle bundle = ourFhirContext.newXmlParser().parseBundle(new InputStreamReader(bundleRes));
|
||||
List<IResource> res = bundle.toListOfResources();
|
||||
|
||||
ourSystemDao.transaction(res);
|
||||
|
||||
Patient p1 = (Patient) res.get(0);
|
||||
String id = p1.getId().getValue();
|
||||
ourLog.info("ID: {}", id);
|
||||
assertThat(id, not(equalToIgnoringCase("74635")));
|
||||
assertThat(id, not(equalToIgnoringCase("")));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Issue #55
|
||||
*/
|
||||
@Test
|
||||
public void testTransactionWithCidIds() throws Exception {
|
||||
List<IResource> res = new ArrayList<IResource>();
|
||||
|
||||
Patient p1 = new Patient();
|
||||
p1.setId("cid:patient1");
|
||||
p1.addIdentifier().setSystem("system").setValue("testTransactionWithCidIds01");
|
||||
res.add(p1);
|
||||
|
||||
Observation o1 = new Observation();
|
||||
o1.setId("cid:observation1");
|
||||
o1.getIdentifier().setSystem("system").setValue("testTransactionWithCidIds02");
|
||||
o1.setSubject(new ResourceReferenceDt("Patient/cid:patient1"));
|
||||
res.add(o1);
|
||||
|
||||
Observation o2 = new Observation();
|
||||
o2.setId("cid:observation2");
|
||||
o2.getIdentifier().setSystem("system").setValue("testTransactionWithCidIds03");
|
||||
o2.setSubject(new ResourceReferenceDt("Patient/cid:patient1"));
|
||||
res.add(o2);
|
||||
|
||||
ourSystemDao.transaction(res);
|
||||
|
||||
assertTrue(p1.getId().getValue(), p1.getId().getIdPart().matches("^[0-9]+$"));
|
||||
assertTrue(o1.getId().getValue(), o1.getId().getIdPart().matches("^[0-9]+$"));
|
||||
assertTrue(o2.getId().getValue(), o2.getId().getIdPart().matches("^[0-9]+$"));
|
||||
|
||||
assertThat(o1.getSubject().getReference().getValue(), endsWith("Patient/" + p1.getId().getIdPart()));
|
||||
assertThat(o2.getSubject().getReference().getValue(), endsWith("Patient/" + p1.getId().getIdPart()));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionWithDelete() throws Exception {
|
||||
|
||||
/*
|
||||
* Create 3
|
||||
*/
|
||||
|
||||
List<IResource> res;
|
||||
res = new ArrayList<IResource>();
|
||||
|
||||
Patient p1 = new Patient();
|
||||
p1.addIdentifier().setSystem("urn:system").setValue("testTransactionWithDelete");
|
||||
res.add(p1);
|
||||
|
||||
Patient p2 = new Patient();
|
||||
p2.addIdentifier().setSystem("urn:system").setValue("testTransactionWithDelete");
|
||||
res.add(p2);
|
||||
|
||||
Patient p3 = new Patient();
|
||||
p3.addIdentifier().setSystem("urn:system").setValue("testTransactionWithDelete");
|
||||
res.add(p3);
|
||||
|
||||
ourSystemDao.transaction(res);
|
||||
|
||||
/*
|
||||
* Verify
|
||||
*/
|
||||
|
||||
IBundleProvider results = ourPatientDao.search(Patient.SP_IDENTIFIER, new TokenParam("urn:system", "testTransactionWithDelete"));
|
||||
assertEquals(3, results.size());
|
||||
|
||||
/*
|
||||
* Now delete 2
|
||||
*/
|
||||
|
||||
res = new ArrayList<IResource>();
|
||||
List<IResource> existing = results.getResources(0, 3);
|
||||
|
||||
p1 = new Patient();
|
||||
p1.setId(existing.get(0).getId());
|
||||
ResourceMetadataKeyEnum.DELETED_AT.put(p1, InstantDt.withCurrentTime());
|
||||
res.add(p1);
|
||||
|
||||
p2 = new Patient();
|
||||
p2.setId(existing.get(1).getId());
|
||||
ResourceMetadataKeyEnum.DELETED_AT.put(p2, InstantDt.withCurrentTime());
|
||||
res.add(p2);
|
||||
|
||||
ourSystemDao.transaction(res);
|
||||
|
||||
/*
|
||||
* Verify
|
||||
*/
|
||||
|
||||
IBundleProvider results2 = ourPatientDao.search(Patient.SP_IDENTIFIER, new TokenParam("urn:system", "testTransactionWithDelete"));
|
||||
assertEquals(1, results2.size());
|
||||
List<IResource> existing2 = results2.getResources(0, 1);
|
||||
assertEquals(existing2.get(0).getId(), existing.get(2).getId());
|
||||
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() {
|
||||
ourCtx.close();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@BeforeClass
|
||||
public static void beforeClass() {
|
||||
ourCtx = new ClassPathXmlApplicationContext("hapi-fhir-server-resourceproviders-dstu1.xml", "fhir-jpabase-spring-test-config.xml");
|
||||
ourFhirContext = ourCtx.getBean(FhirContext.class);
|
||||
ourPatientDao = ourCtx.getBean("myPatientDaoDstu1", IFhirResourceDao.class);
|
||||
ourObservationDao = ourCtx.getBean("myObservationDaoDstu1", IFhirResourceDao.class);
|
||||
ourLocationDao = ourCtx.getBean("myLocationDaoDstu1", IFhirResourceDao.class);
|
||||
ourSystemDao = ourCtx.getBean("mySystemDaoDstu1", IFhirSystemDao.class);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,681 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.model.dstu2.composite.IdentifierDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.QuantityDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Location;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Observation;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.model.valueset.BundleEntryTransactionOperationEnum;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||
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.ResourceNotFoundException;
|
||||
|
||||
public class FhirSystemDaoDstu2Test {
|
||||
|
||||
private static ClassPathXmlApplicationContext ourCtx;
|
||||
private static FhirContext ourFhirContext;
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirSystemDaoDstu2Test.class);
|
||||
private static IFhirResourceDao<Patient> ourPatientDao;
|
||||
private static IFhirSystemDao<Bundle> ourSystemDao;
|
||||
private static IFhirResourceDao<Observation> ourObservationDao;
|
||||
|
||||
@Test
|
||||
public void testTransactionCreateMatchUrlWithOneMatch() {
|
||||
String methodName = "testTransactionCreateMatchUrlWithOneMatch";
|
||||
Bundle request = new Bundle();
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.setId("Patient/" + methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
request.addEntry().setResource(p).getTransaction().setMethod(HTTPVerbEnum.POST).setIfNoneExist("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient/" + methodName);
|
||||
request.addEntry().setResource(o).getTransaction().setMethod(HTTPVerbEnum.POST);
|
||||
|
||||
Bundle resp = ourSystemDao.transaction(request);
|
||||
assertEquals(3, resp.getEntry().size());
|
||||
|
||||
Entry respEntry = resp.getEntry().get(1);
|
||||
assertEquals(Constants.STATUS_HTTP_200_OK + "", respEntry.getTransactionResponse().getStatus());
|
||||
assertThat(respEntry.getTransactionResponse().getLocation(), endsWith("Patient/" + id.getIdPart() + "/_history/1"));
|
||||
assertEquals("1", respEntry.getTransactionResponse().getEtag().get(0).getValue());
|
||||
|
||||
respEntry = resp.getEntry().get(2);
|
||||
assertEquals(Constants.STATUS_HTTP_201_CREATED + "", respEntry.getTransactionResponse().getStatus());
|
||||
assertThat(respEntry.getTransactionResponse().getLocation(), containsString("Observation/"));
|
||||
assertThat(respEntry.getTransactionResponse().getLocation(), endsWith("/_history/1"));
|
||||
assertEquals("1", respEntry.getTransactionResponse().getEtag().get(0).getValue());
|
||||
|
||||
o = (Observation) ourObservationDao.read(new IdDt(respEntry.getTransactionResponse().getLocationElement()));
|
||||
assertEquals(id.toVersionless(), o.getSubject().getReference());
|
||||
assertEquals("1", o.getId().getVersionIdPart());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testTransactionReadAndSearch() {
|
||||
String methodName = "testTransactionReadAndSearch";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.setId("Patient/" + methodName);
|
||||
IdDt idv1 = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got id: {}", idv1);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Family Name");
|
||||
p.setId("Patient/" + methodName);
|
||||
IdDt idv2 = ourPatientDao.update(p).getId();
|
||||
ourLog.info("Updated patient, got id: {}", idv2);
|
||||
|
||||
Bundle request = new Bundle();
|
||||
request.addEntry().getTransaction().setMethod(HTTPVerbEnum.GET).setUrl(idv1.toUnqualifiedVersionless().getValue());
|
||||
request.addEntry().getTransaction().setMethod(HTTPVerbEnum.GET).setUrl(idv1.toUnqualified().getValue());
|
||||
request.addEntry().getTransaction().setMethod(HTTPVerbEnum.GET).setUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Bundle resp = ourSystemDao.transaction(request);
|
||||
|
||||
assertEquals(4, resp.getEntry().size());
|
||||
|
||||
Entry nextEntry;
|
||||
|
||||
nextEntry = resp.getEntry().get(1);
|
||||
assertEquals(Patient.class, nextEntry.getResource().getClass());
|
||||
assertEquals(idv2.toUnqualified(), nextEntry.getResource().getId().toUnqualified());
|
||||
|
||||
nextEntry = resp.getEntry().get(2);
|
||||
assertEquals(Patient.class, nextEntry.getResource().getClass());
|
||||
assertEquals(idv1.toUnqualified(), nextEntry.getResource().getId().toUnqualified());
|
||||
|
||||
nextEntry = resp.getEntry().get(3);
|
||||
assertEquals(Bundle.class, nextEntry.getResource().getClass());
|
||||
|
||||
Bundle respBundle = (Bundle)nextEntry.getResource();
|
||||
assertEquals(1, respBundle.getTotal().intValue());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testTransactionCreateMatchUrlWithTwoMatch() {
|
||||
String methodName = "testTransactionCreateMatchUrlWithTwoMatch";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
Bundle request = new Bundle();
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
request.addEntry().setResource(p).getTransaction().setMethod(HTTPVerbEnum.POST).setIfNoneExist("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient/" + methodName);
|
||||
request.addEntry().setResource(o).getTransaction().setMethod(HTTPVerbEnum.POST);
|
||||
|
||||
try {
|
||||
ourSystemDao.transaction(request);
|
||||
fail();
|
||||
} catch (PreconditionFailedException e) {
|
||||
assertThat(e.getMessage(), containsString("with match URL \"Patient"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionCreateMatchUrlWithZeroMatch() {
|
||||
String methodName = "testTransactionCreateMatchUrlWithZeroMatch";
|
||||
Bundle request = new Bundle();
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
request.addEntry().setResource(p).getTransaction().setMethod(HTTPVerbEnum.POST).setIfNoneExist("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient/" + methodName);
|
||||
request.addEntry().setResource(o).getTransaction().setMethod(HTTPVerbEnum.POST);
|
||||
|
||||
Bundle resp = ourSystemDao.transaction(request);
|
||||
assertEquals(3, resp.getEntry().size());
|
||||
|
||||
Entry respEntry = resp.getEntry().get(1);
|
||||
assertEquals(Constants.STATUS_HTTP_201_CREATED + "", respEntry.getTransactionResponse().getStatus());
|
||||
String patientId = respEntry.getTransactionResponse().getLocation();
|
||||
assertThat(patientId, not(endsWith("Patient/" + methodName + "/_history/1")));
|
||||
assertThat(patientId, (endsWith("/_history/1")));
|
||||
assertThat(patientId, (containsString("Patient/")));
|
||||
assertEquals("1", respEntry.getTransactionResponse().getEtag().get(0).getValue());
|
||||
|
||||
respEntry = resp.getEntry().get(2);
|
||||
assertEquals(Constants.STATUS_HTTP_201_CREATED + "", respEntry.getTransactionResponse().getStatus());
|
||||
assertThat(respEntry.getTransactionResponse().getLocation(), containsString("Observation/"));
|
||||
assertThat(respEntry.getTransactionResponse().getLocation(), endsWith("/_history/1"));
|
||||
assertEquals("1", respEntry.getTransactionResponse().getEtag().get(0).getValue());
|
||||
|
||||
o = (Observation) ourObservationDao.read(new IdDt(respEntry.getTransactionResponse().getLocationElement()));
|
||||
assertEquals(new IdDt(patientId).toUnqualifiedVersionless(), o.getSubject().getReference());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionCreateNoMatchUrl() {
|
||||
String methodName = "testTransactionCreateNoMatchUrl";
|
||||
Bundle request = new Bundle();
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.setId("Patient/" + methodName);
|
||||
request.addEntry().setResource(p).getTransaction().setMethod(HTTPVerbEnum.POST).setIfNoneExist("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Bundle resp = ourSystemDao.transaction(request);
|
||||
assertEquals(2, resp.getEntry().size());
|
||||
|
||||
Entry respEntry = resp.getEntry().get(1);
|
||||
assertEquals(Constants.STATUS_HTTP_201_CREATED + "", respEntry.getTransactionResponse().getStatus());
|
||||
String patientId = respEntry.getTransactionResponse().getLocation();
|
||||
assertThat(patientId, not(containsString("test")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionDeleteMatchUrlWithOneMatch() {
|
||||
String methodName = "testTransactionDeleteMatchUrlWithOneMatch";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
Bundle request = new Bundle();
|
||||
request.addEntry().getTransaction().setMethod(HTTPVerbEnum.DELETE).setUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Bundle resp = ourSystemDao.transaction(request);
|
||||
assertEquals(2, resp.getEntry().size());
|
||||
|
||||
Entry nextEntry = resp.getEntry().get(1);
|
||||
assertEquals(Constants.STATUS_HTTP_204_NO_CONTENT + "", nextEntry.getTransactionResponse().getStatus());
|
||||
|
||||
try {
|
||||
ourPatientDao.read(id.toVersionless());
|
||||
fail();
|
||||
} catch (ResourceGoneException e) {
|
||||
// ok
|
||||
}
|
||||
|
||||
try {
|
||||
ourPatientDao.read(new IdDt("Patient/" + methodName));
|
||||
fail();
|
||||
} catch (ResourceNotFoundException e) {
|
||||
// ok
|
||||
}
|
||||
|
||||
IBundleProvider history = ourPatientDao.history(id, null);
|
||||
assertEquals(2, history.size());
|
||||
|
||||
assertNotNull(ResourceMetadataKeyEnum.DELETED_AT.get(history.getResources(0, 0).get(0)));
|
||||
assertNotNull(ResourceMetadataKeyEnum.DELETED_AT.get(history.getResources(0, 0).get(0)).getValue());
|
||||
assertNull(ResourceMetadataKeyEnum.DELETED_AT.get(history.getResources(1, 1).get(0)));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionDeleteMatchUrlWithTwoMatch() {
|
||||
String methodName = "testTransactionDeleteMatchUrlWithTwoMatch";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
|
||||
Bundle request = new Bundle();
|
||||
request.addEntry().getTransaction().setMethod(HTTPVerbEnum.DELETE).setUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
try {
|
||||
ourSystemDao.transaction(request);
|
||||
fail();
|
||||
} catch (ResourceNotFoundException e) {
|
||||
assertThat(e.getMessage(), containsString("resource with match URL \"Patient?"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionDeleteByResourceId() {
|
||||
String methodName = "testTransactionDeleteByResourceId";
|
||||
|
||||
Patient p1 = new Patient();
|
||||
p1.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
IdDt id1 = ourPatientDao.create(p1).getId();
|
||||
ourLog.info("Created patient, got it: {}", id1);
|
||||
|
||||
Patient p2 = new Patient();
|
||||
p2.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p2.setId("Patient/" + methodName);
|
||||
IdDt id2 = ourPatientDao.create(p2).getId();
|
||||
ourLog.info("Created patient, got it: {}", id2);
|
||||
|
||||
Bundle request = new Bundle();
|
||||
|
||||
request.addEntry().getTransaction().setMethod(HTTPVerbEnum.DELETE).setUrl("Patient/" + id1.getIdPart());
|
||||
request.addEntry().getTransaction().setMethod(HTTPVerbEnum.DELETE).setUrl("Patient/" + id2.getIdPart());
|
||||
|
||||
ourPatientDao.read(id1.toVersionless());
|
||||
ourPatientDao.read(id2.toVersionless());
|
||||
|
||||
Bundle resp = ourSystemDao.transaction(request);
|
||||
|
||||
assertEquals(3, resp.getEntry().size());
|
||||
assertEquals("204", resp.getEntry().get(1).getTransactionResponse().getStatus());
|
||||
assertEquals("204", resp.getEntry().get(2).getTransactionResponse().getStatus());
|
||||
|
||||
try {
|
||||
ourPatientDao.read(id1.toVersionless());
|
||||
fail();
|
||||
} catch (ResourceGoneException e) {
|
||||
// good
|
||||
}
|
||||
|
||||
try {
|
||||
ourPatientDao.read(id2.toVersionless());
|
||||
fail();
|
||||
} catch (ResourceGoneException e) {
|
||||
// good
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionDeleteMatchUrlWithZeroMatch() {
|
||||
String methodName = "testTransactionDeleteMatchUrlWithZeroMatch";
|
||||
|
||||
Bundle request = new Bundle();
|
||||
request.addEntry().getTransaction().setMethod(HTTPVerbEnum.DELETE).setUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
try {
|
||||
ourSystemDao.transaction(request);
|
||||
fail();
|
||||
} catch (ResourceNotFoundException e) {
|
||||
assertThat(e.getMessage(), containsString("resource matching URL \"Patient?"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionDeleteNoMatchUrl() {
|
||||
String methodName = "testTransactionDeleteNoMatchUrl";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.setId("Patient/" + methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
Bundle request = new Bundle();
|
||||
request.addEntry().getTransaction().setMethod(HTTPVerbEnum.DELETE).setUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Bundle res = ourSystemDao.transaction(request);
|
||||
assertEquals(2, res.getEntry().size());
|
||||
|
||||
assertEquals(Constants.STATUS_HTTP_204_NO_CONTENT + "", res.getEntry().get(1).getTransactionResponse().getStatus());
|
||||
|
||||
try {
|
||||
ourPatientDao.read(id.toVersionless());
|
||||
fail();
|
||||
} catch (ResourceGoneException e) {
|
||||
// ok
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = InvalidRequestException.class)
|
||||
public void testTransactionFailsWithDuplicateIds() {
|
||||
Bundle request = new Bundle();
|
||||
|
||||
Patient patient1 = new Patient();
|
||||
patient1.setId(new IdDt("Patient/testTransactionFailsWithDusplicateIds"));
|
||||
patient1.addIdentifier().setSystem("urn:system").setValue("testPersistWithSimpleLinkP01");
|
||||
request.addEntry().setResource(patient1).getTransaction().setMethod(HTTPVerbEnum.POST);
|
||||
|
||||
Patient patient2 = new Patient();
|
||||
patient2.setId(new IdDt("Patient/testTransactionFailsWithDusplicateIds"));
|
||||
patient2.addIdentifier().setSystem("urn:system").setValue("testPersistWithSimpleLinkP02");
|
||||
request.addEntry().setResource(patient2).getTransaction().setMethod(HTTPVerbEnum.POST);
|
||||
|
||||
ourSystemDao.transaction(request);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionUpdateMatchUrlWithOneMatch() {
|
||||
String methodName = "testTransactionUpdateMatchUrlWithOneMatch";
|
||||
Bundle request = new Bundle();
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
request.addEntry().setResource(p).getTransaction().setMethod(HTTPVerbEnum.PUT).setUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient/" + methodName);
|
||||
request.addEntry().setResource(o).getTransaction().setMethod(HTTPVerbEnum.POST);
|
||||
|
||||
Bundle resp = ourSystemDao.transaction(request);
|
||||
assertEquals(3, resp.getEntry().size());
|
||||
|
||||
Entry nextEntry = resp.getEntry().get(1);
|
||||
assertEquals("200", nextEntry.getTransactionResponse().getStatus());
|
||||
assertThat(nextEntry.getTransactionResponse().getLocation(), not(containsString("test")));
|
||||
assertEquals(id.toVersionless(), p.getId().toVersionless());
|
||||
assertNotEquals(id, p.getId());
|
||||
assertThat(p.getId().toString(), endsWith("/_history/2"));
|
||||
|
||||
nextEntry = resp.getEntry().get(1);
|
||||
assertEquals(""+Constants.STATUS_HTTP_200_OK, nextEntry.getTransactionResponse().getStatus());
|
||||
assertThat(nextEntry.getTransactionResponse().getLocation(), not(emptyString()));
|
||||
|
||||
nextEntry = resp.getEntry().get(2);
|
||||
o = ourObservationDao.read(new IdDt(nextEntry.getTransactionResponse().getLocation()));
|
||||
assertEquals(id.toVersionless(), o.getSubject().getReference());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionUpdateMatchUrlWithTwoMatch() {
|
||||
String methodName = "testTransactionUpdateMatchUrlWithTwoMatch";
|
||||
Bundle request = new Bundle();
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
request.addEntry().setResource(p).getTransaction().setMethod(HTTPVerbEnum.PUT).setUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient/" + methodName);
|
||||
request.addEntry().setResource(o).getTransaction().setMethod(HTTPVerbEnum.POST);
|
||||
|
||||
try {
|
||||
ourSystemDao.transaction(request);
|
||||
fail();
|
||||
} catch (PreconditionFailedException e) {
|
||||
assertThat(e.getMessage(), containsString("with match URL \"Patient"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionUpdateMatchUrlWithZeroMatch() {
|
||||
String methodName = "testTransactionUpdateMatchUrlWithZeroMatch";
|
||||
Bundle request = new Bundle();
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addName().addFamily("Hello");
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId(id);
|
||||
request.addEntry().setResource(p).getTransaction().setMethod(HTTPVerbEnum.PUT).setUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference(id);
|
||||
request.addEntry().setResource(o).getTransaction().setMethod(HTTPVerbEnum.POST);
|
||||
|
||||
Bundle resp = ourSystemDao.transaction(request);
|
||||
assertEquals(3, resp.getEntry().size());
|
||||
|
||||
Entry nextEntry = resp.getEntry().get(1);
|
||||
assertEquals(Constants.STATUS_HTTP_201_CREATED + "", nextEntry.getTransactionResponse().getStatus());
|
||||
|
||||
assertThat(nextEntry.getTransactionResponse().getLocation(), not(containsString("test")));
|
||||
assertNotEquals(id.toVersionless(), new IdDt(nextEntry.getTransactionResponse().getLocation()).toVersionless());
|
||||
|
||||
assertThat(nextEntry.getTransactionResponse().getLocation(), endsWith("/_history/1"));
|
||||
|
||||
nextEntry = resp.getEntry().get(1);
|
||||
assertEquals(""+Constants.STATUS_HTTP_201_CREATED, nextEntry.getTransactionResponse().getStatus());
|
||||
|
||||
nextEntry = resp.getEntry().get(2);
|
||||
o = ourObservationDao.read(new IdDt(nextEntry.getTransactionResponse().getLocation()));
|
||||
assertEquals(id.toVersionless(), o.getSubject().getReference());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testTransactionUpdateNoMatchUrl() {
|
||||
String methodName = "testTransactionUpdateNoMatchUrl";
|
||||
Bundle request = new Bundle();
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.setId("Patient/" + methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
request.addEntry().setResource(p).getTransaction().setMethod(HTTPVerbEnum.PUT).setUrl("Patient/"+ id.getIdPart());
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient/" + methodName);
|
||||
request.addEntry().setResource(o).getTransaction().setMethod(HTTPVerbEnum.POST);
|
||||
|
||||
Bundle resp = ourSystemDao.transaction(request);
|
||||
assertEquals(3, resp.getEntry().size());
|
||||
|
||||
Entry nextEntry = resp.getEntry().get(1);
|
||||
assertEquals("200", nextEntry.getTransactionResponse().getStatus());
|
||||
|
||||
assertThat(nextEntry.getTransactionResponse().getLocation(), (containsString("test")));
|
||||
assertEquals(id.toVersionless(), new IdDt(nextEntry.getTransactionResponse().getLocation()).toVersionless());
|
||||
assertNotEquals(id, new IdDt(nextEntry.getTransactionResponse().getLocation()));
|
||||
assertThat(nextEntry.getTransactionResponse().getLocation(), endsWith("/_history/2"));
|
||||
|
||||
nextEntry = resp.getEntry().get(2);
|
||||
assertEquals(""+Constants.STATUS_HTTP_201_CREATED, nextEntry.getTransactionResponse().getStatus());
|
||||
|
||||
o = ourObservationDao.read(new IdDt(resp.getEntry().get(2).getTransactionResponse().getLocation()));
|
||||
assertEquals(id.toVersionless(), o.getSubject().getReference());
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * Issue #55
|
||||
// */
|
||||
// @Test
|
||||
// public void testTransactionWithCidIds() throws Exception {
|
||||
// Bundle request = new Bundle();
|
||||
//
|
||||
// Patient p1 = new Patient();
|
||||
// p1.setId("cid:patient1");
|
||||
// p1.addIdentifier().setSystem("system").setValue("testTransactionWithCidIds01");
|
||||
// res.add(p1);
|
||||
//
|
||||
// Observation o1 = new Observation();
|
||||
// o1.setId("cid:observation1");
|
||||
// o1.getIdentifier().setSystem("system").setValue("testTransactionWithCidIds02");
|
||||
// o1.setSubject(new ResourceReferenceDt("Patient/cid:patient1"));
|
||||
// res.add(o1);
|
||||
//
|
||||
// Observation o2 = new Observation();
|
||||
// o2.setId("cid:observation2");
|
||||
// o2.getIdentifier().setSystem("system").setValue("testTransactionWithCidIds03");
|
||||
// o2.setSubject(new ResourceReferenceDt("Patient/cid:patient1"));
|
||||
// res.add(o2);
|
||||
//
|
||||
// ourSystemDao.transaction(res);
|
||||
//
|
||||
// assertTrue(p1.getId().getValue(), p1.getId().getIdPart().matches("^[0-9]+$"));
|
||||
// assertTrue(o1.getId().getValue(), o1.getId().getIdPart().matches("^[0-9]+$"));
|
||||
// assertTrue(o2.getId().getValue(), o2.getId().getIdPart().matches("^[0-9]+$"));
|
||||
//
|
||||
// assertThat(o1.getSubject().getReference().getValue(), endsWith("Patient/" + p1.getId().getIdPart()));
|
||||
// assertThat(o2.getSubject().getReference().getValue(), endsWith("Patient/" + p1.getId().getIdPart()));
|
||||
//
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void testTransactionWithDelete() throws Exception {
|
||||
// Bundle request = new Bundle();
|
||||
//
|
||||
// /*
|
||||
// * Create 3
|
||||
// */
|
||||
//
|
||||
// List<IResource> res;
|
||||
// res = new ArrayList<IResource>();
|
||||
//
|
||||
// Patient p1 = new Patient();
|
||||
// p1.addIdentifier().setSystem("urn:system").setValue("testTransactionWithDelete");
|
||||
// res.add(p1);
|
||||
//
|
||||
// Patient p2 = new Patient();
|
||||
// p2.addIdentifier().setSystem("urn:system").setValue("testTransactionWithDelete");
|
||||
// res.add(p2);
|
||||
//
|
||||
// Patient p3 = new Patient();
|
||||
// p3.addIdentifier().setSystem("urn:system").setValue("testTransactionWithDelete");
|
||||
// res.add(p3);
|
||||
//
|
||||
// ourSystemDao.transaction(res);
|
||||
//
|
||||
// /*
|
||||
// * Verify
|
||||
// */
|
||||
//
|
||||
// IBundleProvider results = ourPatientDao.search(Patient.SP_IDENTIFIER, new TokenParam("urn:system",
|
||||
// "testTransactionWithDelete"));
|
||||
// assertEquals(3, results.size());
|
||||
//
|
||||
// /*
|
||||
// * Now delete 2
|
||||
// */
|
||||
//
|
||||
// request = new Bundle();
|
||||
// res = new ArrayList<IResource>();
|
||||
// List<IResource> existing = results.getResources(0, 3);
|
||||
//
|
||||
// p1 = new Patient();
|
||||
// p1.setId(existing.get(0).getId());
|
||||
// ResourceMetadataKeyEnum.DELETED_AT.put(p1, InstantDt.withCurrentTime());
|
||||
// res.add(p1);
|
||||
//
|
||||
// p2 = new Patient();
|
||||
// p2.setId(existing.get(1).getId());
|
||||
// ResourceMetadataKeyEnum.DELETED_AT.put(p2, InstantDt.withCurrentTime());
|
||||
// res.add(p2);
|
||||
//
|
||||
// ourSystemDao.transaction(res);
|
||||
//
|
||||
// /*
|
||||
// * Verify
|
||||
// */
|
||||
//
|
||||
// IBundleProvider results2 = ourPatientDao.search(Patient.SP_IDENTIFIER, new TokenParam("urn:system",
|
||||
// "testTransactionWithDelete"));
|
||||
// assertEquals(1, results2.size());
|
||||
// List<IResource> existing2 = results2.getResources(0, 1);
|
||||
// assertEquals(existing2.get(0).getId(), existing.get(2).getId());
|
||||
//
|
||||
// }
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() {
|
||||
ourCtx.close();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@BeforeClass
|
||||
public static void beforeClass() {
|
||||
ourCtx = new ClassPathXmlApplicationContext("hapi-fhir-server-resourceproviders-dstu2.xml", "fhir-jpabase-spring-test-config.xml");
|
||||
ourFhirContext = ourCtx.getBean(FhirContext.class);
|
||||
assertEquals(FhirVersionEnum.DSTU2, ourFhirContext.getVersion().getVersion());
|
||||
ourPatientDao = ourCtx.getBean("myPatientDaoDstu2", IFhirResourceDao.class);
|
||||
ourObservationDao = ourCtx.getBean("myObservationDaoDstu2", IFhirResourceDao.class);
|
||||
ourSystemDao = ourCtx.getBean("mySystemDaoDstu2", IFhirSystemDao.class);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,899 +0,0 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.QuantityDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
|
||||
import ca.uhn.fhir.model.dstu.resource.Location;
|
||||
import ca.uhn.fhir.model.dstu.resource.Observation;
|
||||
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.model.valueset.BundleEntryTransactionOperationEnum;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
|
||||
public class FhirSystemDaoTest {
|
||||
|
||||
private static ClassPathXmlApplicationContext ourCtx;
|
||||
private static FhirContext ourFhirContext;
|
||||
private static IFhirResourceDao<Location> ourLocationDao;
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirSystemDaoTest.class);
|
||||
private static IFhirResourceDao<Observation> ourObservationDao;
|
||||
private static IFhirResourceDao<Patient> ourPatientDao;
|
||||
private static IFhirSystemDao<List<IResource>> ourSystemDao;
|
||||
|
||||
@Test
|
||||
public void testGetResourceCounts() {
|
||||
Observation obs = new Observation();
|
||||
obs.getName().addCoding().setSystem("urn:system").setCode("testGetResourceCountsO01");
|
||||
ourObservationDao.create(obs);
|
||||
|
||||
Map<String, Long> oldCounts = ourSystemDao.getResourceCounts();
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("testGetResourceCountsP01");
|
||||
patient.addName().addFamily("Tester").addGiven("Joe");
|
||||
ourPatientDao.create(patient);
|
||||
|
||||
Map<String, Long> newCounts = ourSystemDao.getResourceCounts();
|
||||
|
||||
if (oldCounts.containsKey("Patient")) {
|
||||
assertEquals(oldCounts.get("Patient") + 1, (long) newCounts.get("Patient"));
|
||||
} else {
|
||||
assertEquals(1L, (long) newCounts.get("Patient"));
|
||||
}
|
||||
|
||||
assertEquals((long) oldCounts.get("Observation"), (long) newCounts.get("Observation"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHistory() throws Exception {
|
||||
Date start = new Date();
|
||||
Thread.sleep(10);
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("testHistory");
|
||||
patient.addName().addFamily("Tester").addGiven("Joe");
|
||||
IdDt pid = ourPatientDao.create(patient).getId().toVersionless();
|
||||
|
||||
Thread.sleep(10);
|
||||
IdDt newpid = ourPatientDao.update(patient, pid).getId();
|
||||
|
||||
Thread.sleep(10);
|
||||
IdDt newpid2 = ourPatientDao.update(patient, pid).getId();
|
||||
|
||||
Thread.sleep(10);
|
||||
IdDt newpid3 = ourPatientDao.update(patient, pid).getId();
|
||||
|
||||
IBundleProvider values = ourSystemDao.history(start);
|
||||
assertEquals(4, values.size());
|
||||
|
||||
List<IResource> res = values.getResources(0, 4);
|
||||
assertEquals(newpid3, res.get(0).getId());
|
||||
assertEquals(newpid2, res.get(1).getId());
|
||||
assertEquals(newpid, res.get(2).getId());
|
||||
assertEquals(pid.toUnqualifiedVersionless(), res.get(3).getId().toUnqualifiedVersionless());
|
||||
|
||||
Location loc = new Location();
|
||||
loc.getAddress().addLine("AAA");
|
||||
IdDt lid = ourLocationDao.create(loc).getId();
|
||||
|
||||
Location loc2 = new Location();
|
||||
loc2.getAddress().addLine("AAA");
|
||||
ourLocationDao.create(loc2).getId();
|
||||
|
||||
Thread.sleep(2000);
|
||||
|
||||
values = ourLocationDao.history(start);
|
||||
assertEquals(2, values.size());
|
||||
|
||||
values = ourLocationDao.history(lid.getIdPartAsLong(), start);
|
||||
assertEquals(1, values.size());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPersistWithSimpleLink() {
|
||||
Patient patient = new Patient();
|
||||
patient.setId(new IdDt("Patient/testPersistWithSimpleLinkP01"));
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("testPersistWithSimpleLinkP01");
|
||||
patient.addName().addFamily("Tester").addGiven("Joe");
|
||||
|
||||
Observation obs = new Observation();
|
||||
obs.getName().addCoding().setSystem("urn:system").setCode("testPersistWithSimpleLinkO01");
|
||||
obs.setSubject(new ResourceReferenceDt("Patient/testPersistWithSimpleLinkP01"));
|
||||
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) patient, obs));
|
||||
|
||||
String patientId = (patient.getId().getIdPart());
|
||||
String obsId = (obs.getId().getIdPart());
|
||||
|
||||
// assertThat(patientId, greaterThan(0L));
|
||||
// assertEquals(patientVersion, 1L);
|
||||
// assertThat(obsId, greaterThan(patientId));
|
||||
// assertEquals(obsVersion, 1L);
|
||||
|
||||
// Try to search
|
||||
|
||||
IBundleProvider obsResults = ourObservationDao.search(Observation.SP_NAME, new IdentifierDt("urn:system", "testPersistWithSimpleLinkO01"));
|
||||
assertEquals(1, obsResults.size());
|
||||
|
||||
IBundleProvider patResults = ourPatientDao.search(Patient.SP_IDENTIFIER, new IdentifierDt("urn:system", "testPersistWithSimpleLinkP01"));
|
||||
assertEquals(1, obsResults.size());
|
||||
|
||||
IdDt foundPatientId = patResults.getResources(0, 1).get(0).getId();
|
||||
ResourceReferenceDt subject = obs.getSubject();
|
||||
assertEquals(foundPatientId.getIdPart(), subject.getReference().getIdPart());
|
||||
|
||||
// Update
|
||||
|
||||
patient = (Patient) patResults.getResources(0, 1).get(0);
|
||||
obs = (Observation) obsResults.getResources(0, 1).get(0);
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("testPersistWithSimpleLinkP02");
|
||||
obs.getName().addCoding().setSystem("urn:system").setCode("testPersistWithSimpleLinkO02");
|
||||
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) patient, obs));
|
||||
|
||||
String patientId2 = (patient.getId().getIdPart());
|
||||
String patientVersion2 = (patient.getId().getVersionIdPart());
|
||||
String obsId2 = (obs.getId().getIdPart());
|
||||
String obsVersion2 = (obs.getId().getVersionIdPart());
|
||||
|
||||
assertEquals(patientId, patientId2);
|
||||
assertEquals(patientVersion2, "2");
|
||||
assertEquals(obsId, obsId2);
|
||||
assertEquals(obsVersion2, "2");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPersistWithUnknownId() {
|
||||
Observation obs = new Observation();
|
||||
obs.getName().addCoding().setSystem("urn:system").setCode("testPersistWithSimpleLinkO01");
|
||||
obs.setSubject(new ResourceReferenceDt("Patient/999998888888"));
|
||||
|
||||
try {
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) obs));
|
||||
} catch (InvalidRequestException e) {
|
||||
assertThat(e.getMessage(), containsString("Resource Patient/999998888888 not found, specified in path: Observation.subject"));
|
||||
}
|
||||
|
||||
obs = new Observation();
|
||||
obs.getName().addCoding().setSystem("urn:system").setCode("testPersistWithSimpleLinkO01");
|
||||
obs.setSubject(new ResourceReferenceDt("Patient/1.2.3.4"));
|
||||
|
||||
try {
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) obs));
|
||||
} catch (InvalidRequestException e) {
|
||||
assertThat(e.getMessage(), containsString("Resource Patient/1.2.3.4 not found, specified in path: Observation.subject"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTagOperationss() throws Exception {
|
||||
|
||||
TagList preSystemTl = ourSystemDao.getAllTags();
|
||||
|
||||
TagList tl1 = new TagList();
|
||||
tl1.addTag("testGetAllTagsScheme1", "testGetAllTagsTerm1", "testGetAllTagsLabel1");
|
||||
Patient p1 = new Patient();
|
||||
p1.addIdentifier().setSystem("foo").setValue("testGetAllTags01");
|
||||
ResourceMetadataKeyEnum.TAG_LIST.put(p1, tl1);
|
||||
ourPatientDao.create(p1);
|
||||
|
||||
TagList tl2 = new TagList();
|
||||
tl2.addTag("testGetAllTagsScheme2", "testGetAllTagsTerm2", "testGetAllTagsLabel2");
|
||||
Observation o1 = new Observation();
|
||||
o1.getName().setText("testGetAllTags02");
|
||||
ResourceMetadataKeyEnum.TAG_LIST.put(o1, tl2);
|
||||
IdDt o1id = ourObservationDao.create(o1).getId();
|
||||
assertTrue(o1id.getVersionIdPart() != null);
|
||||
|
||||
TagList postSystemTl = ourSystemDao.getAllTags();
|
||||
assertEquals(preSystemTl.size() + 2, postSystemTl.size());
|
||||
assertEquals("testGetAllTagsLabel1", postSystemTl.getTag("testGetAllTagsScheme1", "testGetAllTagsTerm1").getLabel());
|
||||
|
||||
TagList tags = ourPatientDao.getAllResourceTags();
|
||||
assertEquals("testGetAllTagsLabel1", tags.getTag("testGetAllTagsScheme1", "testGetAllTagsTerm1").getLabel());
|
||||
assertNull(tags.getTag("testGetAllTagsScheme2", "testGetAllTagsTerm2"));
|
||||
|
||||
TagList tags2 = ourObservationDao.getTags(o1id);
|
||||
assertNull(tags2.getTag("testGetAllTagsScheme1", "testGetAllTagsTerm1"));
|
||||
assertEquals("testGetAllTagsLabel2", tags2.getTag("testGetAllTagsScheme2", "testGetAllTagsTerm2").getLabel());
|
||||
|
||||
o1.getResourceMetadata().remove(ResourceMetadataKeyEnum.TAG_LIST);
|
||||
IdDt o1id2 = ourObservationDao.update(o1, o1id).getId();
|
||||
assertTrue(o1id2.getVersionIdPart() != null);
|
||||
|
||||
tags2 = ourObservationDao.getTags(o1id);
|
||||
assertNull(tags2.getTag("testGetAllTagsScheme1", "testGetAllTagsTerm1"));
|
||||
assertEquals("testGetAllTagsLabel2", tags2.getTag("testGetAllTagsScheme2", "testGetAllTagsTerm2").getLabel());
|
||||
|
||||
tags2 = ourObservationDao.getTags(o1id2);
|
||||
assertNull(tags2.getTag("testGetAllTagsScheme1", "testGetAllTagsTerm1"));
|
||||
assertNotNull(tags2.getTag("testGetAllTagsScheme2", "testGetAllTagsTerm2"));
|
||||
|
||||
/*
|
||||
* Remove a tag from a version
|
||||
*/
|
||||
|
||||
ourObservationDao.removeTag(o1id2, "testGetAllTagsScheme2", "testGetAllTagsTerm2");
|
||||
tags2 = ourObservationDao.getTags(o1id2);
|
||||
assertNull(tags2.getTag("testGetAllTagsScheme1", "testGetAllTagsTerm1"));
|
||||
assertNull(tags2.getTag("testGetAllTagsScheme2", "testGetAllTagsTerm2"));
|
||||
|
||||
tags2 = ourObservationDao.getTags(o1id);
|
||||
assertNull(tags2.getTag("testGetAllTagsScheme1", "testGetAllTagsTerm1"));
|
||||
assertNotNull(tags2.getTag("testGetAllTagsScheme2", "testGetAllTagsTerm2"));
|
||||
|
||||
/*
|
||||
* Add a tag
|
||||
*/
|
||||
ourObservationDao.addTag(o1id2, "testGetAllTagsScheme3", "testGetAllTagsTerm3", "testGetAllTagsLabel3");
|
||||
tags2 = ourObservationDao.getTags(o1id2);
|
||||
assertNull(tags2.getTag("testGetAllTagsScheme1", "testGetAllTagsTerm1"));
|
||||
assertNull(tags2.getTag("testGetAllTagsScheme2", "testGetAllTagsTerm2"));
|
||||
assertNotNull(tags2.getTag("testGetAllTagsScheme3", "testGetAllTagsTerm3"));
|
||||
assertEquals("testGetAllTagsLabel3", tags2.getTag("testGetAllTagsScheme3", "testGetAllTagsTerm3").getLabel());
|
||||
|
||||
tags2 = ourObservationDao.getTags(o1id);
|
||||
assertNull(tags2.getTag("testGetAllTagsScheme1", "testGetAllTagsTerm1"));
|
||||
assertNotNull(tags2.getTag("testGetAllTagsScheme2", "testGetAllTagsTerm2"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionCreateMatchUrlWithOneMatch() {
|
||||
String methodName = "testTransactionCreateMatchUrlWithOneMatch";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.setId("Patient/" + methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.CREATE);
|
||||
ResourceMetadataKeyEnum.LINK_SEARCH.put(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient/" + methodName);
|
||||
|
||||
List<IResource> resp = ourSystemDao.transaction(Arrays.asList((IResource) p, o));
|
||||
assertEquals(3, resp.size());
|
||||
|
||||
p = (Patient) resp.get(1);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.NOOP, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(p));
|
||||
assertEquals(id, p.getId());
|
||||
|
||||
o = (Observation) resp.get(2);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.CREATE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(o));
|
||||
assertEquals(id.toVersionless(), o.getSubject().getReference());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionCreateMatchUrlWithTwoMatch() {
|
||||
String methodName = "testTransactionCreateMatchUrlWithTwoMatch";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.CREATE);
|
||||
ResourceMetadataKeyEnum.LINK_SEARCH.put(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient/" + methodName);
|
||||
|
||||
try {
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) p, o));
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertThat(e.getMessage(), containsString("with match URL \"Patient"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionCreateMatchUrlWithZeroMatch() {
|
||||
String methodName = "testTransactionCreateMatchUrlWithZeroMatch";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.CREATE);
|
||||
ResourceMetadataKeyEnum.LINK_SEARCH.put(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient/" + methodName);
|
||||
|
||||
List<IResource> resp = ourSystemDao.transaction(Arrays.asList((IResource) p, o));
|
||||
assertEquals(3, resp.size());
|
||||
|
||||
p = (Patient) resp.get(1);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.CREATE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(p));
|
||||
assertThat(p.getId().getIdPart(), not(containsString("test")));
|
||||
|
||||
o = (Observation) resp.get(2);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.CREATE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(o));
|
||||
assertEquals(p.getId().toVersionless(), o.getSubject().getReference());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionCreateNoMatchUrl() {
|
||||
String methodName = "testTransactionCreateNoMatchUrl";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.setId("Patient/" + methodName);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.CREATE);
|
||||
|
||||
List<IResource> resp = ourSystemDao.transaction(Arrays.asList((IResource) p));
|
||||
assertEquals(2, resp.size());
|
||||
p = (Patient) resp.get(1);
|
||||
|
||||
assertEquals(BundleEntryTransactionOperationEnum.CREATE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(p));
|
||||
assertThat(p.getId().getIdPart(), not(containsString("test")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionDeleteMatchUrlWithOneMatch() {
|
||||
String methodName = "testTransactionDeleteMatchUrlWithOneMatch";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.DELETE);
|
||||
ResourceMetadataKeyEnum.LINK_SEARCH.put(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
List<IResource> resp = ourSystemDao.transaction(Arrays.asList((IResource) p));
|
||||
assertEquals(2, resp.size());
|
||||
|
||||
p = (Patient) resp.get(1);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.DELETE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(p));
|
||||
assertThat(p.getId().toVersionless().toString(), not(containsString("test")));
|
||||
assertEquals(id.toVersionless(), p.getId().toVersionless());
|
||||
assertNotEquals(id, p.getId());
|
||||
assertThat(p.getId().toString(), endsWith("/_history/2"));
|
||||
|
||||
try {
|
||||
ourPatientDao.read(id.toVersionless());
|
||||
fail();
|
||||
} catch (ResourceGoneException e) {
|
||||
// ok
|
||||
}
|
||||
|
||||
try {
|
||||
ourPatientDao.read(new IdDt("Patient/" + methodName));
|
||||
fail();
|
||||
} catch (ResourceNotFoundException e) {
|
||||
// ok
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionDeleteMatchUrlWithTwoMatch() {
|
||||
String methodName = "testTransactionDeleteMatchUrlWithTwoMatch";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.DELETE);
|
||||
ResourceMetadataKeyEnum.LINK_SEARCH.put(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient/" + methodName);
|
||||
|
||||
try {
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) p, o));
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertThat(e.getMessage(), containsString("with match URL \"Patient"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionDeleteMatchUrlWithZeroMatch() {
|
||||
String methodName = "testTransactionDeleteMatchUrlWithZeroMatch";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName + "ZZZ");
|
||||
p.addName().addFamily("Hello");
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
|
||||
p = new Patient();
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
IdDt id2 = ourPatientDao.create(p).getId();
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.DELETE);
|
||||
ResourceMetadataKeyEnum.LINK_SEARCH.put(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
List<IResource> resp = ourSystemDao.transaction(Arrays.asList((IResource) p));
|
||||
assertEquals(2, resp.size());
|
||||
|
||||
p = (Patient) resp.get(1);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.DELETE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(p));
|
||||
assertThat(p.getId().toVersionless().toString(), (containsString("test")));
|
||||
assertThat(p.getId().toString(), endsWith("/_history/2"));
|
||||
assertEquals(id2.toVersionless(), p.getId().toVersionless());
|
||||
assertNotEquals(id2, p.getId());
|
||||
|
||||
try {
|
||||
ourPatientDao.read(id2.toVersionless());
|
||||
fail();
|
||||
} catch (ResourceGoneException e) {
|
||||
// ok
|
||||
}
|
||||
|
||||
Patient found = ourPatientDao.read(id);
|
||||
assertEquals(id, found.getId());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionDeleteNoMatchUrl() {
|
||||
String methodName = "testTransactionDeleteNoMatchUrl";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.setId("Patient/" + methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.DELETE);
|
||||
|
||||
List<IResource> resp = ourSystemDao.transaction(Arrays.asList((IResource) p));
|
||||
assertEquals(2, resp.size());
|
||||
|
||||
p = (Patient) resp.get(1);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.DELETE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(p));
|
||||
assertNotNull(ResourceMetadataKeyEnum.DELETED_AT.get(p).getValue());
|
||||
|
||||
try {
|
||||
ourPatientDao.read(id.toVersionless());
|
||||
fail();
|
||||
} catch (ResourceGoneException e) {
|
||||
// ok
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = InvalidRequestException.class)
|
||||
public void testTransactionFailsWithDuplicateIds() {
|
||||
Patient patient1 = new Patient();
|
||||
patient1.setId(new IdDt("Patient/testTransactionFailsWithDusplicateIds"));
|
||||
patient1.addIdentifier().setSystem("urn:system").setValue("testPersistWithSimpleLinkP01");
|
||||
|
||||
Patient patient2 = new Patient();
|
||||
patient2.setId(new IdDt("Patient/testTransactionFailsWithDusplicateIds"));
|
||||
patient2.addIdentifier().setSystem("urn:system").setValue("testPersistWithSimpleLinkP02");
|
||||
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) patient1, patient2));
|
||||
}
|
||||
|
||||
// @Test TODO: re-enable
|
||||
public void testTransactionFromBundle() throws Exception {
|
||||
|
||||
InputStream bundleRes = FhirSystemDaoTest.class.getResourceAsStream("/bundle.json");
|
||||
Bundle bundle = ourFhirContext.newJsonParser().parseBundle(new InputStreamReader(bundleRes));
|
||||
List<IResource> res = bundle.toListOfResources();
|
||||
|
||||
ourSystemDao.transaction(res);
|
||||
|
||||
Patient p1 = (Patient) res.get(0);
|
||||
String id = p1.getId().getValue();
|
||||
ourLog.info("ID: {}", id);
|
||||
assertThat(id, not(containsString("5556918")));
|
||||
assertThat(id, not(equalToIgnoringCase("")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionUpdateMatchUrlWithOneMatch() {
|
||||
String methodName = "testTransactionUpdateMatchUrlWithOneMatch";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.UPDATE);
|
||||
ResourceMetadataKeyEnum.LINK_SEARCH.put(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient/" + methodName);
|
||||
|
||||
List<IResource> resp = ourSystemDao.transaction(Arrays.asList((IResource) p, o));
|
||||
assertEquals(3, resp.size());
|
||||
|
||||
p = (Patient) resp.get(1);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.UPDATE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(p));
|
||||
assertThat(p.getId().toVersionless().toString(), not(containsString("test")));
|
||||
assertEquals(id.toVersionless(), p.getId().toVersionless());
|
||||
assertNotEquals(id, p.getId());
|
||||
assertThat(p.getId().toString(), endsWith("/_history/2"));
|
||||
|
||||
o = (Observation) resp.get(2);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.CREATE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(o));
|
||||
assertEquals(id.toVersionless(), o.getSubject().getReference());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionUpdateMatchUrlWithTwoMatch() {
|
||||
String methodName = "testTransactionUpdateMatchUrlWithTwoMatch";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.UPDATE);
|
||||
ResourceMetadataKeyEnum.LINK_SEARCH.put(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient/" + methodName);
|
||||
|
||||
try {
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) p, o));
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertThat(e.getMessage(), containsString("with match URL \"Patient"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionUpdateMatchUrlWithZeroMatch() {
|
||||
String methodName = "testTransactionUpdateMatchUrlWithZeroMatch";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addName().addFamily("Hello");
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId(id);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.UPDATE);
|
||||
ResourceMetadataKeyEnum.LINK_SEARCH.put(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference(id);
|
||||
|
||||
List<IResource> resp = ourSystemDao.transaction(Arrays.asList((IResource) p, o));
|
||||
assertEquals(3, resp.size());
|
||||
|
||||
p = (Patient) resp.get(1);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.UPDATE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(p));
|
||||
assertEquals(id.toVersionless(), p.getId().toVersionless());
|
||||
assertNotEquals(id, p.getId());
|
||||
assertThat(p.getId().toString(), endsWith("/_history/2"));
|
||||
|
||||
o = (Observation) resp.get(2);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.CREATE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(o));
|
||||
assertEquals(p.getId().toVersionless(), o.getSubject().getReference());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionUpdateMatchUrlWithZeroMatchAndNotPreExisting() {
|
||||
String methodName = "testTransactionUpdateMatchUrlWithZeroMatchAndNotPreExisting";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.UPDATE);
|
||||
ResourceMetadataKeyEnum.LINK_SEARCH.put(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient/" + methodName);
|
||||
|
||||
List<IResource> resp = ourSystemDao.transaction(Arrays.asList((IResource) p, o));
|
||||
assertEquals(3, resp.size());
|
||||
|
||||
p = (Patient) resp.get(1);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.CREATE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(p));
|
||||
assertThat(p.getId().toVersionless().toString(), containsString("test"));
|
||||
assertThat(p.getId().toString(), endsWith("/_history/1"));
|
||||
|
||||
o = (Observation) resp.get(2);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.CREATE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(o));
|
||||
assertEquals(p.getId().toVersionless(), o.getSubject().getReference());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionUpdateNoMatchUrl() {
|
||||
String methodName = "testTransactionUpdateNoMatchUrl";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.setId("Patient/" + methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.UPDATE);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient/" + methodName);
|
||||
|
||||
List<IResource> resp = ourSystemDao.transaction(Arrays.asList((IResource) p, o));
|
||||
assertEquals(3, resp.size());
|
||||
|
||||
p = (Patient) resp.get(1);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.UPDATE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(p));
|
||||
assertThat(p.getId().toVersionless().toString(), containsString("test"));
|
||||
assertEquals(id.toVersionless(), p.getId().toVersionless());
|
||||
assertNotEquals(id, p.getId());
|
||||
assertThat(p.getId().toString(), endsWith("/_history/2"));
|
||||
|
||||
o = (Observation) resp.get(2);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.CREATE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(o));
|
||||
assertEquals(id.toVersionless(), o.getSubject().getReference());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionUpdateNoOperationSpecified() throws Exception {
|
||||
List<IResource> res = new ArrayList<IResource>();
|
||||
|
||||
Patient p1 = new Patient();
|
||||
p1.getId().setValue("testTransactionWithUpdateXXX01");
|
||||
p1.addIdentifier().setSystem("system").setValue("testTransactionWithUpdate01");
|
||||
res.add(p1);
|
||||
|
||||
Observation p2 = new Observation();
|
||||
p2.getId().setValue("testTransactionWithUpdateXXX02");
|
||||
p2.getIdentifier().setSystem("system").setValue("testTransactionWithUpdate02");
|
||||
p2.setSubject(new ResourceReferenceDt("Patient/testTransactionWithUpdateXXX01"));
|
||||
res.add(p2);
|
||||
|
||||
ourSystemDao.transaction(res);
|
||||
|
||||
assertFalse(p1.getId().isEmpty());
|
||||
assertFalse(p2.getId().isEmpty());
|
||||
assertEquals("testTransactionWithUpdateXXX01", p1.getId().getIdPart());
|
||||
assertEquals("testTransactionWithUpdateXXX02", p2.getId().getIdPart());
|
||||
assertNotEquals("testTransactionWithUpdateXXX01", p1.getId().getVersionIdPart());
|
||||
assertNotEquals("testTransactionWithUpdateXXX02", p2.getId().getVersionIdPart());
|
||||
assertEquals(p1.getId().toUnqualified().toVersionless(), p2.getSubject().getReference());
|
||||
|
||||
IdDt p1id = p1.getId().toUnqualified().toVersionless();
|
||||
IdDt p1idWithVer = p1.getId().toUnqualified();
|
||||
IdDt p2id = p2.getId().toUnqualified().toVersionless();
|
||||
IdDt p2idWithVer = p2.getId().toUnqualified();
|
||||
|
||||
/*
|
||||
* Make some changes
|
||||
*/
|
||||
|
||||
res = new ArrayList<IResource>();
|
||||
|
||||
p1 = new Patient();
|
||||
p1.getId().setValue("testTransactionWithUpdateXXX01");
|
||||
p1.addIdentifier().setSystem("system").setValue("testTransactionWithUpdate01");
|
||||
p1.addName().addFamily("Name1");
|
||||
res.add(p1);
|
||||
|
||||
p2 = new Observation();
|
||||
p2.getId().setValue("testTransactionWithUpdateXXX02");
|
||||
p2.getIdentifier().setSystem("system").setValue("testTransactionWithUpdate02");
|
||||
p2.setSubject(new ResourceReferenceDt("Patient/testTransactionWithUpdateXXX01"));
|
||||
p2.addReferenceRange().setHigh(new QuantityDt(123L));
|
||||
res.add(p2);
|
||||
|
||||
List<IResource> results = ourSystemDao.transaction(res);
|
||||
|
||||
assertEquals(p1id, results.get(1).getId().toUnqualified().toVersionless());
|
||||
assertEquals(p2id, results.get(2).getId().toUnqualified().toVersionless());
|
||||
assertNotEquals(p1idWithVer, results.get(1).getId().toUnqualified());
|
||||
assertNotEquals(p2idWithVer, results.get(2).getId().toUnqualified());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Issue #55
|
||||
*/
|
||||
@Test
|
||||
public void testTransactionWithCidIds() throws Exception {
|
||||
List<IResource> res = new ArrayList<IResource>();
|
||||
|
||||
Patient p1 = new Patient();
|
||||
p1.setId("cid:patient1");
|
||||
p1.addIdentifier().setSystem("system").setValue("testTransactionWithCidIds01");
|
||||
res.add(p1);
|
||||
|
||||
Observation o1 = new Observation();
|
||||
o1.setId("cid:observation1");
|
||||
o1.getIdentifier().setSystem("system").setValue("testTransactionWithCidIds02");
|
||||
o1.setSubject(new ResourceReferenceDt("Patient/cid:patient1"));
|
||||
res.add(o1);
|
||||
|
||||
Observation o2 = new Observation();
|
||||
o2.setId("cid:observation2");
|
||||
o2.getIdentifier().setSystem("system").setValue("testTransactionWithCidIds03");
|
||||
o2.setSubject(new ResourceReferenceDt("Patient/cid:patient1"));
|
||||
res.add(o2);
|
||||
|
||||
ourSystemDao.transaction(res);
|
||||
|
||||
assertTrue(p1.getId().getValue(), p1.getId().getIdPart().matches("^[0-9]+$"));
|
||||
assertTrue(o1.getId().getValue(), o1.getId().getIdPart().matches("^[0-9]+$"));
|
||||
assertTrue(o2.getId().getValue(), o2.getId().getIdPart().matches("^[0-9]+$"));
|
||||
|
||||
assertThat(o1.getSubject().getReference().getValue(), endsWith("Patient/" + p1.getId().getIdPart()));
|
||||
assertThat(o2.getSubject().getReference().getValue(), endsWith("Patient/" + p1.getId().getIdPart()));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionWithDelete() throws Exception {
|
||||
|
||||
/*
|
||||
* Create 3
|
||||
*/
|
||||
|
||||
List<IResource> res;
|
||||
res = new ArrayList<IResource>();
|
||||
|
||||
Patient p1 = new Patient();
|
||||
p1.addIdentifier().setSystem("urn:system").setValue("testTransactionWithDelete");
|
||||
res.add(p1);
|
||||
|
||||
Patient p2 = new Patient();
|
||||
p2.addIdentifier().setSystem("urn:system").setValue("testTransactionWithDelete");
|
||||
res.add(p2);
|
||||
|
||||
Patient p3 = new Patient();
|
||||
p3.addIdentifier().setSystem("urn:system").setValue("testTransactionWithDelete");
|
||||
res.add(p3);
|
||||
|
||||
ourSystemDao.transaction(res);
|
||||
|
||||
/*
|
||||
* Verify
|
||||
*/
|
||||
|
||||
IBundleProvider results = ourPatientDao.search(Patient.SP_IDENTIFIER, new TokenParam("urn:system", "testTransactionWithDelete"));
|
||||
assertEquals(3, results.size());
|
||||
|
||||
/*
|
||||
* Now delete 2
|
||||
*/
|
||||
|
||||
res = new ArrayList<IResource>();
|
||||
List<IResource> existing = results.getResources(0, 3);
|
||||
|
||||
p1 = new Patient();
|
||||
p1.setId(existing.get(0).getId());
|
||||
ResourceMetadataKeyEnum.DELETED_AT.put(p1, InstantDt.withCurrentTime());
|
||||
res.add(p1);
|
||||
|
||||
p2 = new Patient();
|
||||
p2.setId(existing.get(1).getId());
|
||||
ResourceMetadataKeyEnum.DELETED_AT.put(p2, InstantDt.withCurrentTime());
|
||||
res.add(p2);
|
||||
|
||||
ourSystemDao.transaction(res);
|
||||
|
||||
/*
|
||||
* Verify
|
||||
*/
|
||||
|
||||
IBundleProvider results2 = ourPatientDao.search(Patient.SP_IDENTIFIER, new TokenParam("urn:system", "testTransactionWithDelete"));
|
||||
assertEquals(1, results2.size());
|
||||
List<IResource> existing2 = results2.getResources(0, 1);
|
||||
assertEquals(existing2.get(0).getId(), existing.get(2).getId());
|
||||
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() {
|
||||
ourCtx.close();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@BeforeClass
|
||||
public static void beforeClass() {
|
||||
ourCtx = new ClassPathXmlApplicationContext("hapi-fhir-server-resourceproviders-dstu1.xml", "fhir-jpabase-spring-test-config.xml");
|
||||
ourFhirContext = ourCtx.getBean(FhirContext.class);
|
||||
ourPatientDao = ourCtx.getBean("myPatientDaoDstu1", IFhirResourceDao.class);
|
||||
ourObservationDao = ourCtx.getBean("myObservationDaoDstu1", IFhirResourceDao.class);
|
||||
ourLocationDao = ourCtx.getBean("myLocationDaoDstu1", IFhirResourceDao.class);
|
||||
ourSystemDao = ourCtx.getBean("mySystemDaoDstu1", IFhirSystemDao.class);
|
||||
}
|
||||
|
||||
}
|
|
@ -19,7 +19,6 @@ import org.springframework.context.support.ClassPathXmlApplicationContext;
|
|||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
|
||||
import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,74 +0,0 @@
|
|||
package ca.uhn.fhir.rest.client;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import org.apache.commons.io.input.ReaderInputStream;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.ProtocolVersion;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
import org.apache.http.message.BasicHeader;
|
||||
import org.apache.http.message.BasicStatusLine;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
|
||||
public class GenericClientTestDev {
|
||||
private static FhirContext ourCtx;
|
||||
private HttpClient myHttpClient;
|
||||
private HttpResponse myHttpResponse;
|
||||
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() {
|
||||
ourCtx = FhirContext.forDstu2();
|
||||
}
|
||||
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
myHttpClient = mock(HttpClient.class, new ReturnsDeepStubs());
|
||||
ourCtx.getRestfulClientFactory().setHttpClient(myHttpClient);
|
||||
ourCtx.getRestfulClientFactory().setServerValidationModeEnum(ServerValidationModeEnum.NEVER);
|
||||
myHttpResponse = mock(HttpResponse.class, new ReturnsDeepStubs());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSearchByString() 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\"}]}}]}";
|
||||
|
||||
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_JSON + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
//@formatter:off
|
||||
Bundle response = client.search()
|
||||
.forResource("Patient")
|
||||
.where(Patient.NAME.matches().value("james"))
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
assertEquals("http://example.com/fhir/Patient?name=james", capt.getValue().getURI().toString());
|
||||
assertEquals(Patient.class, response.getEntries().get(0).getResource().getClass());
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,212 @@
|
|||
package ca.uhn.fhir.rest.client;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.io.input.ReaderInputStream;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.ProtocolVersion;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
|
||||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
import org.apache.http.message.BasicHeader;
|
||||
import org.apache.http.message.BasicStatusLine;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
|
||||
public class GenericClientTestDstu2 {
|
||||
private static FhirContext ourCtx;
|
||||
private HttpClient myHttpClient;
|
||||
private HttpResponse myHttpResponse;
|
||||
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() {
|
||||
ourCtx = FhirContext.forDstu2();
|
||||
}
|
||||
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
myHttpClient = mock(HttpClient.class, new ReturnsDeepStubs());
|
||||
ourCtx.getRestfulClientFactory().setHttpClient(myHttpClient);
|
||||
ourCtx.getRestfulClientFactory().setServerValidationModeEnum(ServerValidationModeEnum.NEVER);
|
||||
myHttpResponse = mock(HttpResponse.class, new ReturnsDeepStubs());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSearchByString() 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\"}]}}]}";
|
||||
|
||||
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_JSON + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
//@formatter:off
|
||||
Bundle response = client.search()
|
||||
.forResource("Patient")
|
||||
.where(Patient.NAME.matches().value("james"))
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
assertEquals("http://example.com/fhir/Patient?name=james", capt.getValue().getURI().toString());
|
||||
assertEquals(Patient.class, response.getEntries().get(0).getResource().getClass());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteConditional() throws Exception {
|
||||
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), Constants.STATUS_HTTP_204_NO_CONTENT, ""));
|
||||
// when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_TEXT + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).then(new Answer<ReaderInputStream>() {
|
||||
@Override
|
||||
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
return new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8"));
|
||||
}
|
||||
});
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
int idx = 0;
|
||||
|
||||
client.delete().resourceById(new IdDt("Patient/123")).execute();
|
||||
assertEquals("DELETE", capt.getAllValues().get(idx).getMethod());
|
||||
assertEquals("http://example.com/fhir/Patient/123", capt.getAllValues().get(idx).getURI().toString());
|
||||
idx++;
|
||||
|
||||
client.delete().resourceConditionalByUrl("Patient?name=foo").execute();
|
||||
assertEquals("DELETE", capt.getAllValues().get(idx).getMethod());
|
||||
assertEquals("http://example.com/fhir/Patient?name=foo", capt.getAllValues().get(idx).getURI().toString());
|
||||
idx++;
|
||||
|
||||
client.delete().resourceConditionalByType("Patient").where(Patient.NAME.matches().value("foo")).execute();
|
||||
assertEquals("DELETE", capt.getAllValues().get(idx).getMethod());
|
||||
assertEquals("http://example.com/fhir/Patient?name=foo", capt.getAllValues().get(idx).getURI().toString());
|
||||
idx++;
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateConditional() throws Exception {
|
||||
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), Constants.STATUS_HTTP_204_NO_CONTENT, ""));
|
||||
when(myHttpResponse.getEntity().getContent()).then(new Answer<ReaderInputStream>() {
|
||||
@Override
|
||||
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
return new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8"));
|
||||
}
|
||||
});
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
int idx = 0;
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addName().addFamily("FOOFAMILY");
|
||||
|
||||
client.create().resource(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());
|
||||
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=foo", 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());
|
||||
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=foo", capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_IF_NONE_EXIST).getValue());
|
||||
assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod());
|
||||
idx++;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testUpdateConditional() throws Exception {
|
||||
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), Constants.STATUS_HTTP_204_NO_CONTENT, ""));
|
||||
when(myHttpResponse.getEntity().getContent()).then(new Answer<ReaderInputStream>() {
|
||||
@Override
|
||||
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
return new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8"));
|
||||
}
|
||||
});
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
int idx = 0;
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addName().addFamily("FOOFAMILY");
|
||||
|
||||
client.update().resource(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());
|
||||
assertThat(extractBody(capt, idx), containsString("<family value=\"FOOFAMILY\"/>"));
|
||||
assertEquals("PUT", capt.getAllValues().get(idx).getRequestLine().getMethod());
|
||||
assertEquals("http://example.com/fhir/Patient?name=foo", 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());
|
||||
assertThat(extractBody(capt, idx), containsString("<family value=\"FOOFAMILY\"/>"));
|
||||
assertEquals("PUT", capt.getAllValues().get(idx).getRequestLine().getMethod());
|
||||
assertEquals("http://example.com/fhir/Patient?name=foo", capt.getAllValues().get(idx).getURI().toString());
|
||||
idx++;
|
||||
|
||||
client.update().resource(p).conditional().where(Patient.NAME.matches().value("foo")).and(Patient.ADDRESS.matches().value("AAA|BBB")).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=foo&address=AAA%5C%7CBBB", capt.getAllValues().get(idx).getURI().toString());
|
||||
idx++;
|
||||
|
||||
client.update().resource(ourCtx.newXmlParser().encodeResourceToString(p)).conditional().where(Patient.NAME.matches().value("foo")).and(Patient.ADDRESS.matches().value("AAA|BBB")).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=foo&address=AAA%5C%7CBBB", capt.getAllValues().get(idx).getURI().toString());
|
||||
idx++;
|
||||
|
||||
}
|
||||
|
||||
private String extractBody(ArgumentCaptor<HttpUriRequest> capt, int count) throws IOException {
|
||||
String body = IOUtils.toString(((HttpEntityEnclosingRequestBase) capt.getAllValues().get(count)).getEntity().getContent(), "UTF-8");
|
||||
return body;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,133 @@
|
|||
package ca.uhn.fhir.rest.server;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpPut;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.servlet.ServletHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.model.dstu2.resource.DiagnosticOrder;
|
||||
import ca.uhn.fhir.model.dstu2.resource.DiagnosticReport;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Observation;
|
||||
import ca.uhn.fhir.model.dstu2.resource.OperationOutcome;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Organization;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
||||
import ca.uhn.fhir.rest.annotation.Update;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.util.PortUtil;
|
||||
|
||||
/**
|
||||
* Created by dsotnikov on 2/25/2014.
|
||||
*/
|
||||
public class UpdateConditionalTest {
|
||||
private static CloseableHttpClient ourClient;
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(UpdateConditionalTest.class);
|
||||
private static int ourPort;
|
||||
private static Server ourServer;
|
||||
|
||||
@Test
|
||||
public void testUpdate() throws Exception {
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setValue("002");
|
||||
|
||||
HttpPut httpPost = new HttpPut("http://localhost:" + ourPort + "/Patient/001");
|
||||
httpPost.setEntity(new StringEntity(new FhirContext().newXmlParser().encodeResourceToString(patient), ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||
|
||||
HttpResponse status = ourClient.execute(httpPost);
|
||||
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
ourLog.info("Response was:\n{}", responseContent);
|
||||
|
||||
OperationOutcome oo = new FhirContext().newXmlParser().parseResource(OperationOutcome.class, responseContent);
|
||||
assertEquals("OODETAILS", oo.getIssueFirstRep().getDetails());
|
||||
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
assertEquals("http://localhost:" + ourPort + "/Patient/001/_history/002", status.getFirstHeader("location").getValue());
|
||||
assertEquals("http://localhost:" + ourPort + "/Patient/001/_history/002", status.getFirstHeader("content-location").getValue());
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() throws Exception {
|
||||
ourServer.stop();
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception {
|
||||
ourPort = PortUtil.findFreePort();
|
||||
ourServer = new Server(ourPort);
|
||||
|
||||
PatientProvider patientProvider = new PatientProvider();
|
||||
|
||||
ServletHandler proxyHandler = new ServletHandler();
|
||||
RestfulServer servlet = new RestfulServer();
|
||||
servlet.setResourceProviders(patientProvider);
|
||||
ServletHolder servletHolder = new ServletHolder(servlet);
|
||||
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
||||
ourServer.setHandler(proxyHandler);
|
||||
ourServer.start();
|
||||
|
||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
||||
HttpClientBuilder builder = HttpClientBuilder.create();
|
||||
builder.setConnectionManager(connectionManager);
|
||||
ourClient = builder.build();
|
||||
|
||||
}
|
||||
|
||||
private static String ourLastConditionalUrl;
|
||||
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
ourLastConditionalUrl=null;
|
||||
}
|
||||
|
||||
public static class PatientProvider implements IResourceProvider {
|
||||
|
||||
@Override
|
||||
public Class<? extends IResource> getResourceType() {
|
||||
return Patient.class;
|
||||
}
|
||||
|
||||
|
||||
@Update()
|
||||
public MethodOutcome updatePatient(@IdParam IdDt theId, @ResourceParam Patient thePatient) {
|
||||
IdDt id = theId.withVersion(thePatient.getIdentifierFirstRep().getValue());
|
||||
OperationOutcome oo = new OperationOutcome();
|
||||
oo.addIssue().setDetails("OODETAILS");
|
||||
if (theId.getValueAsString().contains("CREATE")) {
|
||||
return new MethodOutcome(id,oo, true);
|
||||
}
|
||||
|
||||
return new MethodOutcome(id,oo);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue