From fc4fb07562a7e8ddffeeb138187e97f79243dbc9 Mon Sep 17 00:00:00 2001
From: James Agnew
Date: Tue, 3 Mar 2015 18:31:01 -0500
Subject: [PATCH] Work on history suport for fluent client
---
.../java/example/GenericClientExample.java | 38 +
hapi-fhir-android/dependency-reduced-pom.xml | 151 ++++
hapi-fhir-android/pom.xml | 58 +-
.../java/ca/uhn/fhir/android/BuiltJarIT.java | 5 +-
.../fhir/model/primitive/Base64BinaryDt.java | 5 +-
.../uhn/fhir/rest/client/GenericClient.java | 734 ++++++++++--------
.../uhn/fhir/rest/client/IGenericClient.java | 30 +-
.../ca/uhn/fhir/rest/gclient/IBaseOn.java | 28 +
.../ca/uhn/fhir/rest/gclient/IHistory.java | 5 +
.../uhn/fhir/rest/gclient/IHistoryTyped.java | 25 +
.../fhir/rest/gclient/IHistoryUntyped.java | 21 +
.../uhn/fhir/rest/gclient/IOperationOn.java | 2 +-
.../fhir/rest/gclient/IOperationTyped.java | 7 +
.../BaseAddOrDeleteTagsMethodBinding.java | 2 +-
.../BaseHttpClientInvocationWithContents.java | 22 +-
.../rest/method/GetTagsMethodBinding.java | 2 +-
.../rest/method/HistoryMethodBinding.java | 14 +-
.../ca/uhn/fhir/rest/server/Constants.java | 6 +-
.../fhir/rest/server/RestfulServerUtils.java | 4 +-
hapi-fhir-jpaserver-base/.classpath | 2 +-
....eclipse.wst.common.project.facet.core.xml | 2 +-
.../fhir/rest/client/GenericClientTest.java | 60 +-
hapi-fhir-structures-dstu2/.gitignore | 1 +
.../rest/client/GenericClientTestDstu2.java | 87 ++-
pom.xml | 2 +-
src/site/xdoc/doc_rest_client.xml | 72 +-
26 files changed, 975 insertions(+), 410 deletions(-)
create mode 100644 hapi-fhir-android/dependency-reduced-pom.xml
create mode 100644 hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IBaseOn.java
create mode 100644 hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IHistory.java
create mode 100644 hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IHistoryTyped.java
create mode 100644 hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IHistoryUntyped.java
create mode 100644 hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IOperationTyped.java
diff --git a/examples/src/main/java/example/GenericClientExample.java b/examples/src/main/java/example/GenericClientExample.java
index 29f62a843df..14e904ae0bc 100644
--- a/examples/src/main/java/example/GenericClientExample.java
+++ b/examples/src/main/java/example/GenericClientExample.java
@@ -14,6 +14,7 @@ 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.model.primitive.InstantDt;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.client.IGenericClient;
import ca.uhn.fhir.rest.method.SearchStyleEnum;
@@ -320,6 +321,43 @@ public class GenericClientExample {
}
+ @SuppressWarnings("unused")
+ public static void history() {
+ IGenericClient client = FhirContext.forDstu2().newRestfulGenericClient("");
+ {
+ Bundle response;
+ // START SNIPPET: historyDstu1
+ response = client
+ .history()
+ .ofServer()
+ .andReturnDstu1Bundle()
+ .execute();
+ // END SNIPPET: historyDstu1
+ }
+ {
+ ca.uhn.fhir.model.dstu2.resource.Bundle response;
+ // START SNIPPET: historyDstu2
+ response = client
+ .history()
+ .ofServer()
+ .andReturnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class)
+ .execute();
+ // END SNIPPET: historyDstu2
+ }
+ {
+ ca.uhn.fhir.model.dstu2.resource.Bundle response;
+ // START SNIPPET: historyFeatures
+ response = client
+ .history()
+ .ofServer()
+ .andReturnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class)
+ .since(new InstantDt("2012-01-01T12:22:32.038Z"))
+ .count(100)
+ .execute();
+ // END SNIPPET: historyFeatures
+ }
+ }
+
public static void main(String[] args) {
fluentSearch();
}
diff --git a/hapi-fhir-android/dependency-reduced-pom.xml b/hapi-fhir-android/dependency-reduced-pom.xml
new file mode 100644
index 00000000000..0246aa284a5
--- /dev/null
+++ b/hapi-fhir-android/dependency-reduced-pom.xml
@@ -0,0 +1,151 @@
+
+
+
+ hapi-fhir
+ ca.uhn.hapi.fhir
+ 0.9-SNAPSHOT
+
+ 4.0.0
+ hapi-fhir-android
+ HAPI FHIR - Android
+
+
+
+ maven-deploy-plugin
+
+ true
+
+
+
+ maven-failsafe-plugin
+ ${maven_failsafe_plugin_version}
+
+
+
+ integration-test
+ verify
+
+
+
+
+ compile+runtime
+
+ ${project.build.directory}/hapi-fhir-android-${project.version}.jar
+
+
+
+
+ maven-shade-plugin
+ 2.3
+
+
+ package
+
+ shade
+
+
+ true
+
+
+ commons-codec:commons-codec
+ commons-io:commons-io
+ ca.uhn.hapi.fhir:hapi-fhir-base
+ ca.uhn.hapi.fhir:hapi-fhir-structures-dstu
+ ca.uhn.hapi.fhir:hapi-fhir-structures-dstu2
+ org.glassfish:javax.json
+ org.codehaus.woodstox:woodstox-core-asl
+ javax.xml.stream:stax-api
+ org.codehaus.woodstox:stax2-api
+ org.slf4j:slf4j*
+ org.apache.commons:*
+ org.apache.httpcomponents:*
+ org.glassfish:javax.json
+
+
+
+
+ javax.xml.stream
+ ca.uhn.fhir.repackage.javax.xml.stream
+
+
+ javax.json
+ ca.uhn.fhir.repackage.javax.json
+
+
+
+
+ ca.uhn.hapi.fhir:hapi-fhir-base
+
+ ca/uhn/fhir/model/dstu/valueset/**
+ **/*.java
+
+
+
+
+
+
+
+
+
+
+
+ DIST
+
+
+
+ maven-assembly-plugin
+ ${maven_assembly_plugin_version}
+
+
+ package
+
+ single
+
+
+ false
+
+ ${project.basedir}/src/assembly/hapi-fhir-all.xml
+ ${project.basedir}/src/assembly/hapi-fhir-jpaserver-example.xml
+
+
+
+
+
+
+
+
+
+
+
+ com.phloc
+ phloc-schematron
+ 2.7.1
+ compile
+
+
+ com.phloc
+ phloc-commons
+ 4.3.5
+ compile
+
+
+ javax.servlet
+ javax.servlet-api
+ 3.1.0
+ compile
+
+
+ junit
+ junit
+ 4.12
+ test
+
+
+ hamcrest-core
+ org.hamcrest
+
+
+
+
+
+
diff --git a/hapi-fhir-android/pom.xml b/hapi-fhir-android/pom.xml
index d3c73a1c71f..ce409b3b9da 100644
--- a/hapi-fhir-android/pom.xml
+++ b/hapi-fhir-android/pom.xml
@@ -28,6 +28,10 @@
org.apache.httpcomponents
httpcore
+
+ commons-codec
+ commons-codec
+
@@ -63,17 +67,21 @@
-
- commons-codec
- commons-codec
- ${commons_codec_version}
-
commons-io
commons-io
${commons_io_version}
+
+
+ javax.servlet
+ javax.servlet-api
+ ${servlet_api_version}
+ compile
+
@@ -102,7 +110,7 @@
compile+runtime
- target/hapi-fhir-android-0.9-SNAPSHOT-shaded.jar
+ ${project.build.directory}/hapi-fhir-android-${project.version}.jar
@@ -125,7 +133,6 @@
shade
- true
true
@@ -158,13 +165,6 @@
ca.uhn.hapi.fhir:hapi-fhir-base
-
ca/uhn/fhir/model/dstu/valueset/**
**/*.java
@@ -177,34 +177,4 @@
-
-
-
- DIST
-
-
-
- maven-assembly-plugin
- ${maven_assembly_plugin_version}
-
-
- package
-
- single
-
-
- false
-
- ${project.basedir}/src/assembly/hapi-fhir-all.xml
- ${project.basedir}/src/assembly/hapi-fhir-jpaserver-example.xml
-
-
-
-
-
-
-
-
-
-
diff --git a/hapi-fhir-android/src/test/java/ca/uhn/fhir/android/BuiltJarIT.java b/hapi-fhir-android/src/test/java/ca/uhn/fhir/android/BuiltJarIT.java
index 496e1ebcc59..51d4e19625c 100644
--- a/hapi-fhir-android/src/test/java/ca/uhn/fhir/android/BuiltJarIT.java
+++ b/hapi-fhir-android/src/test/java/ca/uhn/fhir/android/BuiltJarIT.java
@@ -57,9 +57,10 @@ public class BuiltJarIT {
*/
@Test
public void testJarForDuplicates() throws Exception {
- Collection files = FileUtils.listFiles(new File("target"), new WildcardFileFilter("*-shaded.jar"), null);
+ String wildcard = "hapi-fhir-android-*.jar";
+ Collection files = FileUtils.listFiles(new File("target"), new WildcardFileFilter(wildcard), null);
if (files.isEmpty()) {
- throw new Exception("No files matching target/*-shaded.jar");
+ throw new Exception("No files matching " + wildcard);
}
for (File file : files) {
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/Base64BinaryDt.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/Base64BinaryDt.java
index d65b6d218f0..6b9924d6f39 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/Base64BinaryDt.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/Base64BinaryDt.java
@@ -25,6 +25,7 @@ import org.apache.commons.codec.binary.Base64;
import ca.uhn.fhir.model.api.BasePrimitive;
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
import ca.uhn.fhir.model.api.annotation.SimpleSetter;
+import ca.uhn.fhir.rest.server.Constants;
@DatatypeDef(name = "base64Binary")
public class Base64BinaryDt extends BasePrimitive {
@@ -46,12 +47,12 @@ public class Base64BinaryDt extends BasePrimitive {
@Override
protected byte[] parse(String theValue) {
- return Base64.decodeBase64(theValue);
+ return Base64.decodeBase64(theValue.getBytes(Constants.CHARSET_UTF8));
}
@Override
protected String encode(byte[] theValue) {
- return Base64.encodeBase64String(theValue);
+ return new String(Base64.encodeBase64(theValue), Constants.CHARSET_UTF8);
}
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/GenericClient.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/GenericClient.java
index 772adc52f46..b6ed2c1aab0 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/GenericClient.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/GenericClient.java
@@ -20,11 +20,13 @@ package ca.uhn.fhir.rest.client;
* #L%
*/
-import static org.apache.commons.lang3.StringUtils.*;
+import static org.apache.commons.lang3.StringUtils.isBlank;
+import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
+import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
@@ -36,6 +38,7 @@ import org.apache.commons.lang3.Validate;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpRequestBase;
import org.hl7.fhir.instance.model.IBaseResource;
+import org.hl7.fhir.instance.model.api.IBaseBundle;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
@@ -49,6 +52,7 @@ import ca.uhn.fhir.model.base.resource.BaseConformance;
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
import ca.uhn.fhir.model.primitive.DateTimeDt;
import ca.uhn.fhir.model.primitive.IdDt;
+import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.model.primitive.UriDt;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.parser.IParser;
@@ -68,6 +72,9 @@ 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;
+import ca.uhn.fhir.rest.gclient.IHistory;
+import ca.uhn.fhir.rest.gclient.IHistoryTyped;
+import ca.uhn.fhir.rest.gclient.IHistoryUntyped;
import ca.uhn.fhir.rest.gclient.IOperation;
import ca.uhn.fhir.rest.gclient.IParam;
import ca.uhn.fhir.rest.gclient.IQuery;
@@ -111,12 +118,13 @@ import ca.uhn.fhir.util.ICallable;
public class GenericClient extends BaseClient implements IGenericClient {
private static final String I18N_CANNOT_DETEMINE_RESOURCE_TYPE = "ca.uhn.fhir.rest.client.GenericClient.cannotDetermineResourceTypeFromUri";
+
private static final String I18N_INCOMPLETE_URI_FOR_READ = "ca.uhn.fhir.rest.client.GenericClient.incompleteUriForRead";
private static final String I18N_NO_VERSION_ID_FOR_VREAD = "ca.uhn.fhir.rest.client.GenericClient.noVersionIdForVread";
-
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(GenericClient.class);
private FhirContext myContext;
+
private HttpRequestBase myLastRequest;
private boolean myLogRequestAndResponse;
@@ -170,6 +178,19 @@ public class GenericClient extends BaseClient implements IGenericClient {
return new DeleteInternal();
}
+ @Override
+ public MethodOutcome delete(final Class extends IResource> theType, IdDt theId) {
+ HttpDeleteClientInvocation invocation = DeleteMethodBinding.createDeleteInvocation(theId.withResourceType(toResourceName(theType)));
+ if (isKeepResponses()) {
+ myLastRequest = invocation.asHttpRequest(getServerBase(), createExtraParams(), getEncoding());
+ }
+
+ final String resourceName = myContext.getResourceDefinition(theType).getName();
+ OutcomeResponseHandler binding = new OutcomeResponseHandler(resourceName);
+ MethodOutcome resp = invokeClient(myContext, binding, invocation, myLogRequestAndResponse);
+ return resp;
+ }
+
// public IResource read(UriDt url) {
// return read(inferResourceClass(url), url);
// }
@@ -184,21 +205,51 @@ public class GenericClient extends BaseClient implements IGenericClient {
// }
@Override
- public MethodOutcome delete(final Class extends IResource> theType, IdDt theId) {
- HttpDeleteClientInvocation invocation = DeleteMethodBinding.createDeleteInvocation(theId.withResourceType(toResourceName(theType)));
+ public MethodOutcome delete(Class extends IResource> theType, String theId) {
+ return delete(theType, new IdDt(theId));
+ }
+
+ private T doReadOrVRead(final Class theType, IdDt theId, boolean theVRead, ICallable theNotModifiedHandler, String theIfVersionMatches) {
+ String resName = toResourceName(theType);
+ IdDt id = theId;
+ if (!id.hasBaseUrl()) {
+ id = new IdDt(resName, id.getIdPart(), id.getVersionIdPart());
+ }
+
+ HttpGetClientInvocation invocation;
+ if (id.hasBaseUrl()) {
+ if (theVRead) {
+ invocation = ReadMethodBinding.createAbsoluteVReadInvocation(id);
+ } else {
+ invocation = ReadMethodBinding.createAbsoluteReadInvocation(id);
+ }
+ } else {
+ if (theVRead) {
+ invocation = ReadMethodBinding.createVReadInvocation(id, resName);
+ } else {
+ invocation = ReadMethodBinding.createReadInvocation(id, resName);
+ }
+ }
if (isKeepResponses()) {
myLastRequest = invocation.asHttpRequest(getServerBase(), createExtraParams(), getEncoding());
}
- final String resourceName = myContext.getResourceDefinition(theType).getName();
- OutcomeResponseHandler binding = new OutcomeResponseHandler(resourceName);
- MethodOutcome resp = invokeClient(myContext, binding, invocation, myLogRequestAndResponse);
- return resp;
- }
+ if (theIfVersionMatches != null) {
+ invocation.addHeader(Constants.HEADER_IF_NONE_MATCH, '"' + theIfVersionMatches + '"');
+ }
+
+ ResourceResponseHandler binding = new ResourceResponseHandler(theType, id);
+
+ if (theNotModifiedHandler == null) {
+ return invokeClient(myContext, binding, invocation, myLogRequestAndResponse);
+ } else {
+ try {
+ return invokeClient(myContext, binding, invocation, myLogRequestAndResponse);
+ } catch (NotModifiedException e) {
+ return theNotModifiedHandler.call();
+ }
+ }
- @Override
- public MethodOutcome delete(Class extends IResource> theType, String theId) {
- return delete(theType, new IdDt(theId));
}
public HttpRequestBase getLastRequest() {
@@ -217,10 +268,15 @@ public class GenericClient extends BaseClient implements IGenericClient {
return new GetTagsInternal();
}
+ @Override
+ public IHistory history() {
+ return new HistoryInternal();
+ }
+
@Override
public Bundle history(final Class theType, IdDt theIdDt, DateTimeDt theSince, Integer theLimit) {
String resourceName = theType != null ? toResourceName(theType) : null;
- IdDt id = theIdDt != null && theIdDt.isEmpty() == false ? theIdDt : null;
+ String id = theIdDt != null && theIdDt.isEmpty() == false ? theIdDt.getValue() : null;
HttpGetClientInvocation invocation = HistoryMethodBinding.createHistoryInvocation(resourceName, id, theSince, theLimit);
if (isKeepResponses()) {
myLastRequest = invocation.asHttpRequest(getServerBase(), createExtraParams(), getEncoding());
@@ -237,6 +293,42 @@ public class GenericClient extends BaseClient implements IGenericClient {
return history(theType, new IdDt(theId), theSince, theLimit);
}
+ private Class extends IBaseResource> inferResourceClass(UriDt theUrl) {
+ String urlString = theUrl.getValueAsString();
+ int i = urlString.indexOf('?');
+
+ if (i >= 0) {
+ urlString = urlString.substring(0, i);
+ }
+
+ i = urlString.indexOf("://");
+
+ if (i >= 0) {
+ urlString = urlString.substring(i + 3);
+ }
+
+ String[] pcs = urlString.split("\\/");
+
+ for (i = pcs.length - 1; i >= 0; i--) {
+ String s = pcs[i].trim();
+
+ if (!s.isEmpty()) {
+ RuntimeResourceDefinition def = myContext.getResourceDefinition(s);
+ if (def != null) {
+ return def.getImplementingClass();
+ }
+ }
+ }
+
+ throw new RuntimeException(myContext.getLocalizer().getMessage(I18N_CANNOT_DETEMINE_RESOURCE_TYPE, theUrl.getValueAsString()));
+
+ }
+
+ // @Override
+ // public T read(final Class theType, IdDt theId) {
+ // return doReadOrVRead(theType, theId, false, null, null);
+ // }
+
public boolean isLogRequestAndResponse() {
return myLogRequestAndResponse;
}
@@ -246,10 +338,16 @@ public class GenericClient extends BaseClient implements IGenericClient {
return new LoadPageInternal();
}
- // @Override
- // public T read(final Class theType, IdDt theId) {
- // return doReadOrVRead(theType, theId, false, null, null);
- // }
+ @Override
+ public IOperation operation() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public IRead read() {
+ return new ReadInternal();
+ }
@Override
public T read(Class theType, String theId) {
@@ -316,37 +414,6 @@ public class GenericClient extends BaseClient implements IGenericClient {
return search(inferResourceClass(theUrl), theUrl);
}
- private Class extends IBaseResource> inferResourceClass(UriDt theUrl) {
- String urlString = theUrl.getValueAsString();
- int i = urlString.indexOf('?');
-
- if (i >= 0) {
- urlString = urlString.substring(0, i);
- }
-
- i = urlString.indexOf("://");
-
- if (i >= 0) {
- urlString = urlString.substring(i + 3);
- }
-
- String[] pcs = urlString.split("\\/");
-
- for (i = pcs.length - 1; i >= 0; i--) {
- String s = pcs[i].trim();
-
- if (!s.isEmpty()) {
- RuntimeResourceDefinition def = myContext.getResourceDefinition(s);
- if (def != null) {
- return def.getImplementingClass();
- }
- }
- }
-
- throw new RuntimeException(myContext.getLocalizer().getMessage(I18N_CANNOT_DETEMINE_RESOURCE_TYPE, theUrl.getValueAsString()));
-
- }
-
/**
* For now, this is a part of the internal API of HAPI - Use with caution as this method may change!
*/
@@ -428,49 +495,6 @@ public class GenericClient extends BaseClient implements IGenericClient {
return doReadOrVRead(theType, theId, true, null, null);
}
- private T doReadOrVRead(final Class theType, IdDt theId, boolean theVRead, ICallable theNotModifiedHandler, String theIfVersionMatches) {
- String resName = toResourceName(theType);
- IdDt id = theId;
- if (!id.hasBaseUrl()) {
- id = new IdDt(resName, id.getIdPart(), id.getVersionIdPart());
- }
-
- HttpGetClientInvocation invocation;
- if (id.hasBaseUrl()) {
- if (theVRead) {
- invocation = ReadMethodBinding.createAbsoluteVReadInvocation(id);
- } else {
- invocation = ReadMethodBinding.createAbsoluteReadInvocation(id);
- }
- } else {
- if (theVRead) {
- invocation = ReadMethodBinding.createVReadInvocation(id, resName);
- } else {
- invocation = ReadMethodBinding.createReadInvocation(id, resName);
- }
- }
- if (isKeepResponses()) {
- myLastRequest = invocation.asHttpRequest(getServerBase(), createExtraParams(), getEncoding());
- }
-
- if (theIfVersionMatches != null) {
- invocation.addHeader(Constants.HEADER_IF_NONE_MATCH, '"' + theIfVersionMatches + '"');
- }
-
- ResourceResponseHandler binding = new ResourceResponseHandler(theType, id);
-
- if (theNotModifiedHandler == null) {
- return invokeClient(myContext, binding, invocation, myLogRequestAndResponse);
- } else {
- try {
- return invokeClient(myContext, binding, invocation, myLogRequestAndResponse);
- } catch (NotModifiedException e) {
- return theNotModifiedHandler.call();
- }
- }
-
- }
-
/* also deprecated in interface */
@Deprecated
@Override
@@ -517,6 +541,10 @@ public class GenericClient extends BaseClient implements IGenericClient {
return (T) this;
}
+ protected EncodingEnum getParamEncoding() {
+ return myParamEncoding;
+ }
+
protected Z invoke(Map> theParams, IClientResponseHandler theHandler, BaseHttpClientInvocation theInvocation) {
// if (myParamEncoding != null) {
// theParams.put(Constants.PARAM_FORMAT, Collections.singletonList(myParamEncoding.getFormatContentType()));
@@ -534,10 +562,6 @@ public class GenericClient extends BaseClient implements IGenericClient {
return resp;
}
- protected EncodingEnum getParamEncoding() {
- return myParamEncoding;
- }
-
protected IResource parseResourceBody(String theResourceBody) {
EncodingEnum encoding = null;
for (int i = 0; i < theResourceBody.length() && encoding == null; i++) {
@@ -574,7 +598,8 @@ public class GenericClient extends BaseClient implements IGenericClient {
}
@Override
- public Bundle invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map> theHeaders) throws IOException, BaseServerResponseException {
+ public Bundle invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map> theHeaders) throws IOException,
+ BaseServerResponseException {
EncodingEnum respType = EncodingEnum.forContentType(theResponseMimeType);
if (respType == null) {
throw NonFhirResponseException.newInstance(theResponseStatusCode, theResponseMimeType, theResponseReader);
@@ -586,11 +611,29 @@ public class GenericClient extends BaseClient implements IGenericClient {
private class CreateInternal extends BaseClientExecutable implements ICreate, ICreateTyped, ICreateWithQuery, ICreateWithQueryTyped {
+ private CriterionList myCriterionList;
private String myId;
private IResource myResource;
private String myResourceBody;
private String mySearchUrl;
- private CriterionList myCriterionList;
+
+ @Override
+ public ICreateWithQueryTyped and(ICriterion> theCriterion) {
+ myCriterionList.add((ICriterionInternal) theCriterion);
+ return this;
+ }
+
+ @Override
+ public ICreateWithQuery conditional() {
+ myCriterionList = new CriterionList();
+ return this;
+ }
+
+ @Override
+ public ICreateTyped conditionalByUrl(String theSearchUrl) {
+ mySearchUrl = theSearchUrl;
+ return this;
+ }
@Override
public MethodOutcome execute() {
@@ -637,6 +680,12 @@ public class GenericClient extends BaseClient implements IGenericClient {
return this;
}
+ @Override
+ public ICreateWithQueryTyped where(ICriterion> theCriterion) {
+ myCriterionList.add((ICriterionInternal) theCriterion);
+ return this;
+ }
+
@Override
public CreateInternal withId(IdDt theId) {
myId = theId.getIdPart();
@@ -649,38 +698,40 @@ public class GenericClient extends BaseClient implements IGenericClient {
return this;
}
- @Override
- public ICreateTyped conditionalByUrl(String theSearchUrl) {
- mySearchUrl = theSearchUrl;
- return this;
+ }
+
+ private static class CriterionList extends ArrayList {
+
+ private static final long serialVersionUID = 1L;
+
+ public void populateParamList(Map> theParams) {
+ for (ICriterionInternal next : this) {
+ String parameterName = next.getParameterName();
+ String parameterValue = next.getParameterValue();
+ addParam(theParams, parameterName, parameterValue);
+ }
}
- @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;
+ public Map> toParamList() {
+ LinkedHashMap> retVal = new LinkedHashMap>();
+ populateParamList(retVal);
+ return retVal;
}
}
private class DeleteInternal extends BaseClientExecutable implements IDelete, IDeleteTyped, IDeleteWithQuery, IDeleteWithQueryTyped {
- private IdDt myId;
- private String mySearchUrl;
- private String myResourceType;
private CriterionList myCriterionList;
+ private IdDt myId;
+ private String myResourceType;
+ private String mySearchUrl;
+
+ @Override
+ public IDeleteWithQueryTyped and(ICriterion> theCriterion) {
+ myCriterionList.add((ICriterionInternal) theCriterion);
+ return this;
+ }
@Override
public BaseOperationOutcome execute() {
@@ -734,13 +785,6 @@ public class GenericClient extends BaseClient implements IGenericClient {
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");
@@ -753,38 +797,19 @@ public class GenericClient extends BaseClient implements IGenericClient {
}
@Override
- public IDeleteWithQueryTyped where(ICriterion> theCriterion) {
- myCriterionList.add((ICriterionInternal) theCriterion);
+ public IDeleteTyped resourceConditionalByUrl(String theSearchUrl) {
+ Validate.notBlank(theSearchUrl, "theSearchUrl can not be blank/null");
+ mySearchUrl = theSearchUrl;
return this;
}
@Override
- public IDeleteWithQueryTyped and(ICriterion> theCriterion) {
+ public IDeleteWithQueryTyped where(ICriterion> theCriterion) {
myCriterionList.add((ICriterionInternal) theCriterion);
return this;
}
}
- private static class CriterionList extends ArrayList {
-
- private static final long serialVersionUID = 1L;
-
- public void populateParamList(Map> theParams) {
- for (ICriterionInternal next : this) {
- String parameterName = next.getParameterName();
- String parameterValue = next.getParameterValue();
- addParam(theParams, parameterName, parameterValue);
- }
- }
-
- public Map> toParamList() {
- LinkedHashMap> retVal = new LinkedHashMap>();
- populateParamList(retVal);
- return retVal;
- }
-
- }
-
private class GetPageInternal extends BaseClientExecutable implements IGetPageTyped {
private String myUrl;
@@ -806,132 +831,6 @@ public class GenericClient extends BaseClient implements IGenericClient {
}
- @Override
- public IRead read() {
- return new ReadInternal();
- }
-
- @SuppressWarnings({ "rawtypes", "unchecked" })
- private class ReadInternal extends BaseClientExecutable implements IRead, IReadTyped, IReadExecutable {
- private RuntimeResourceDefinition myType;
- private IdDt myId;
- private ICallable myNotModifiedHandler;
- private String myIfVersionMatches;
-
- @Override
- public IReadTyped resource(Class theResourceType) {
- Validate.notNull(theResourceType, "theResourceType must not be null");
- myType = myContext.getResourceDefinition(theResourceType);
- if (myType == null) {
- throw new IllegalArgumentException(myContext.getLocalizer().getMessage(I18N_CANNOT_DETEMINE_RESOURCE_TYPE, theResourceType));
- }
- return this;
- }
-
- @Override
- public IReadTyped resource(String theResourceAsText) {
- Validate.notBlank(theResourceAsText, "You must supply a value for theResourceAsText");
- myType = myContext.getResourceDefinition(theResourceAsText);
- if (myType == null) {
- throw new IllegalArgumentException(myContext.getLocalizer().getMessage(I18N_CANNOT_DETEMINE_RESOURCE_TYPE, theResourceAsText));
- }
- return this;
- }
-
- @Override
- public IReadExecutable withId(String theId) {
- Validate.notBlank(theId, "The ID can not be blank");
- myId = new IdDt(myType.getName(), theId);
- return this;
- }
-
- @Override
- public IReadExecutable withIdAndVersion(String theId, String theVersion) {
- Validate.notBlank(theId, "The ID can not be blank");
- myId = new IdDt(myType.getName(), theId, theVersion);
- return this;
- }
-
- @Override
- public IReadExecutable withId(IdDt theId) {
- Validate.notNull(theId, "The ID can not be null");
- Validate.notBlank(theId.getIdPart(), "The ID can not be blank");
- myId = theId.toUnqualified();
- return this;
- }
-
- @Override
- public IReadExecutable withUrl(String theUrl) {
- myId = new IdDt(theUrl);
- processUrl();
- return this;
- }
-
- private void processUrl() {
- String resourceType = myId.getResourceType();
- if (isBlank(resourceType)) {
- throw new IllegalArgumentException(myContext.getLocalizer().getMessage(I18N_INCOMPLETE_URI_FOR_READ, myId));
- }
- myType = myContext.getResourceDefinition(resourceType);
- if (myType == null) {
- throw new IllegalArgumentException(myContext.getLocalizer().getMessage(I18N_CANNOT_DETEMINE_RESOURCE_TYPE, myId));
- }
- }
-
- @Override
- public Object execute() {
- if (myId.hasVersionIdPart()) {
- return doReadOrVRead(myType.getImplementingClass(), myId, true, myNotModifiedHandler, myIfVersionMatches);
- } else {
- return doReadOrVRead(myType.getImplementingClass(), myId, false, myNotModifiedHandler, myIfVersionMatches);
- }
- }
-
- @Override
- public IReadExecutable withUrl(IdDt theUrl) {
- Validate.notNull(theUrl, "theUrl can not be null");
- myId = theUrl;
- processUrl();
- return this;
- }
-
- @Override
- public IReadIfNoneMatch ifVersionMatches(String theVersion) {
- myIfVersionMatches = theVersion;
- return new IReadIfNoneMatch() {
-
- @Override
- public IReadExecutable returnResource(final IBaseResource theInstance) {
- myNotModifiedHandler = new ICallable() {
- @Override
- public Object call() {
- return theInstance;
- }
- };
- return ReadInternal.this;
- }
-
- @Override
- public IReadExecutable returnNull() {
- myNotModifiedHandler = new ICallable() {
- @Override
- public Object call() {
- return null;
- }
- };
- return ReadInternal.this;
- }
-
- @Override
- public IReadExecutable throwNotModifiedException() {
- myNotModifiedHandler = null;
- return ReadInternal.this;
- }
- };
- }
-
- }
-
private class GetTagsInternal extends BaseClientExecutable implements IGetTags {
private String myId;
@@ -998,6 +897,100 @@ public class GenericClient extends BaseClient implements IGenericClient {
}
+ @SuppressWarnings("rawtypes")
+ public class HistoryInternal extends BaseClientExecutable implements IHistory, IHistoryUntyped, IHistoryTyped {
+
+ private Integer myCount;
+ private IdDt myId;
+ private Class extends IBaseBundle> myReturnType;
+ private InstantDt mySince;
+ private Class extends IBaseResource> myType;
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public IHistoryTyped andReturnBundle(Class theType) {
+ myReturnType = theType;
+ return this;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public IHistoryTyped andReturnDstu1Bundle() {
+ return this;
+ }
+
+ @Override
+ public IHistoryTyped count(Integer theCount) {
+ myCount = theCount;
+ return this;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Object execute() {
+ String resourceName;
+ String id;
+ if (myType != null) {
+ resourceName = myContext.getResourceDefinition(myType).getName();
+ id = null;
+ } else if (myId != null) {
+ resourceName = myId.getResourceType();
+ id = myId.getIdPart();
+ } else {
+ resourceName = null;
+ id = null;
+ }
+
+ HttpGetClientInvocation invocation = HistoryMethodBinding.createHistoryInvocation(resourceName, id, mySince, myCount);
+
+ IClientResponseHandler handler;
+ if (myReturnType != null) {
+ handler = new ResourceResponseHandler(myReturnType, null);
+ } else {
+ handler = new BundleResponseHandler(null);
+ }
+
+ return invoke(null, handler, invocation);
+ }
+
+ @Override
+ public IHistoryUntyped ofInstance(IdDt theId) {
+ if (theId.hasResourceType() == false) {
+ throw new IllegalArgumentException("Resource ID does not have a resource type: " + theId.getValue());
+ }
+ myId = theId;
+ return this;
+ }
+
+ @Override
+ public IHistoryUntyped ofServer() {
+ return this;
+ }
+
+ @Override
+ public IHistoryUntyped ofType(Class extends IBaseResource> theResourceType) {
+ myType = theResourceType;
+ return this;
+ }
+
+ @Override
+ public IHistoryTyped since(Date theCutoff) {
+ if (theCutoff != null) {
+ mySince = new InstantDt(theCutoff);
+ } else {
+ mySince = null;
+ }
+ return this;
+ }
+
+ @Override
+ public IHistoryTyped since(InstantDt theCutoff) {
+ mySince = theCutoff;
+ return this;
+ }
+
+ }
+
private final class LoadPageInternal implements IGetPage {
@Override
@@ -1020,7 +1013,8 @@ public class GenericClient extends BaseClient implements IGenericClient {
private final class OperationOutcomeResponseHandler implements IClientResponseHandler {
@Override
- public BaseOperationOutcome invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map> theHeaders) throws IOException, BaseServerResponseException {
+ public BaseOperationOutcome invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map> theHeaders) throws IOException,
+ BaseServerResponseException {
EncodingEnum respType = EncodingEnum.forContentType(theResponseMimeType);
if (respType == null) {
return null;
@@ -1048,7 +1042,8 @@ public class GenericClient extends BaseClient implements IGenericClient {
}
@Override
- public MethodOutcome invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map> theHeaders) throws IOException, BaseServerResponseException {
+ public MethodOutcome invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map> theHeaders) throws IOException,
+ BaseServerResponseException {
MethodOutcome response = MethodUtil.process2xxResponse(myContext, myResourceName, theResponseStatusCode, theResponseMimeType, theResponseReader, theHeaders);
if (theResponseStatusCode == Constants.STATUS_HTTP_201_CREATED) {
response.setCreated(true);
@@ -1057,6 +1052,127 @@ public class GenericClient extends BaseClient implements IGenericClient {
}
}
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ private class ReadInternal extends BaseClientExecutable implements IRead, IReadTyped, IReadExecutable {
+ private IdDt myId;
+ private String myIfVersionMatches;
+ private ICallable myNotModifiedHandler;
+ private RuntimeResourceDefinition myType;
+
+ @Override
+ public Object execute() {
+ if (myId.hasVersionIdPart()) {
+ return doReadOrVRead(myType.getImplementingClass(), myId, true, myNotModifiedHandler, myIfVersionMatches);
+ } else {
+ return doReadOrVRead(myType.getImplementingClass(), myId, false, myNotModifiedHandler, myIfVersionMatches);
+ }
+ }
+
+ @Override
+ public IReadIfNoneMatch ifVersionMatches(String theVersion) {
+ myIfVersionMatches = theVersion;
+ return new IReadIfNoneMatch() {
+
+ @Override
+ public IReadExecutable returnNull() {
+ myNotModifiedHandler = new ICallable() {
+ @Override
+ public Object call() {
+ return null;
+ }
+ };
+ return ReadInternal.this;
+ }
+
+ @Override
+ public IReadExecutable returnResource(final IBaseResource theInstance) {
+ myNotModifiedHandler = new ICallable() {
+ @Override
+ public Object call() {
+ return theInstance;
+ }
+ };
+ return ReadInternal.this;
+ }
+
+ @Override
+ public IReadExecutable throwNotModifiedException() {
+ myNotModifiedHandler = null;
+ return ReadInternal.this;
+ }
+ };
+ }
+
+ private void processUrl() {
+ String resourceType = myId.getResourceType();
+ if (isBlank(resourceType)) {
+ throw new IllegalArgumentException(myContext.getLocalizer().getMessage(I18N_INCOMPLETE_URI_FOR_READ, myId));
+ }
+ myType = myContext.getResourceDefinition(resourceType);
+ if (myType == null) {
+ throw new IllegalArgumentException(myContext.getLocalizer().getMessage(I18N_CANNOT_DETEMINE_RESOURCE_TYPE, myId));
+ }
+ }
+
+ @Override
+ public IReadTyped resource(Class theResourceType) {
+ Validate.notNull(theResourceType, "theResourceType must not be null");
+ myType = myContext.getResourceDefinition(theResourceType);
+ if (myType == null) {
+ throw new IllegalArgumentException(myContext.getLocalizer().getMessage(I18N_CANNOT_DETEMINE_RESOURCE_TYPE, theResourceType));
+ }
+ return this;
+ }
+
+ @Override
+ public IReadTyped resource(String theResourceAsText) {
+ Validate.notBlank(theResourceAsText, "You must supply a value for theResourceAsText");
+ myType = myContext.getResourceDefinition(theResourceAsText);
+ if (myType == null) {
+ throw new IllegalArgumentException(myContext.getLocalizer().getMessage(I18N_CANNOT_DETEMINE_RESOURCE_TYPE, theResourceAsText));
+ }
+ return this;
+ }
+
+ @Override
+ public IReadExecutable withId(IdDt theId) {
+ Validate.notNull(theId, "The ID can not be null");
+ Validate.notBlank(theId.getIdPart(), "The ID can not be blank");
+ myId = theId.toUnqualified();
+ return this;
+ }
+
+ @Override
+ public IReadExecutable withId(String theId) {
+ Validate.notBlank(theId, "The ID can not be blank");
+ myId = new IdDt(myType.getName(), theId);
+ return this;
+ }
+
+ @Override
+ public IReadExecutable withIdAndVersion(String theId, String theVersion) {
+ Validate.notBlank(theId, "The ID can not be blank");
+ myId = new IdDt(myType.getName(), theId, theVersion);
+ return this;
+ }
+
+ @Override
+ public IReadExecutable withUrl(IdDt theUrl) {
+ Validate.notNull(theUrl, "theUrl can not be null");
+ myId = theUrl;
+ processUrl();
+ return this;
+ }
+
+ @Override
+ public IReadExecutable withUrl(String theUrl) {
+ myId = new IdDt(theUrl);
+ processUrl();
+ return this;
+ }
+
+ }
+
private final class ResourceListResponseHandler implements IClientResponseHandler> {
private Class extends IResource> myType;
@@ -1067,7 +1183,8 @@ public class GenericClient extends BaseClient implements IGenericClient {
@SuppressWarnings("unchecked")
@Override
- public List invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map> theHeaders) throws IOException, BaseServerResponseException {
+ public List invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map> theHeaders) throws IOException,
+ BaseServerResponseException {
if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
Class extends IBaseResource> bundleType = myContext.getResourceDefinition("Bundle").getImplementingClass();
ResourceResponseHandler handler = new ResourceResponseHandler((Class) bundleType, null);
@@ -1278,7 +1395,8 @@ public class GenericClient extends BaseClient implements IGenericClient {
private final class TagListResponseHandler implements IClientResponseHandler {
@Override
- public TagList invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map> theHeaders) throws IOException, BaseServerResponseException {
+ public TagList invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map> theHeaders) throws IOException,
+ BaseServerResponseException {
EncodingEnum respType = EncodingEnum.forContentType(theResponseMimeType);
if (respType == null) {
throw NonFhirResponseException.newInstance(theResponseStatusCode, theResponseMimeType, theResponseReader);
@@ -1335,11 +1453,29 @@ public class GenericClient extends BaseClient implements IGenericClient {
private class UpdateInternal extends BaseClientExecutable implements IUpdate, IUpdateTyped, IUpdateExecutable, IUpdateWithQuery, IUpdateWithQueryTyped {
+ private CriterionList myCriterionList;
private IdDt myId;
private IResource myResource;
private String myResourceBody;
private String mySearchUrl;
- private CriterionList myCriterionList;
+
+ @Override
+ public IUpdateWithQueryTyped and(ICriterion> theCriterion) {
+ myCriterionList.add((ICriterionInternal) theCriterion);
+ return this;
+ }
+
+ @Override
+ public IUpdateWithQuery conditional() {
+ myCriterionList = new CriterionList();
+ return this;
+ }
+
+ @Override
+ public IUpdateTyped conditionalByUrl(String theSearchUrl) {
+ mySearchUrl = theSearchUrl;
+ return this;
+ }
@Override
public MethodOutcome execute() {
@@ -1391,6 +1527,12 @@ public class GenericClient extends BaseClient implements IGenericClient {
return this;
}
+ @Override
+ public IUpdateWithQueryTyped where(ICriterion> theCriterion) {
+ myCriterionList.add((ICriterionInternal) theCriterion);
+ return this;
+ }
+
@Override
public IUpdateExecutable withId(IdDt theId) {
if (theId == null) {
@@ -1415,36 +1557,6 @@ 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;
- }
-
- }
-
- @Override
- public IOperation operation() {
- // TODO Auto-generated method stub
- return null;
}
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/IGenericClient.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/IGenericClient.java
index 0479387a149..cb34846e28b 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/IGenericClient.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/IGenericClient.java
@@ -34,10 +34,13 @@ import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.UriDt;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.client.api.IRestfulClient;
+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.IDelete;
import ca.uhn.fhir.rest.gclient.IGetPage;
import ca.uhn.fhir.rest.gclient.IGetTags;
+import ca.uhn.fhir.rest.gclient.IHistory;
import ca.uhn.fhir.rest.gclient.IOperation;
import ca.uhn.fhir.rest.gclient.IRead;
import ca.uhn.fhir.rest.gclient.ITransaction;
@@ -101,6 +104,11 @@ public interface IGenericClient {
*/
IGetTags getTags();
+ /**
+ * Implementation of the "history" method
+ */
+ IHistory history();
+
/**
* Implementation of the "history instance" method.
*
@@ -117,6 +125,7 @@ public interface IGenericClient {
* server may return less even if more are available, but should not return more according to the FHIR
* specification.
* @return A bundle containing returned resources
+ * @deprecated As of 0.9, use the fluent {@link #history()} method instead
*/
Bundle history(Class theType, IdDt theId, DateTimeDt theSince, Integer theLimit);
@@ -136,6 +145,7 @@ public interface IGenericClient {
* server may return less even if more are available, but should not return more according to the FHIR
* specification.
* @return A bundle containing returned resources
+ * @deprecated As of 0.9, use the fluent {@link #history()} method instead
*/
Bundle history(Class theType, String theId, DateTimeDt theSince, Integer theLimit);
@@ -147,11 +157,6 @@ public interface IGenericClient {
*/
IGetPage loadPage();
- /**
- * Fluent method for "read" and "vread" methods.
- */
- IRead read();
-
// /**
// * Implementation of the "instance read" method. This method will only ever do a "read" for the latest version of a
// * given resource instance, even if the ID passed in contains a version. If you wish to request a specific version
@@ -170,6 +175,16 @@ public interface IGenericClient {
// */
// T read(Class theType, IdDt theId);
+ /**
+ * Implementation of the FHIR "extended operations" action
+ */
+ IOperation operation();
+
+ /**
+ * Fluent method for "read" and "vread" methods.
+ */
+ IRead read();
+
/**
* Implementation of the "instance read" method.
*
@@ -343,9 +358,4 @@ public interface IGenericClient {
*/
T vread(Class theType, String theId, String theVersionId);
- /**
- * Implementation of the FHIR "extended operations" action
- */
- IOperation operation();
-
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IBaseOn.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IBaseOn.java
new file mode 100644
index 00000000000..6341c0227f3
--- /dev/null
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IBaseOn.java
@@ -0,0 +1,28 @@
+package ca.uhn.fhir.rest.gclient;
+
+import org.hl7.fhir.instance.model.IBaseResource;
+
+import ca.uhn.fhir.model.primitive.IdDt;
+
+public interface IBaseOn {
+
+ /**
+ * Perform the operation across all versions of all resources of all types on the server
+ */
+ T ofServer();
+
+ /**
+ * Perform the operation across all versions of all resources of the given type on the server
+ */
+ T ofType(Class extends IBaseResource> theResourceType);
+
+ /**
+ * Perform the operation across all versions of a specific resource (by ID and type) on the server.
+ * Note that theId
must be populated with both a resource type and a resource ID at
+ * a minimum.
+ *
+ * @throws IllegalArgumentException If theId
does not contain at least a resource type and ID
+ */
+ T ofInstance(IdDt theId);
+
+}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IHistory.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IHistory.java
new file mode 100644
index 00000000000..3a3dde7e140
--- /dev/null
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IHistory.java
@@ -0,0 +1,5 @@
+package ca.uhn.fhir.rest.gclient;
+
+public interface IHistory extends IBaseOn {
+
+}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IHistoryTyped.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IHistoryTyped.java
new file mode 100644
index 00000000000..e2c790bb87d
--- /dev/null
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IHistoryTyped.java
@@ -0,0 +1,25 @@
+package ca.uhn.fhir.rest.gclient;
+
+import java.util.Date;
+
+import ca.uhn.fhir.model.primitive.InstantDt;
+
+public interface IHistoryTyped extends IClientExecutable, T> {
+
+ /**
+ * Request that the server return only resource versions that were created at or after the given time (inclusive)
+ */
+ IHistoryTyped since(Date theCutoff);
+
+ /**
+ * Request that the server return only resource versions that were created at or after the given time (inclusive)
+ */
+ IHistoryTyped since(InstantDt theCutoff);
+
+ /**
+ * Request that the server return only up to theCount
number of resources
+ */
+ IHistoryTyped count(Integer theCount);
+
+
+}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IHistoryUntyped.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IHistoryUntyped.java
new file mode 100644
index 00000000000..53b3b5dbdb9
--- /dev/null
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IHistoryUntyped.java
@@ -0,0 +1,21 @@
+package ca.uhn.fhir.rest.gclient;
+
+import org.hl7.fhir.instance.model.api.IBaseBundle;
+
+import ca.uhn.fhir.model.api.Bundle;
+
+public interface IHistoryUntyped {
+
+ /**
+ * Request that the method return a DSTU1 style bundle object. This method should only
+ * be called if you are accessing a DSTU1 server.
+ */
+ IHistoryTyped andReturnDstu1Bundle();
+
+ /**
+ * Request that the method return a Bundle resource (such as ca.uhn.fhir.model.dstu2.resource.Bundle
).
+ * Use this method if you are accessing a DSTU2+ server.
+ */
+ IHistoryTyped andReturnBundle(Class theType);
+
+}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IOperationOn.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IOperationOn.java
index 79dfb2fd9f0..8be7145a07d 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IOperationOn.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IOperationOn.java
@@ -1,6 +1,6 @@
package ca.uhn.fhir.rest.gclient;
-public interface IOperationOn {
+public interface IOperationOn extends IBaseOn {
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IOperationTyped.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IOperationTyped.java
new file mode 100644
index 00000000000..cdfb83bac89
--- /dev/null
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IOperationTyped.java
@@ -0,0 +1,7 @@
+package ca.uhn.fhir.rest.gclient;
+
+public interface IOperationTyped {
+
+
+
+}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseAddOrDeleteTagsMethodBinding.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseAddOrDeleteTagsMethodBinding.java
index c2cb2ef97d8..2baec5d23cb 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseAddOrDeleteTagsMethodBinding.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseAddOrDeleteTagsMethodBinding.java
@@ -190,7 +190,7 @@ abstract class BaseAddOrDeleteTagsMethodBinding extends BaseMethodBinding
HttpServletResponse response = theRequest.getServletResponse();
response.setContentType(Constants.CT_TEXT);
response.setStatus(Constants.STATUS_HTTP_200_OK);
- response.setCharacterEncoding(Constants.CHARSET_UTF_8);
+ response.setCharacterEncoding(Constants.CHARSETNAME_UTF_8);
theServer.addHeadersToResponse(response);
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseHttpClientInvocationWithContents.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseHttpClientInvocationWithContents.java
index 65ebdbf3e01..3d8d527f8c8 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseHttpClientInvocationWithContents.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseHttpClientInvocationWithContents.java
@@ -20,6 +20,10 @@ package ca.uhn.fhir.rest.method;
* #L%
*/
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
@@ -207,7 +211,14 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
if (myResource != null && BaseBinary.class.isAssignableFrom(myResource.getClass())) {
BaseBinary binary = (BaseBinary) myResource;
- ByteArrayEntity entity = new ByteArrayEntity(binary.getContent(), ContentType.parse(binary.getContentType()));
+
+ /*
+ * Note: Be careful about changing which constructor we use for ByteArrayEntity,
+ * as Android's version of HTTPClient doesn't support the newer ones for
+ * whatever reason.
+ */
+ ByteArrayEntity entity = new ByteArrayEntity(binary.getContent());
+ entity.setContentType(binary.getContentType());
HttpRequestBase retVal = createRequest(url, entity);
addMatchHeaders(retVal, url);
return retVal;
@@ -275,7 +286,14 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
contents = parser.encodeResourceToString(myResource);
contentType = encoding.getResourceContentType();
}
- entity = new StringEntity(contents, ContentType.create(contentType, Constants.CHARSET_UTF_8));
+
+ /*
+ * We aren't using a StringEntity here because the constructors supported by
+ * Android aren't available in non-Android, and vice versa. Since we add the
+ * content type header manually, it makes no difference which one
+ * we use anyhow.
+ */
+ entity = new ByteArrayEntity(contents.getBytes(Constants.CHARSET_UTF8));
}
HttpRequestBase retVal = createRequest(url, entity);
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/GetTagsMethodBinding.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/GetTagsMethodBinding.java
index b19db9b2e19..4056433f40c 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/GetTagsMethodBinding.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/GetTagsMethodBinding.java
@@ -173,7 +173,7 @@ public class GetTagsMethodBinding extends BaseMethodBinding {
HttpServletResponse response = theRequest.getServletResponse();
response.setContentType(responseEncoding.getResourceContentType());
response.setStatus(Constants.STATUS_HTTP_200_OK);
- response.setCharacterEncoding(Constants.CHARSET_UTF_8);
+ response.setCharacterEncoding(Constants.CHARSETNAME_UTF_8);
theServer.addHeadersToResponse(response);
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/HistoryMethodBinding.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/HistoryMethodBinding.java
index ccf2e630e90..13ad5d3a5a6 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/HistoryMethodBinding.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/HistoryMethodBinding.java
@@ -20,7 +20,8 @@ package ca.uhn.fhir.rest.method;
* #L%
*/
-import static org.apache.commons.lang3.StringUtils.*;
+import static org.apache.commons.lang3.StringUtils.isBlank;
+import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
@@ -34,7 +35,7 @@ import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationSystemEnum;
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationTypeEnum;
-import ca.uhn.fhir.model.primitive.DateTimeDt;
+import ca.uhn.fhir.model.primitive.BaseDateTimeDt;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
@@ -116,7 +117,8 @@ public class HistoryMethodBinding extends BaseResourceReturningMethodBinding {
}
}
- HttpGetClientInvocation retVal = createHistoryInvocation(resourceName, id, null, null);
+ String historyId = id != null ? id.getIdPart() : null;
+ HttpGetClientInvocation retVal = createHistoryInvocation(resourceName, historyId, null, null);
if (theArgs != null) {
for (int idx = 0; idx < theArgs.length; idx++) {
@@ -133,13 +135,13 @@ public class HistoryMethodBinding extends BaseResourceReturningMethodBinding {
return BundleTypeEnum.HISTORY;
}
- public static HttpGetClientInvocation createHistoryInvocation(String theResourceName, IdDt theId, DateTimeDt theSince, Integer theLimit) {
+ public static HttpGetClientInvocation createHistoryInvocation(String theResourceName, String theId, BaseDateTimeDt theSince, Integer theLimit) {
StringBuilder b = new StringBuilder();
if (theResourceName != null) {
b.append(theResourceName);
- if (theId != null && !theId.isEmpty()) {
+ if (isNotBlank(theId)) {
b.append('/');
- b.append(theId.getValue());
+ b.append(theId);
}
}
if (b.length() > 0) {
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/Constants.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/Constants.java
index 4296edc4a88..be99c1feae2 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/Constants.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/Constants.java
@@ -20,6 +20,7 @@ package ca.uhn.fhir.rest.server;
* #L%
*/
+import java.nio.charset.Charset;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -28,7 +29,7 @@ import java.util.Set;
public class Constants {
- public static final String CHARSET_UTF_8 = "UTF-8";
+ public static final String CHARSETNAME_UTF_8 = "UTF-8";
public static final String CT_ATOM_XML = "application/atom+xml";
public static final String CT_FHIR_JSON = "application/json+fhir";
@@ -119,6 +120,7 @@ public class Constants {
public static final String LINK_NEXT = "next";
public static final String LINK_LAST = "last";
public static final String LINK_FHIR_BASE = "fhir-base";
+ public static final Charset CHARSET_UTF8;
static {
Map valToEncoding = new HashMap();
@@ -142,6 +144,8 @@ public class Constants {
}
FORMAT_VAL_TO_ENCODING = Collections.unmodifiableMap(valToEncoding);
+
+ CHARSET_UTF8 = Charset.forName(CHARSETNAME_UTF_8);
}
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServerUtils.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServerUtils.java
index 597546fb148..516c7700348 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServerUtils.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServerUtils.java
@@ -104,7 +104,7 @@ public class RestfulServerUtils {
} else {
theHttpResponse.setContentType(responseEncoding.getResourceContentType());
}
- theHttpResponse.setCharacterEncoding(Constants.CHARSET_UTF_8);
+ theHttpResponse.setCharacterEncoding(Constants.CHARSETNAME_UTF_8);
theServer.addHeadersToResponse(theHttpResponse);
@@ -340,7 +340,7 @@ public class RestfulServerUtils {
theHttpResponse.setContentType(responseEncoding.getBundleContentType());
}
- theHttpResponse.setCharacterEncoding(Constants.CHARSET_UTF_8);
+ theHttpResponse.setCharacterEncoding(Constants.CHARSETNAME_UTF_8);
theServer.addHeadersToResponse(theHttpResponse);
diff --git a/hapi-fhir-jpaserver-base/.classpath b/hapi-fhir-jpaserver-base/.classpath
index 9ebe1a6b158..f9148a1a7ac 100644
--- a/hapi-fhir-jpaserver-base/.classpath
+++ b/hapi-fhir-jpaserver-base/.classpath
@@ -27,7 +27,7 @@
-
+
diff --git a/hapi-fhir-jpaserver-base/.settings/org.eclipse.wst.common.project.facet.core.xml b/hapi-fhir-jpaserver-base/.settings/org.eclipse.wst.common.project.facet.core.xml
index 5c9bd7532ab..4f92af543f1 100644
--- a/hapi-fhir-jpaserver-base/.settings/org.eclipse.wst.common.project.facet.core.xml
+++ b/hapi-fhir-jpaserver-base/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/client/GenericClientTest.java b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/client/GenericClientTest.java
index e828e14875d..39bdf198d93 100644
--- a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/client/GenericClientTest.java
+++ b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/client/GenericClientTest.java
@@ -5,6 +5,7 @@ import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import java.io.IOException;
+import java.io.InputStream;
import java.io.StringReader;
import java.net.URLEncoder;
import java.nio.charset.Charset;
@@ -30,6 +31,8 @@ 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;
@@ -639,6 +642,61 @@ public class GenericClientTest {
}
+ @Test
+ public void testHistory() throws Exception {
+
+ final String msg = getPatientFeedWithOneResult();
+
+ ArgumentCaptor capt = ArgumentCaptor.forClass(HttpUriRequest.class);
+ when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
+ when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
+ when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
+ when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer() {
+ @Override
+ public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
+ return new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8"));
+ }});
+
+ IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
+
+ int idx = 0;
+ Bundle response;
+
+ //@formatter:off
+ response = client
+ .history()
+ .ofServer()
+ .andReturnDstu1Bundle()
+ .execute();
+ //@formatter:on
+ assertEquals("http://example.com/fhir/_history", capt.getAllValues().get(idx).getURI().toString());
+ assertEquals(1, response.size());
+ idx++;
+
+ //@formatter:off
+ response = client
+ .history()
+ .ofType(Patient.class)
+ .andReturnDstu1Bundle()
+ .execute();
+ //@formatter:on
+ assertEquals("http://example.com/fhir/Patient/_history", capt.getAllValues().get(idx).getURI().toString());
+ assertEquals(1, response.size());
+ idx++;
+
+ //@formatter:off
+ response = client
+ .history()
+ .ofInstance(new IdDt("Patient", "123"))
+ .andReturnDstu1Bundle()
+ .execute();
+ //@formatter:on
+ assertEquals("http://example.com/fhir/Patient/123/_history", capt.getAllValues().get(idx).getURI().toString());
+ assertEquals(1, response.size());
+ idx++;
+ }
+
+
@SuppressWarnings("unused")
@Test
public void testSearchByNumberExact() throws Exception {
@@ -1069,7 +1127,7 @@ public class GenericClientTest {
HttpEntityEnclosingRequestBase value = (HttpEntityEnclosingRequestBase) capt.getValue();
- Header ct = value.getEntity().getContentType();
+ Header ct = value.getFirstHeader(Constants.HEADER_CONTENT_TYPE);
assertNotNull(ct);
assertEquals(Constants.CT_FHIR_JSON + "; charset=UTF-8", ct.getValue());
diff --git a/hapi-fhir-structures-dstu2/.gitignore b/hapi-fhir-structures-dstu2/.gitignore
index 3f6aa3cd273..69d045b5132 100644
--- a/hapi-fhir-structures-dstu2/.gitignore
+++ b/hapi-fhir-structures-dstu2/.gitignore
@@ -10,3 +10,4 @@
/target/
/target/
/target/
+/target/
diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/client/GenericClientTestDstu2.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/client/GenericClientTestDstu2.java
index 676f7d8b741..06590c5ac78 100644
--- a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/client/GenericClientTestDstu2.java
+++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/client/GenericClientTestDstu2.java
@@ -1,11 +1,13 @@
package ca.uhn.fhir.rest.client;
-import static org.hamcrest.Matchers.*;
-import static org.junit.Assert.*;
-import static org.mockito.Mockito.*;
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
import java.io.IOException;
-import java.io.Reader;
+import java.io.InputStream;
import java.io.StringReader;
import java.nio.charset.Charset;
import java.util.ArrayList;
@@ -34,7 +36,6 @@ import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu2.resource.Parameters;
import ca.uhn.fhir.model.dstu2.resource.Patient;
-import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.rest.server.Constants;
@@ -58,6 +59,82 @@ public class GenericClientTestDstu2 {
myHttpResponse = mock(HttpResponse.class, new ReturnsDeepStubs());
}
+ private String getPatientFeedWithOneResult() {
+ //@formatter:off
+ String msg = "\n" +
+ "d039f91a-cc3c-4013-988e-af4d8d0614bd \n" +
+ "\n" +
+ ""
+ + ""
+ + "John Cardinal: 444333333
"
+ + " "
+ + " "
+ + " "
+ + " "
+ + " "
+ + " "
+ + " \n"
+ + " \n"
+ + "";
+ //@formatter:on
+ return msg;
+ }
+
+ @Test
+ public void testHistory() throws Exception {
+
+ final String msg = getPatientFeedWithOneResult();
+
+ ArgumentCaptor capt = ArgumentCaptor.forClass(HttpUriRequest.class);
+ when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
+ when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
+ when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
+ when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer() {
+ @Override
+ public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
+ return new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8"));
+ }});
+
+ IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
+
+ int idx = 0;
+ ca.uhn.fhir.model.dstu2.resource.Bundle response;
+
+ //@formatter:off
+ response = client
+ .history()
+ .ofServer()
+ .andReturnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class)
+ .execute();
+ //@formatter:on
+ assertEquals("http://example.com/fhir/_history", capt.getAllValues().get(idx).getURI().toString());
+ assertEquals(1, response.getEntry().size());
+ idx++;
+
+ //@formatter:off
+ response = client
+ .history()
+ .ofType(Patient.class)
+ .andReturnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class)
+ .execute();
+ //@formatter:on
+ assertEquals("http://example.com/fhir/Patient/_history", capt.getAllValues().get(idx).getURI().toString());
+ assertEquals(1, response.getEntry().size());
+ idx++;
+
+ //@formatter:off
+ response = client
+ .history()
+ .ofInstance(new IdDt("Patient", "123"))
+ .andReturnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class)
+ .execute();
+ //@formatter:on
+ assertEquals("http://example.com/fhir/Patient/123/_history", capt.getAllValues().get(idx).getURI().toString());
+ assertEquals(1, response.getEntry().size());
+ idx++;
+ }
+
+
@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\"}]}}]}";
diff --git a/pom.xml b/pom.xml
index 2bf5f85cdd3..6e596d7739c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -761,7 +761,7 @@
restful-server-example-test
hapi-fhir-testpage-overlay
hapi-fhir-jpaserver-uhnfhirtest
-
+ hapi-fhir-android
hapi-fhir-dist
diff --git a/src/site/xdoc/doc_rest_client.xml b/src/site/xdoc/doc_rest_client.xml
index 3d79cd3b349..e7a2160cc09 100644
--- a/src/site/xdoc/doc_rest_client.xml
+++ b/src/site/xdoc/doc_rest_client.xml
@@ -74,7 +74,7 @@
-
+
Searching for resources is probably the most common initial scenario for
@@ -186,7 +186,7 @@
-
+
The following example shows how to perform a create
operation using the generic client:
@@ -211,7 +211,7 @@
-
+
Given a resource name and ID, it is simple to retrieve
the latest version of that resource (a 'read')
@@ -249,7 +249,7 @@
-
+
The following example shows how to perform a delete
operation using the generic client:
@@ -275,7 +275,7 @@
-
+
Updating a resource is similar to creating one, except that
an ID must be supplied since you are updating a previously
@@ -315,7 +315,54 @@
-
+
+
+ To retrieve the version history of all resources, or all resources of a given type, or
+ of a specific instance of a resource, you call the history()
+ method.
+
+
+
+
+
+
+
+ If you are using a DSTU2 compliant server, you should instead use the
+ Bundle resource which is found in the DSTU2 structures JAR, as shown
+ in the syntax below. Note that in both cases, the class name is Bundle
,
+ but the DSTU2 bundle is found in the .resources.
package.
+
+
+
+
+
+
+
+ You can also optionally request that only resource versions
+ later than a given date, and/or only up to a given count (number)
+ of resource versions be returned.
+
+
+
+
+
+
+
+
+
+ The following example shows how to execute a transaction using the generic client:
+
+
+
+
+
+
+
+
To retrieve the server's conformance statement, simply call the conformance()
method as shown below.
@@ -326,18 +373,7 @@
value="examples/src/main/java/example/GenericClientExample.java" />
-
-
-
- The following example shows how to execute a transaction using the generic client:
-
-
-
-
-
-
-
+