mirror of
https://github.com/hapifhir/hapi-fhir.git
synced 2025-03-09 14:33:32 +00:00
Work on history suport for fluent client
This commit is contained in:
parent
27e126254c
commit
fc4fb07562
@ -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();
|
||||
}
|
||||
|
151
hapi-fhir-android/dependency-reduced-pom.xml
Normal file
151
hapi-fhir-android/dependency-reduced-pom.xml
Normal file
@ -0,0 +1,151 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<version>0.9-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>hapi-fhir-android</artifactId>
|
||||
<name>HAPI FHIR - Android</name>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<version>${maven_failsafe_plugin_version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>integration-test</goal>
|
||||
<goal>verify</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<classpathDependencyScopeExclude>compile+runtime</classpathDependencyScopeExclude>
|
||||
<additionalClasspathElements>
|
||||
<additionalClasspathElement>${project.build.directory}/hapi-fhir-android-${project.version}.jar</additionalClasspathElement>
|
||||
</additionalClasspathElements>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>2.3</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>true</createDependencyReducedPom>
|
||||
<artifactSet>
|
||||
<includes>
|
||||
<include>commons-codec:commons-codec</include>
|
||||
<include>commons-io:commons-io</include>
|
||||
<include>ca.uhn.hapi.fhir:hapi-fhir-base</include>
|
||||
<include>ca.uhn.hapi.fhir:hapi-fhir-structures-dstu</include>
|
||||
<include>ca.uhn.hapi.fhir:hapi-fhir-structures-dstu2</include>
|
||||
<include>org.glassfish:javax.json</include>
|
||||
<include>org.codehaus.woodstox:woodstox-core-asl</include>
|
||||
<include>javax.xml.stream:stax-api</include>
|
||||
<include>org.codehaus.woodstox:stax2-api</include>
|
||||
<include>org.slf4j:slf4j*</include>
|
||||
<include>org.apache.commons:*</include>
|
||||
<include>org.apache.httpcomponents:*</include>
|
||||
<include>org.glassfish:javax.json</include>
|
||||
</includes>
|
||||
</artifactSet>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>javax.xml.stream</pattern>
|
||||
<shadedPattern>ca.uhn.fhir.repackage.javax.xml.stream</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>javax.json</pattern>
|
||||
<shadedPattern>ca.uhn.fhir.repackage.javax.json</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
<filters>
|
||||
<filter>
|
||||
<artifact>ca.uhn.hapi.fhir:hapi-fhir-base</artifact>
|
||||
<excludes>
|
||||
<exclude>ca/uhn/fhir/model/dstu/valueset/**</exclude>
|
||||
<exclude>**/*.java</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
</filters>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>DIST</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>${maven_assembly_plugin_version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<attach>false</attach>
|
||||
<descriptors>
|
||||
<descriptor>${project.basedir}/src/assembly/hapi-fhir-all.xml</descriptor>
|
||||
<descriptor>${project.basedir}/src/assembly/hapi-fhir-jpaserver-example.xml</descriptor>
|
||||
</descriptors>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.phloc</groupId>
|
||||
<artifactId>phloc-schematron</artifactId>
|
||||
<version>2.7.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.phloc</groupId>
|
||||
<artifactId>phloc-commons</artifactId>
|
||||
<version>4.3.5</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>hamcrest-core</artifactId>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
@ -28,6 +28,10 @@
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpcore</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@ -63,17 +67,21 @@
|
||||
<!-- <dependency> <groupId>org.codehaus.woodstox</groupId> <artifactId>stax2-api</artifactId>
|
||||
<version>3.1.4</version> </dependency> -->
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
<version>${commons_codec_version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>${commons_io_version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--
|
||||
Android does not come with the Servlet API bundled, and MethodUtil requires it
|
||||
-->
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>${servlet_api_version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Testing -->
|
||||
<dependency>
|
||||
@ -102,7 +110,7 @@
|
||||
<configuration>
|
||||
<classpathDependencyScopeExclude>compile+runtime</classpathDependencyScopeExclude>
|
||||
<additionalClasspathElements>
|
||||
<additionalClasspathElement>target/hapi-fhir-android-0.9-SNAPSHOT-shaded.jar</additionalClasspathElement>
|
||||
<additionalClasspathElement>${project.build.directory}/hapi-fhir-android-${project.version}.jar</additionalClasspathElement>
|
||||
</additionalClasspathElements>
|
||||
</configuration>
|
||||
<executions>
|
||||
@ -125,7 +133,6 @@
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<shadedArtifactAttached>true</shadedArtifactAttached>
|
||||
<createDependencyReducedPom>true</createDependencyReducedPom>
|
||||
<!--<minimizeJar>true</minimizeJar>-->
|
||||
<artifactSet>
|
||||
@ -158,13 +165,6 @@
|
||||
<filters>
|
||||
<filter>
|
||||
<artifact>ca.uhn.hapi.fhir:hapi-fhir-base</artifact>
|
||||
<!--
|
||||
<includes>
|
||||
<include>**/*.class</include>
|
||||
<include>**/*.properties</include>
|
||||
<include>**/*.html</include>
|
||||
</includes>
|
||||
-->
|
||||
<excludes>
|
||||
<exclude>ca/uhn/fhir/model/dstu/valueset/**</exclude>
|
||||
<exclude>**/*.java</exclude>
|
||||
@ -177,34 +177,4 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>DIST</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>${maven_assembly_plugin_version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<attach>false</attach>
|
||||
<descriptors>
|
||||
<descriptor>${project.basedir}/src/assembly/hapi-fhir-all.xml</descriptor>
|
||||
<descriptor>${project.basedir}/src/assembly/hapi-fhir-jpaserver-example.xml</descriptor>
|
||||
</descriptors>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
</project>
|
||||
|
@ -57,9 +57,10 @@ public class BuiltJarIT {
|
||||
*/
|
||||
@Test
|
||||
public void testJarForDuplicates() throws Exception {
|
||||
Collection<File> files = FileUtils.listFiles(new File("target"), new WildcardFileFilter("*-shaded.jar"), null);
|
||||
String wildcard = "hapi-fhir-android-*.jar";
|
||||
Collection<File> 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) {
|
||||
|
@ -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<byte[]> {
|
||||
@ -46,12 +47,12 @@ public class Base64BinaryDt extends BasePrimitive<byte[]> {
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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 extends IBaseResource> T doReadOrVRead(final Class<T> theType, IdDt theId, boolean theVRead, ICallable<T> 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<T> binding = new ResourceResponseHandler<T>(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 <T extends IResource> Bundle history(final Class<T> 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 extends IBaseResource> T read(final Class<T> 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 extends IBaseResource> T read(final Class<T> 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 extends IBaseResource> T read(Class<T> 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 extends IBaseResource> T doReadOrVRead(final Class<T> theType, IdDt theId, boolean theVRead, ICallable<T> 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<T> binding = new ResourceResponseHandler<T>(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> Z invoke(Map<String, List<String>> theParams, IClientResponseHandler<Z> 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<String, List<String>> theHeaders) throws IOException, BaseServerResponseException {
|
||||
public Bundle invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> 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<ICreateTyped, MethodOutcome> 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<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);
|
||||
}
|
||||
}
|
||||
|
||||
@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<String, List<String>> toParamList() {
|
||||
LinkedHashMap<String, List<String>> retVal = new LinkedHashMap<String, List<String>>();
|
||||
populateParamList(retVal);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class DeleteInternal extends BaseClientExecutable<IDeleteTyped, BaseOperationOutcome> 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<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 {
|
||||
|
||||
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 <T extends IBaseResource> IReadTyped<T> resource(Class<T> 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<IBaseResource> 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<IGetTags, TagList> 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<BaseOperationOutcome> {
|
||||
|
||||
@Override
|
||||
public BaseOperationOutcome invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException, BaseServerResponseException {
|
||||
public BaseOperationOutcome invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> 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<String, List<String>> theHeaders) throws IOException, BaseServerResponseException {
|
||||
public MethodOutcome invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> 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 <T extends IBaseResource> IReadTyped<T> resource(Class<T> 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<IBaseResource> 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<List<IResource>> {
|
||||
|
||||
private Class<? extends IResource> myType;
|
||||
@ -1067,7 +1183,8 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public List<IResource> invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException, BaseServerResponseException {
|
||||
public List<IResource> invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException,
|
||||
BaseServerResponseException {
|
||||
if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
|
||||
Class<? extends IBaseResource> bundleType = myContext.getResourceDefinition("Bundle").getImplementingClass();
|
||||
ResourceResponseHandler<IBaseResource> handler = new ResourceResponseHandler<IBaseResource>((Class<IBaseResource>) bundleType, null);
|
||||
@ -1278,7 +1395,8 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||
private final class TagListResponseHandler implements IClientResponseHandler<TagList> {
|
||||
|
||||
@Override
|
||||
public TagList invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException, BaseServerResponseException {
|
||||
public TagList invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> 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<IUpdateExecutable, MethodOutcome> 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
*/
|
||||
<T extends IResource> Bundle history(Class<T> 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
|
||||
*/
|
||||
<T extends IResource> Bundle history(Class<T> 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 extends IBaseResource> T read(Class<T> 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 extends IBaseResource> T vread(Class<T> theType, String theId, String theVersionId);
|
||||
|
||||
/**
|
||||
* Implementation of the FHIR "extended operations" action
|
||||
*/
|
||||
IOperation operation();
|
||||
|
||||
}
|
||||
|
@ -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<T> {
|
||||
|
||||
/**
|
||||
* 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 <code>theId</code> must be populated with both a resource type and a resource ID at
|
||||
* a minimum.
|
||||
*
|
||||
* @throws IllegalArgumentException If <code>theId</code> does not contain at least a resource type and ID
|
||||
*/
|
||||
T ofInstance(IdDt theId);
|
||||
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package ca.uhn.fhir.rest.gclient;
|
||||
|
||||
public interface IHistory extends IBaseOn<IHistoryUntyped> {
|
||||
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package ca.uhn.fhir.rest.gclient;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
|
||||
public interface IHistoryTyped<T> extends IClientExecutable<IHistoryTyped<T>, T> {
|
||||
|
||||
/**
|
||||
* Request that the server return only resource versions that were created at or after the given time (inclusive)
|
||||
*/
|
||||
IHistoryTyped<T> since(Date theCutoff);
|
||||
|
||||
/**
|
||||
* Request that the server return only resource versions that were created at or after the given time (inclusive)
|
||||
*/
|
||||
IHistoryTyped<T> since(InstantDt theCutoff);
|
||||
|
||||
/**
|
||||
* Request that the server return only up to <code>theCount</code> number of resources
|
||||
*/
|
||||
IHistoryTyped<T> count(Integer theCount);
|
||||
|
||||
|
||||
}
|
@ -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<Bundle> andReturnDstu1Bundle();
|
||||
|
||||
/**
|
||||
* Request that the method return a Bundle resource (such as <code>ca.uhn.fhir.model.dstu2.resource.Bundle</code>).
|
||||
* Use this method if you are accessing a DSTU2+ server.
|
||||
*/
|
||||
<T extends IBaseBundle> IHistoryTyped<T> andReturnBundle(Class<T> theType);
|
||||
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
package ca.uhn.fhir.rest.gclient;
|
||||
|
||||
public interface IOperationOn {
|
||||
public interface IOperationOn extends IBaseOn<IOperationTyped> {
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,7 @@
|
||||
package ca.uhn.fhir.rest.gclient;
|
||||
|
||||
public interface IOperationTyped {
|
||||
|
||||
|
||||
|
||||
}
|
@ -190,7 +190,7 @@ abstract class BaseAddOrDeleteTagsMethodBinding extends BaseMethodBinding<Void>
|
||||
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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -173,7 +173,7 @@ public class GetTagsMethodBinding extends BaseMethodBinding<TagList> {
|
||||
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);
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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<String, EncodingEnum> valToEncoding = new HashMap<String, EncodingEnum>();
|
||||
@ -142,6 +144,8 @@ public class Constants {
|
||||
}
|
||||
|
||||
FORMAT_VAL_TO_ENCODING = Collections.unmodifiableMap(valToEncoding);
|
||||
|
||||
CHARSET_UTF8 = Charset.forName(CHARSETNAME_UTF_8);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
||||
<attribute name="org.eclipse.jst.component.nondependency" value=""/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
|
||||
<attributes>
|
||||
<attribute name="owner.project.facets" value="java"/>
|
||||
</attributes>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<faceted-project>
|
||||
<installed facet="jst.utility" version="1.0"/>
|
||||
<installed facet="java" version="1.6"/>
|
||||
<installed facet="java" version="1.7"/>
|
||||
</faceted-project>
|
||||
|
@ -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<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<InputStream>() {
|
||||
@Override
|
||||
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
return new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8"));
|
||||
}});
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
int idx = 0;
|
||||
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());
|
||||
|
||||
|
1
hapi-fhir-structures-dstu2/.gitignore
vendored
1
hapi-fhir-structures-dstu2/.gitignore
vendored
@ -10,3 +10,4 @@
|
||||
/target/
|
||||
/target/
|
||||
/target/
|
||||
/target/
|
||||
|
@ -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 = "<Bundle xmlns=\"http://hl7.org/fhir\">\n" +
|
||||
"<id>d039f91a-cc3c-4013-988e-af4d8d0614bd</id>\n" +
|
||||
"<entry>\n" +
|
||||
"<resource>"
|
||||
+ "<Patient>"
|
||||
+ "<text><status value=\"generated\" /><div xmlns=\"http://www.w3.org/1999/xhtml\">John Cardinal: 444333333 </div></text>"
|
||||
+ "<identifier><label value=\"SSN\" /><system value=\"http://orionhealth.com/mrn\" /><value value=\"PRP1660\" /></identifier>"
|
||||
+ "<name><use value=\"official\" /><family value=\"Cardinal\" /><given value=\"John\" /></name>"
|
||||
+ "<name><family value=\"Kramer\" /><given value=\"Doe\" /></name>"
|
||||
+ "<telecom><system value=\"phone\" /><value value=\"555-555-2004\" /><use value=\"work\" /></telecom>"
|
||||
+ "<address><use value=\"home\" /><line value=\"2222 Home Street\" /></address><active value=\"true\" />"
|
||||
+ "</Patient>"
|
||||
+ "</resource>\n"
|
||||
+ " </entry>\n"
|
||||
+ "</feed>";
|
||||
//@formatter:on
|
||||
return msg;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHistory() throws Exception {
|
||||
|
||||
final String msg = getPatientFeedWithOneResult();
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<InputStream>() {
|
||||
@Override
|
||||
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
return new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8"));
|
||||
}});
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
int idx = 0;
|
||||
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\"}]}}]}";
|
||||
|
2
pom.xml
2
pom.xml
@ -761,7 +761,7 @@
|
||||
<module>restful-server-example-test</module>
|
||||
<module>hapi-fhir-testpage-overlay</module>
|
||||
<module>hapi-fhir-jpaserver-uhnfhirtest</module>
|
||||
<!--<module>hapi-fhir-android</module>-->
|
||||
<module>hapi-fhir-android</module>
|
||||
<module>hapi-fhir-dist</module>
|
||||
</modules>
|
||||
</profile>
|
||||
|
@ -74,7 +74,7 @@
|
||||
</p>
|
||||
</subsection>
|
||||
|
||||
<subsection name="Type - Search/Query">
|
||||
<subsection name="Search/Query - Type">
|
||||
|
||||
<p>
|
||||
Searching for resources is probably the most common initial scenario for
|
||||
@ -186,7 +186,7 @@
|
||||
|
||||
</subsection>
|
||||
|
||||
<subsection name="Type - Create">
|
||||
<subsection name="Create - Type">
|
||||
<p>
|
||||
The following example shows how to perform a create
|
||||
operation using the generic client:
|
||||
@ -211,7 +211,7 @@
|
||||
</macro>
|
||||
</subsection>
|
||||
|
||||
<subsection name="Instance - Read / VRead">
|
||||
<subsection name="Read/VRead - Instance">
|
||||
<p>
|
||||
Given a resource name and ID, it is simple to retrieve
|
||||
the latest version of that resource (a 'read')
|
||||
@ -249,7 +249,7 @@
|
||||
|
||||
</subsection>
|
||||
|
||||
<subsection name="Instance - Delete">
|
||||
<subsection name="Delete - Instance">
|
||||
<p>
|
||||
The following example shows how to perform a delete
|
||||
operation using the generic client:
|
||||
@ -275,7 +275,7 @@
|
||||
</macro>
|
||||
</subsection>
|
||||
|
||||
<subsection name="Instance - Update">
|
||||
<subsection name="Update - Instance">
|
||||
<p>
|
||||
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 @@
|
||||
|
||||
</subsection>
|
||||
|
||||
<subsection name="Server - Conformance">
|
||||
<subsection name="History - Server/Type/Instance">
|
||||
<p>
|
||||
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 <code>history()</code>
|
||||
method.
|
||||
</p>
|
||||
<macro name="snippet">
|
||||
<param name="id" value="historyDstu1" />
|
||||
<param name="file"
|
||||
value="examples/src/main/java/example/GenericClientExample.java" />
|
||||
</macro>
|
||||
|
||||
<p>
|
||||
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 <code>Bundle</code>,
|
||||
but the DSTU2 bundle is found in the <code>.resources.</code> package.
|
||||
</p>
|
||||
<macro name="snippet">
|
||||
<param name="id" value="historyDstu2" />
|
||||
<param name="file"
|
||||
value="examples/src/main/java/example/GenericClientExample.java" />
|
||||
</macro>
|
||||
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<macro name="snippet">
|
||||
<param name="id" value="historyFeatures" />
|
||||
<param name="file"
|
||||
value="examples/src/main/java/example/GenericClientExample.java" />
|
||||
</macro>
|
||||
</subsection>
|
||||
|
||||
<subsection name="Transaction - Server">
|
||||
<p>
|
||||
The following example shows how to execute a transaction using the generic client:
|
||||
</p>
|
||||
<macro name="snippet">
|
||||
<param name="id" value="transaction" />
|
||||
<param name="file"
|
||||
value="examples/src/main/java/example/GenericClientExample.java" />
|
||||
</macro>
|
||||
</subsection>
|
||||
|
||||
<subsection name="Conformance - Server">
|
||||
<p>
|
||||
To retrieve the server's conformance statement, simply call the <code>conformance()</code>
|
||||
method as shown below.
|
||||
@ -326,18 +373,7 @@
|
||||
value="examples/src/main/java/example/GenericClientExample.java" />
|
||||
</macro>
|
||||
</subsection>
|
||||
|
||||
<subsection name="Server - Transaction">
|
||||
<p>
|
||||
The following example shows how to execute a transaction using the generic client:
|
||||
</p>
|
||||
<macro name="snippet">
|
||||
<param name="id" value="transaction" />
|
||||
<param name="file"
|
||||
value="examples/src/main/java/example/GenericClientExample.java" />
|
||||
</macro>
|
||||
</subsection>
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
<section name="The Annotation-Driven Client">
|
||||
|
Loading…
x
Reference in New Issue
Block a user