Add paging methods to generic client for DSTU2 bundle
This commit is contained in:
parent
ec3c94a823
commit
e22f52ca44
|
@ -6,9 +6,9 @@ import java.util.List;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.model.api.Bundle;
|
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
||||||
|
import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Conformance;
|
import ca.uhn.fhir.model.dstu2.resource.Conformance;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Observation;
|
import ca.uhn.fhir.model.dstu2.resource.Observation;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.OperationOutcome;
|
import ca.uhn.fhir.model.dstu2.resource.OperationOutcome;
|
||||||
|
@ -36,7 +36,7 @@ public class GenericClientExample {
|
||||||
IGenericClient client = ctx.newRestfulGenericClient(serverBase);
|
IGenericClient client = ctx.newRestfulGenericClient(serverBase);
|
||||||
|
|
||||||
// Perform a search
|
// Perform a search
|
||||||
Bundle results = client
|
ca.uhn.fhir.model.api.Bundle results = client
|
||||||
.search()
|
.search()
|
||||||
.forResource(Patient.class)
|
.forResource(Patient.class)
|
||||||
.where(Patient.FAMILY.matches().value("duck"))
|
.where(Patient.FAMILY.matches().value("duck"))
|
||||||
|
@ -48,7 +48,7 @@ public class GenericClientExample {
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public static void fluentSearch() {
|
public static void fluentSearch() {
|
||||||
FhirContext ctx = new FhirContext();
|
FhirContext ctx = FhirContext.forDstu2();
|
||||||
IGenericClient client = ctx.newRestfulGenericClient("http://fhir.healthintersections.com.au/open");
|
IGenericClient client = ctx.newRestfulGenericClient("http://fhir.healthintersections.com.au/open");
|
||||||
{
|
{
|
||||||
// START SNIPPET: create
|
// START SNIPPET: create
|
||||||
|
@ -205,6 +205,7 @@ public class GenericClientExample {
|
||||||
.forResource(Patient.class)
|
.forResource(Patient.class)
|
||||||
.where(Patient.BIRTHDATE.beforeOrEquals().day("2011-01-01"))
|
.where(Patient.BIRTHDATE.beforeOrEquals().day("2011-01-01"))
|
||||||
.and(Patient.CAREPROVIDER.hasChainedProperty(Organization.NAME.matches().value("Health")))
|
.and(Patient.CAREPROVIDER.hasChainedProperty(Organization.NAME.matches().value("Health")))
|
||||||
|
.returnBundle(Bundle.class)
|
||||||
.execute();
|
.execute();
|
||||||
// END SNIPPET: search
|
// END SNIPPET: search
|
||||||
|
|
||||||
|
@ -212,6 +213,7 @@ public class GenericClientExample {
|
||||||
response = client.search()
|
response = client.search()
|
||||||
.forResource(Patient.class)
|
.forResource(Patient.class)
|
||||||
.where(Patient.FAMILY.matches().values("Smith", "Smyth"))
|
.where(Patient.FAMILY.matches().values("Smith", "Smyth"))
|
||||||
|
.returnBundle(Bundle.class)
|
||||||
.execute();
|
.execute();
|
||||||
// END SNIPPET: searchOr
|
// END SNIPPET: searchOr
|
||||||
|
|
||||||
|
@ -221,6 +223,7 @@ public class GenericClientExample {
|
||||||
.where(Patient.ADDRESS.matches().values("Toronto"))
|
.where(Patient.ADDRESS.matches().values("Toronto"))
|
||||||
.and(Patient.ADDRESS.matches().values("Ontario"))
|
.and(Patient.ADDRESS.matches().values("Ontario"))
|
||||||
.and(Patient.ADDRESS.matches().values("Canada"))
|
.and(Patient.ADDRESS.matches().values("Canada"))
|
||||||
|
.returnBundle(Bundle.class)
|
||||||
.execute();
|
.execute();
|
||||||
// END SNIPPET: searchAnd
|
// END SNIPPET: searchAnd
|
||||||
|
|
||||||
|
@ -229,6 +232,7 @@ public class GenericClientExample {
|
||||||
.forResource(Patient.class)
|
.forResource(Patient.class)
|
||||||
.withIdAndCompartment("123", "condition")
|
.withIdAndCompartment("123", "condition")
|
||||||
.where(Patient.ADDRESS.matches().values("Toronto"))
|
.where(Patient.ADDRESS.matches().values("Toronto"))
|
||||||
|
.returnBundle(Bundle.class)
|
||||||
.execute();
|
.execute();
|
||||||
// END SNIPPET: searchCompartment
|
// END SNIPPET: searchCompartment
|
||||||
|
|
||||||
|
@ -241,6 +245,7 @@ public class GenericClientExample {
|
||||||
.include(Patient.INCLUDE_ORGANIZATION)
|
.include(Patient.INCLUDE_ORGANIZATION)
|
||||||
.sort().ascending(Patient.BIRTHDATE)
|
.sort().ascending(Patient.BIRTHDATE)
|
||||||
.sort().descending(Patient.NAME).limitTo(123)
|
.sort().descending(Patient.NAME).limitTo(123)
|
||||||
|
.returnBundle(Bundle.class)
|
||||||
.execute();
|
.execute();
|
||||||
// END SNIPPET: searchAdv
|
// END SNIPPET: searchAdv
|
||||||
|
|
||||||
|
@ -249,6 +254,7 @@ public class GenericClientExample {
|
||||||
.forResource("Patient")
|
.forResource("Patient")
|
||||||
.where(Patient.NAME.matches().value("Tester"))
|
.where(Patient.NAME.matches().value("Tester"))
|
||||||
.usingStyle(SearchStyleEnum.POST)
|
.usingStyle(SearchStyleEnum.POST)
|
||||||
|
.returnBundle(Bundle.class)
|
||||||
.execute();
|
.execute();
|
||||||
// END SNIPPET: searchPost
|
// END SNIPPET: searchPost
|
||||||
|
|
||||||
|
@ -258,16 +264,9 @@ public class GenericClientExample {
|
||||||
.where(Observation.CODE_VALUE_DATE
|
.where(Observation.CODE_VALUE_DATE
|
||||||
.withLeft(Observation.CODE.exactly().code("FOO$BAR"))
|
.withLeft(Observation.CODE.exactly().code("FOO$BAR"))
|
||||||
.withRight(Observation.VALUE_DATE.exactly().day("2001-01-01")))
|
.withRight(Observation.VALUE_DATE.exactly().day("2001-01-01")))
|
||||||
|
.returnBundle(Bundle.class)
|
||||||
.execute();
|
.execute();
|
||||||
// END SNIPPET: searchComposite
|
// END SNIPPET: searchComposite
|
||||||
|
|
||||||
// START SNIPPET: searchPaging
|
|
||||||
if (response.getLinkNext().isEmpty() == false) {
|
|
||||||
|
|
||||||
// load next page
|
|
||||||
Bundle nextPage = client.loadPage().next(response).execute();
|
|
||||||
}
|
|
||||||
// END SNIPPET: searchPaging
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
// START SNIPPET: transaction
|
// START SNIPPET: transaction
|
||||||
|
@ -330,7 +329,7 @@ public class GenericClientExample {
|
||||||
public static void history() {
|
public static void history() {
|
||||||
IGenericClient client = FhirContext.forDstu2().newRestfulGenericClient("");
|
IGenericClient client = FhirContext.forDstu2().newRestfulGenericClient("");
|
||||||
{
|
{
|
||||||
Bundle response;
|
ca.uhn.fhir.model.api.Bundle response;
|
||||||
// START SNIPPET: historyDstu1
|
// START SNIPPET: historyDstu1
|
||||||
response = client
|
response = client
|
||||||
.history()
|
.history()
|
||||||
|
@ -364,8 +363,30 @@ public class GenericClientExample {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
operation();
|
paging();
|
||||||
}
|
}
|
||||||
|
private static void paging() {
|
||||||
|
{
|
||||||
|
// START SNIPPET: searchPaging
|
||||||
|
FhirContext ctx = FhirContext.forDstu2();
|
||||||
|
IGenericClient client = ctx.newRestfulGenericClient("http://fhirtest.uhn.ca/baseDstu2");
|
||||||
|
|
||||||
|
// Perform a search
|
||||||
|
Bundle results = client.search()
|
||||||
|
.forResource(Patient.class)
|
||||||
|
.where(Patient.NAME.matches().value("Smith"))
|
||||||
|
.returnBundle(Bundle.class)
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
if (results.getLink(Bundle.LINK_NEXT) != null) {
|
||||||
|
|
||||||
|
// load next page
|
||||||
|
Bundle nextPage = client.loadPage().next(results).execute();
|
||||||
|
}
|
||||||
|
// END SNIPPET: searchPaging
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private static void operationHttpGet() {
|
private static void operationHttpGet() {
|
||||||
// START SNIPPET: operationHttpGet
|
// START SNIPPET: operationHttpGet
|
||||||
|
@ -410,6 +431,17 @@ public class GenericClientExample {
|
||||||
.named("$everything")
|
.named("$everything")
|
||||||
.withParameters(inParams)
|
.withParameters(inParams)
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note that the $everything operation returns a Bundle instead
|
||||||
|
* of a Parameters resource. The client operation methods return a
|
||||||
|
* Parameters instance however, so HAPI creates a Parameters object
|
||||||
|
* with a single parameter containing the value.
|
||||||
|
*/
|
||||||
|
Bundle responseBundle = (Bundle) outParams.getParameter().get(0).getResource();
|
||||||
|
|
||||||
|
// Print the response bundle
|
||||||
|
System.out.println(ctx.newXmlParser().setPrettyPrint(true).encodeResourceToString(responseBundle));
|
||||||
// END SNIPPET: operation
|
// END SNIPPET: operation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ import org.hl7.fhir.instance.model.api.IBaseConformance;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
|
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
|
||||||
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
|
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
|
||||||
|
@ -79,6 +80,7 @@ import ca.uhn.fhir.rest.gclient.IFetchConformanceTyped;
|
||||||
import ca.uhn.fhir.rest.gclient.IFetchConformanceUntyped;
|
import ca.uhn.fhir.rest.gclient.IFetchConformanceUntyped;
|
||||||
import ca.uhn.fhir.rest.gclient.IGetPage;
|
import ca.uhn.fhir.rest.gclient.IGetPage;
|
||||||
import ca.uhn.fhir.rest.gclient.IGetPageTyped;
|
import ca.uhn.fhir.rest.gclient.IGetPageTyped;
|
||||||
|
import ca.uhn.fhir.rest.gclient.IGetPageUntyped;
|
||||||
import ca.uhn.fhir.rest.gclient.IGetTags;
|
import ca.uhn.fhir.rest.gclient.IGetTags;
|
||||||
import ca.uhn.fhir.rest.gclient.IHistory;
|
import ca.uhn.fhir.rest.gclient.IHistory;
|
||||||
import ca.uhn.fhir.rest.gclient.IHistoryTyped;
|
import ca.uhn.fhir.rest.gclient.IHistoryTyped;
|
||||||
|
@ -402,7 +404,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||||
if (def == null) {
|
if (def == null) {
|
||||||
throw new IllegalArgumentException(myContext.getLocalizer().getMessage(I18N_CANNOT_DETEMINE_RESOURCE_TYPE, theUrl.getValueAsString()));
|
throw new IllegalArgumentException(myContext.getLocalizer().getMessage(I18N_CANNOT_DETEMINE_RESOURCE_TYPE, theUrl.getValueAsString()));
|
||||||
}
|
}
|
||||||
return (IBaseResource) read(def.getImplementingClass(), id);
|
return read(def.getImplementingClass(), id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -841,23 +843,33 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class GetPageInternal extends BaseClientExecutable<IGetPageTyped, Bundle> implements IGetPageTyped {
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||||
|
private class GetPageInternal extends BaseClientExecutable<IGetPageTyped<Object>, Object> implements IGetPageTyped<Object> {
|
||||||
|
|
||||||
private String myUrl;
|
private String myUrl;
|
||||||
|
private Class<? extends IBaseBundle> myBundleType;
|
||||||
|
|
||||||
public GetPageInternal(String theUrl) {
|
public GetPageInternal(String theUrl) {
|
||||||
myUrl = theUrl;
|
myUrl = theUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public GetPageInternal(String theUrl, Class<? extends IBaseBundle> theBundleType) {
|
||||||
public Bundle execute() {
|
myUrl = theUrl;
|
||||||
|
myBundleType = theBundleType;
|
||||||
|
}
|
||||||
|
|
||||||
BundleResponseHandler binding = new BundleResponseHandler(null);
|
@Override
|
||||||
|
public Object execute() {
|
||||||
|
IClientResponseHandler binding;
|
||||||
|
if (myBundleType == null) {
|
||||||
|
binding = new BundleResponseHandler(null);
|
||||||
|
} else {
|
||||||
|
binding = new ResourceResponseHandler(myBundleType, null);
|
||||||
|
}
|
||||||
HttpSimpleGetClientInvocation invocation = new HttpSimpleGetClientInvocation(myUrl);
|
HttpSimpleGetClientInvocation invocation = new HttpSimpleGetClientInvocation(myUrl);
|
||||||
|
|
||||||
Map<String, List<String>> params = null;
|
Map<String, List<String>> params = null;
|
||||||
return invoke(params, binding, invocation);
|
return invoke(params, binding, invocation);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1022,7 +1034,12 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class LoadPageInternal implements IGetPage {
|
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||||
|
private final class LoadPageInternal implements IGetPage, IGetPageUntyped {
|
||||||
|
|
||||||
|
private static final String PREVIOUS = "previous";
|
||||||
|
private static final String PREV = "prev";
|
||||||
|
private String myPageUrl;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IGetPageTyped next(Bundle theBundle) {
|
public IGetPageTyped next(Bundle theBundle) {
|
||||||
|
@ -1039,6 +1056,64 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||||
return new GetPageInternal(thePageUrl);
|
return new GetPageInternal(thePageUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T extends IBaseBundle> IGetPageTyped<T> next(T theBundle) {
|
||||||
|
return nextOrPrevious("next", theBundle);
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T extends IBaseBundle> IGetPageTyped<T> nextOrPrevious(String theWantRel, T theBundle) {
|
||||||
|
RuntimeResourceDefinition def = myContext.getResourceDefinition(theBundle);
|
||||||
|
List<IBase> links = def.getChildByName("link").getAccessor().getValues(theBundle);
|
||||||
|
if (links == null || links.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException(myContext.getLocalizer().getMessage(GenericClient.class, "noPagingLinkFoundInBundle", theWantRel));
|
||||||
|
}
|
||||||
|
for (IBase nextLink : links) {
|
||||||
|
BaseRuntimeElementCompositeDefinition linkDef = (BaseRuntimeElementCompositeDefinition) myContext.getElementDefinition(nextLink.getClass());
|
||||||
|
List<IBase> rel = linkDef.getChildByName("relation").getAccessor().getValues(nextLink);
|
||||||
|
if (rel == null || rel.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String relation = ((IPrimitiveType<?>)rel.get(0)).getValueAsString();
|
||||||
|
if (theWantRel.equals(relation) || (theWantRel == PREVIOUS && PREV.equals(relation))) {
|
||||||
|
List<IBase> urls = linkDef.getChildByName("url").getAccessor().getValues(nextLink);
|
||||||
|
if (urls == null || urls.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String url = ((IPrimitiveType<?>)urls.get(0)).getValueAsString();
|
||||||
|
if (isBlank(url)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return (IGetPageTyped<T>) byUrl(url).andReturnBundle(theBundle.getClass());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException(myContext.getLocalizer().getMessage(GenericClient.class, "noPagingLinkFoundInBundle", theWantRel));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T extends IBaseBundle> IGetPageTyped<T> previous(T theBundle) {
|
||||||
|
return nextOrPrevious(PREVIOUS, theBundle);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IGetPageUntyped byUrl(String thePageUrl) {
|
||||||
|
if (isBlank(thePageUrl)) {
|
||||||
|
throw new IllegalArgumentException("thePagingUrl must not be blank or null");
|
||||||
|
}
|
||||||
|
myPageUrl = thePageUrl;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IGetPageTyped andReturnDstu1Bundle() {
|
||||||
|
return new GetPageInternal(myPageUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T extends IBaseBundle> IGetPageTyped andReturnBundle(Class<T> theBundleType) {
|
||||||
|
Validate.notNull(theBundleType, "theBundleType must not be null");
|
||||||
|
return new GetPageInternal(myPageUrl, theBundleType);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
|
@ -1326,7 +1401,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||||
ResourceResponseHandler<IBaseResource> handler = new ResourceResponseHandler<IBaseResource>((Class<IBaseResource>) bundleType, null);
|
ResourceResponseHandler<IBaseResource> handler = new ResourceResponseHandler<IBaseResource>((Class<IBaseResource>) bundleType, null);
|
||||||
IBaseResource response = handler.invokeClient(theResponseMimeType, theResponseReader, theResponseStatusCode, theHeaders);
|
IBaseResource response = handler.invokeClient(theResponseMimeType, theResponseReader, theResponseStatusCode, theHeaders);
|
||||||
IVersionSpecificBundleFactory bundleFactory = myContext.newBundleFactory();
|
IVersionSpecificBundleFactory bundleFactory = myContext.newBundleFactory();
|
||||||
bundleFactory.initializeWithBundleResource((IBaseResource) response);
|
bundleFactory.initializeWithBundleResource(response);
|
||||||
return bundleFactory.toListOfResources();
|
return bundleFactory.toListOfResources();
|
||||||
} else {
|
} else {
|
||||||
return new ArrayList<IBaseResource>(new BundleResponseHandler(myType).invokeClient(theResponseMimeType, theResponseReader, theResponseStatusCode, theHeaders).toListOfResources());
|
return new ArrayList<IBaseResource>(new BundleResponseHandler(myType).invokeClient(theResponseMimeType, theResponseReader, theResponseStatusCode, theHeaders).toListOfResources());
|
||||||
|
|
|
@ -20,14 +20,51 @@ package ca.uhn.fhir.rest.gclient;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||||
|
|
||||||
import ca.uhn.fhir.model.api.Bundle;
|
import ca.uhn.fhir.model.api.Bundle;
|
||||||
|
|
||||||
public interface IGetPage {
|
public interface IGetPage {
|
||||||
|
|
||||||
IGetPageTyped previous(Bundle theBundle);
|
/**
|
||||||
|
* Load the next page of results using the link with relation "next" in the bundle. This
|
||||||
|
* method accepts a DSTU1 Atom Bundle
|
||||||
|
*/
|
||||||
|
IGetPageTyped<Bundle> next(Bundle theBundle);
|
||||||
|
|
||||||
IGetPageTyped next(Bundle theBundle);
|
/**
|
||||||
|
* Load the next page of results using the link with relation "next" in the bundle. This
|
||||||
|
* method accepts a DSTU2 Bundle resource
|
||||||
|
*
|
||||||
|
* @since 1.1
|
||||||
|
*/
|
||||||
|
<T extends IBaseBundle> IGetPageTyped<T> next(T theBundle);
|
||||||
|
|
||||||
IGetPageTyped url(String thePageUrl);
|
/**
|
||||||
|
* Load the previous page of results using the link with relation "previous" in the bundle. This
|
||||||
|
* method accepts a DSTU1 Atom Bundle
|
||||||
|
*/
|
||||||
|
IGetPageTyped<Bundle> previous(Bundle theBundle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load the previous page of results using the link with relation "prev" in the bundle. This
|
||||||
|
* method accepts a DSTU2+ Bundle resource
|
||||||
|
*
|
||||||
|
* @since 1.1
|
||||||
|
*/
|
||||||
|
<T extends IBaseBundle> IGetPageTyped<T> previous(T theBundle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a page of results using the a given URL and return a DSTU1 Atom bundle
|
||||||
|
*
|
||||||
|
* @deprecated Use {@link #byUrl(String)} instead
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
IGetPageTyped<Bundle> url(String thePageUrl);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a page of results using the a given URL and return a DSTU1 Atom bundle
|
||||||
|
*/
|
||||||
|
IGetPageUntyped byUrl(String thePageUrl);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,8 @@ package ca.uhn.fhir.rest.gclient;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import ca.uhn.fhir.model.api.Bundle;
|
|
||||||
|
|
||||||
public interface IGetPageTyped extends IClientExecutable<IGetPageTyped, Bundle> {
|
public interface IGetPageTyped<T> extends IClientExecutable<IGetPageTyped<T>, T> {
|
||||||
|
|
||||||
// nothing for now
|
// nothing for now
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
package ca.uhn.fhir.rest.gclient;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR - Core Library
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 - 2015 University Health Network
|
||||||
|
* %%
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.model.api.Bundle;
|
||||||
|
|
||||||
|
public interface IGetPageUntyped {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a DSTU1 Atom feed
|
||||||
|
*/
|
||||||
|
IGetPageTyped<Bundle> andReturnDstu1Bundle();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a Bundle resource of the given type
|
||||||
|
*/
|
||||||
|
<T extends IBaseBundle> IGetPageTyped<T> andReturnBundle(Class<T> theBundleType);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -35,7 +35,7 @@ public interface IBaseBundle extends IBaseResource {
|
||||||
* link.type field to indicate that the given link is for
|
* link.type field to indicate that the given link is for
|
||||||
* the previous page of results.
|
* the previous page of results.
|
||||||
*/
|
*/
|
||||||
public static final String LINK_PREV = "prev";
|
public static final String LINK_PREV = "previous";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constant for links provided in the bundle. This constant is used in the
|
* Constant for links provided in the bundle. This constant is used in the
|
||||||
|
|
|
@ -6,6 +6,7 @@ ca.uhn.fhir.context.FhirContext.noStructuresForSpecifiedVersion=Could not find t
|
||||||
|
|
||||||
ca.uhn.fhir.context.RuntimeResourceDefinition.nonInstantiableType=Resource type "{0}" can not be instantiated. Check that this class has a no-argument constructor, and that it is static if it is a nested type. Error is: {1}
|
ca.uhn.fhir.context.RuntimeResourceDefinition.nonInstantiableType=Resource type "{0}" can not be instantiated. Check that this class has a no-argument constructor, and that it is static if it is a nested type. Error is: {1}
|
||||||
|
|
||||||
|
ca.uhn.fhir.rest.client.GenericClient.noPagingLinkFoundInBundle=Can not perform paging operation because no link was found in Bundle with relation "{0}"
|
||||||
ca.uhn.fhir.rest.client.GenericClient.noVersionIdForVread=No version specified in URL for 'vread' operation: {0}
|
ca.uhn.fhir.rest.client.GenericClient.noVersionIdForVread=No version specified in URL for 'vread' operation: {0}
|
||||||
ca.uhn.fhir.rest.client.GenericClient.incompleteUriForRead=The given URI is not an absolute URL and is not usable for this operation: {0}
|
ca.uhn.fhir.rest.client.GenericClient.incompleteUriForRead=The given URI is not an absolute URL and is not usable for this operation: {0}
|
||||||
ca.uhn.fhir.rest.client.GenericClient.cannotDetermineResourceTypeFromUri=Unable to determine the resource type from the given URI: {0}
|
ca.uhn.fhir.rest.client.GenericClient.cannotDetermineResourceTypeFromUri=Unable to determine the resource type from the given URI: {0}
|
||||||
|
|
|
@ -21,6 +21,7 @@ import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
|
||||||
import org.apache.http.client.methods.HttpUriRequest;
|
import org.apache.http.client.methods.HttpUriRequest;
|
||||||
import org.apache.http.message.BasicHeader;
|
import org.apache.http.message.BasicHeader;
|
||||||
import org.apache.http.message.BasicStatusLine;
|
import org.apache.http.message.BasicStatusLine;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
|
@ -32,7 +33,6 @@ import org.mockito.stubbing.Answer;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.model.api.Bundle;
|
import ca.uhn.fhir.model.api.Bundle;
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
|
||||||
import ca.uhn.fhir.model.api.Include;
|
import ca.uhn.fhir.model.api.Include;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Observation;
|
import ca.uhn.fhir.model.dstu2.resource.Observation;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Parameters;
|
import ca.uhn.fhir.model.dstu2.resource.Parameters;
|
||||||
|
@ -57,7 +57,7 @@ public class GenericClientDstu2Test {
|
||||||
public void before() {
|
public void before() {
|
||||||
myHttpClient = mock(HttpClient.class, new ReturnsDeepStubs());
|
myHttpClient = mock(HttpClient.class, new ReturnsDeepStubs());
|
||||||
ourCtx.getRestfulClientFactory().setHttpClient(myHttpClient);
|
ourCtx.getRestfulClientFactory().setHttpClient(myHttpClient);
|
||||||
ourCtx.getRestfulClientFactory().setServerValidationModeEnum(ServerValidationModeEnum.NEVER);
|
ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
|
||||||
myHttpResponse = mock(HttpResponse.class, new ReturnsDeepStubs());
|
myHttpResponse = mock(HttpResponse.class, new ReturnsDeepStubs());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,13 +83,10 @@ public class GenericClientDstu2Test {
|
||||||
.execute();
|
.execute();
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
|
|
||||||
assertEquals(
|
assertEquals("http://example.com/fhir/Patient?_revinclude=Provenance%3Atarget&_format=json", capt.getValue().getURI().toString());
|
||||||
"http://example.com/fhir/Patient?_revinclude=Provenance%3Atarget&_format=json",
|
|
||||||
capt.getValue().getURI().toString());
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private String getPatientFeedWithOneResult() {
|
private String getPatientFeedWithOneResult() {
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
String msg = "<Bundle xmlns=\"http://hl7.org/fhir\">\n" +
|
String msg = "<Bundle xmlns=\"http://hl7.org/fhir\">\n" +
|
||||||
|
@ -615,7 +612,6 @@ public class GenericClientDstu2Test {
|
||||||
// assertEquals("PATIENT2", p2.getName().get(0).getFamily().get(0).getValue());
|
// assertEquals("PATIENT2", p2.getName().get(0).getFamily().get(0).getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTransactionWithString() throws Exception {
|
public void testTransactionWithString() throws Exception {
|
||||||
|
|
||||||
|
@ -638,7 +634,8 @@ public class GenericClientDstu2Test {
|
||||||
@Override
|
@Override
|
||||||
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||||
return new ReaderInputStream(new StringReader(respStringJson), Charset.forName("UTF-8"));
|
return new ReaderInputStream(new StringReader(respStringJson), Charset.forName("UTF-8"));
|
||||||
}});
|
}
|
||||||
|
});
|
||||||
|
|
||||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||||
|
|
||||||
|
@ -671,8 +668,6 @@ public class GenericClientDstu2Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTransactionWithTransactionResource() throws Exception {
|
public void testTransactionWithTransactionResource() throws Exception {
|
||||||
|
|
||||||
|
@ -888,4 +883,101 @@ public class GenericClientDstu2Test {
|
||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPageNext() throws Exception {
|
||||||
|
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||||
|
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||||
|
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 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<ReaderInputStream>() {
|
||||||
|
@Override
|
||||||
|
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||||
|
return new ReaderInputStream(new StringReader(getPatientFeedWithOneResult()), Charset.forName("UTF-8"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||||
|
|
||||||
|
int idx = 0;
|
||||||
|
|
||||||
|
ca.uhn.fhir.model.dstu2.resource.Bundle sourceBundle = new ca.uhn.fhir.model.dstu2.resource.Bundle();
|
||||||
|
sourceBundle.getLinkOrCreate(IBaseBundle.LINK_PREV).setUrl("http://foo.bar/prev");
|
||||||
|
sourceBundle.getLinkOrCreate(IBaseBundle.LINK_NEXT).setUrl("http://foo.bar/next");
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
ca.uhn.fhir.model.dstu2.resource.Bundle resp = client
|
||||||
|
.loadPage()
|
||||||
|
.next(sourceBundle)
|
||||||
|
.execute();
|
||||||
|
//@formatter:on
|
||||||
|
|
||||||
|
assertEquals(1, resp.getEntry().size());
|
||||||
|
assertEquals("http://foo.bar/next", capt.getAllValues().get(idx).getURI().toASCIIString());
|
||||||
|
idx++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPagePrev() throws Exception {
|
||||||
|
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||||
|
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||||
|
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 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<ReaderInputStream>() {
|
||||||
|
@Override
|
||||||
|
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||||
|
return new ReaderInputStream(new StringReader(getPatientFeedWithOneResult()), Charset.forName("UTF-8"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||||
|
|
||||||
|
int idx = 0;
|
||||||
|
|
||||||
|
ca.uhn.fhir.model.dstu2.resource.Bundle sourceBundle = new ca.uhn.fhir.model.dstu2.resource.Bundle();
|
||||||
|
sourceBundle.getLinkOrCreate("previous").setUrl("http://foo.bar/prev");
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
ca.uhn.fhir.model.dstu2.resource.Bundle resp = client
|
||||||
|
.loadPage()
|
||||||
|
.previous(sourceBundle)
|
||||||
|
.execute();
|
||||||
|
//@formatter:on
|
||||||
|
|
||||||
|
assertEquals(1, resp.getEntry().size());
|
||||||
|
assertEquals("http://foo.bar/prev", capt.getAllValues().get(idx).getURI().toASCIIString());
|
||||||
|
idx++;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try with "prev" instead of "previous"
|
||||||
|
*/
|
||||||
|
|
||||||
|
sourceBundle = new ca.uhn.fhir.model.dstu2.resource.Bundle();
|
||||||
|
sourceBundle.getLinkOrCreate("prev").setUrl("http://foo.bar/prev");
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
resp = client
|
||||||
|
.loadPage()
|
||||||
|
.previous(sourceBundle)
|
||||||
|
.execute();
|
||||||
|
//@formatter:on
|
||||||
|
|
||||||
|
assertEquals(1, resp.getEntry().size());
|
||||||
|
assertEquals("http://foo.bar/prev", capt.getAllValues().get(idx).getURI().toASCIIString());
|
||||||
|
idx++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPageNextNoLink() throws Exception {
|
||||||
|
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||||
|
|
||||||
|
ca.uhn.fhir.model.dstu2.resource.Bundle sourceBundle = new ca.uhn.fhir.model.dstu2.resource.Bundle();
|
||||||
|
try {
|
||||||
|
client.loadPage().next(sourceBundle).execute();
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
assertThat(e.getMessage(), containsString("Can not perform paging operation because no link was found in Bundle with relation \"next\""));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<mxfile userAgent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:37.0) Gecko/20100101 Firefox/37.0" type="google"><diagram>5Vnfb6M4EP5r8rgoQAnJY5M2e5XupNX2pLt7dMGAVceOjNk299fvGI8DAdpL24RudC+R/fn3N994PGQSrjbPXxXZFn/IlPJJME2fJ+HNJAhmgQ+/BthZ4CqMLZArlloIexjgnv1LEZwiWrGUlgcdtZRcs+0hmEghaKIPsExyXAIn25LcTd8A9wnhffQvlurCovNg1uC/UZYXbhl/trAtpd65OVKakYrrLzUEbaZ5Q9xc9UbCWyBMSQnTmNLmeUW5Ic0REtIwC2dRtoiiZO7HyRe7/fWx3ffHUFTgVj865dxO+YPwCs95tyQl/U5LWamE9lh4Kpim91sCTeHNEyhjEi4LveFQ86GYSaHvsXddZ5yvJJeqHh3eXN366whwXJUqTVFQx5yt7oMH+0rlhmq1gzE4QzBDNaAiI6w+NRb3rxArWtZ2IiIovHw/c0MkFJDLI3lF/bR4lSr3Ch57WcGUx0SpiUioZ0RkXMsjW+Z9nHrrZr6pl9CTifx3mplzAm8OWUqt5eYQ+450tKA/JSxQA2MYKz7SWA47qbHcndT2gkv0AN+xiKT6Qy4QjuUCoMIuqwnxqkJYF7CyN4sa5b+X7lFoHBLnEI3nESfGmrY4r8XuEvUZdpx+UJ+jXdF++K47+gPcj8Lp596kVz1OaApPMaxKpQuZS0H4bYMulaxESs2U00O+6DPTfxvYM4o0tX+wE7CldrYpqNtM3TTWw0R6rZR8guoDl8mjhdYg9P1o9yCtI6XdstnnG40C57Q6eD2saKJy+tJE9UOhb11FOdHsx+GOTmuqaHRTxb+uqfCS/UVNhXlK66b6BkuaI5/29l8s1uvFYqSwOvhAH+91gunqf71O0lJXgafwxvde4r3F8ZAJRuHzc58p/UzyAjXajaafm0T6b84i30n5KFR+6sPE2ef80e5tAa2btXPyQPlSqpQqp3khhdnM2UIfBpdXQ5/N5T4Q+3DoN8mMOvdfAdz15DTinkxuCrspHNWYHygmZnnXbWs6lD2B7Dd6lGYiSrL5LIzjOIh8EmWOvZb39TRUFmRrikml+G6pSPJoKBwMAS35NLo6WwrrnMh9ne37nvOItuv58xP4Xo/HfgLbJFAzbvh6UFDKTelOaKoyIM5as8010GN6tHgstZKPtOMn7XCBEOEsF1BV9qRLwzWDr8PXiG9YmtYOP2Q3Cb0zXnt0Af0oDDiLybp5nHOFlsmcdU59W/Ys1s+ML1b5x0r/LMrHbHhQ+dM7jN5QXHFSlkbyXXf4vzlB13jOKdpvhulYXoAZwgtPBqR1hDfC2SI/Ptlfj/z1XXD6rBeqzT9lNlo3/zOGtz8B</diagram></mxfile>
|
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
|
@ -47,7 +47,7 @@
|
||||||
-->
|
-->
|
||||||
<!--
|
<!--
|
||||||
-->
|
-->
|
||||||
<link rel="shortcut icon" href="https://github.com/jamesagnew/hapi-fhir/images/favicon.png" />
|
<link rel="shortcut icon" href="http://jamesagnew.github.io/hapi-fhir/images/favicon.png" />
|
||||||
<link rel="stylesheet" type="text/css" href="hapi.css" />
|
<link rel="stylesheet" type="text/css" href="hapi.css" />
|
||||||
|
|
||||||
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" />
|
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" />
|
||||||
|
|
|
@ -16,9 +16,42 @@
|
||||||
different one. These dependencies can cause conflicts and be very irritating to solve.
|
different one. These dependencies can cause conflicts and be very irritating to solve.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<subsection name="Quick Start: Using Logback">
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Unfortunately HAPI is not immune to this issue.
|
If you don't want to spend much time worrying about logging, it's probably
|
||||||
|
easiest to just include the <a href="http://logback.qos.ch/">Logback</a>
|
||||||
|
JAR along with your application.
|
||||||
</p>
|
</p>
|
||||||
|
<p>
|
||||||
|
Logback is a powerful and flexible framework. To configure it, simply
|
||||||
|
include a "logback.xml" file on your classpath. The following contents
|
||||||
|
may be placed in this file to simply log at a suitable level
|
||||||
|
to the console:
|
||||||
|
</p>
|
||||||
|
<source><![CDATA[<configuration scan="true" scanPeriod="30 seconds">
|
||||||
|
|
||||||
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||||
|
<level>INFO</level>
|
||||||
|
</filter>
|
||||||
|
<encoder>
|
||||||
|
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} [%file:%line] %msg%n</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<root level="INFO">
|
||||||
|
<appender-ref ref="STDOUT" />
|
||||||
|
</root>
|
||||||
|
|
||||||
|
</configuration>]]></source>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
For more detail on how logging can be configured, see the
|
||||||
|
following section.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</subsection>
|
||||||
|
|
||||||
<subsection name="Configuring HAPI's Logging - SLF4j">
|
<subsection name="Configuring HAPI's Logging - SLF4j">
|
||||||
|
|
||||||
|
|
|
@ -93,8 +93,24 @@
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Searching for resources is probably the most common initial scenario for
|
Searching for resources is probably the most common initial scenario for
|
||||||
client applications, so we'll start the demonstration there.
|
client applications, so we'll start the demonstration there. The FHIR search
|
||||||
|
operation generally uses a URL with a set of predefined search parameters,
|
||||||
|
and returns a Bundle containing zero-or-more resources which matched the
|
||||||
|
given search criteria.
|
||||||
</p>
|
</p>
|
||||||
|
<p>
|
||||||
|
Search is a very powerful mechanism, with advanced features such as paging,
|
||||||
|
including linked resources, etc. See the FHIR
|
||||||
|
<a href="http://hl7.org/fhir/search.html">search specification</a>
|
||||||
|
for more information.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<notclosed ! colour this section differently>
|
||||||
|
<b>Note on Bundle types: </b> As of DSTU2, FHIR defines Bundle as a resource
|
||||||
|
instead of an Atom feed as it was in DSTU1.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The following example shows how to query using the generic client:
|
The following example shows how to query using the generic client:
|
||||||
</p>
|
</p>
|
||||||
|
|
|
@ -8,8 +8,18 @@
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<section name="Upgrading to HAPI FHIR 0.8">
|
<section name="Upgrading to HAPI 1.1">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
HAPI 1.1 introduces support for the "reference i"
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<img src="./images/hapi-1.1-structs-resource.png" alt="Structures"/>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
|
<section name="Upgrading to HAPI FHIR 0.8">
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<b>This section is still incomplete: </b> Note that HAPI 0.8 has not
|
<b>This section is still incomplete: </b> Note that HAPI 0.8 has not
|
||||||
|
@ -123,8 +133,8 @@
|
||||||
|
|
||||||
</subsection>
|
</subsection>
|
||||||
|
|
||||||
-->
|
|
||||||
</section>
|
</section>
|
||||||
|
-->
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue