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 ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
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.Observation;
|
||||
import ca.uhn.fhir.model.dstu2.resource.OperationOutcome;
|
||||
|
@ -36,7 +36,7 @@ public class GenericClientExample {
|
|||
IGenericClient client = ctx.newRestfulGenericClient(serverBase);
|
||||
|
||||
// Perform a search
|
||||
Bundle results = client
|
||||
ca.uhn.fhir.model.api.Bundle results = client
|
||||
.search()
|
||||
.forResource(Patient.class)
|
||||
.where(Patient.FAMILY.matches().value("duck"))
|
||||
|
@ -48,7 +48,7 @@ public class GenericClientExample {
|
|||
|
||||
@SuppressWarnings("unused")
|
||||
public static void fluentSearch() {
|
||||
FhirContext ctx = new FhirContext();
|
||||
FhirContext ctx = FhirContext.forDstu2();
|
||||
IGenericClient client = ctx.newRestfulGenericClient("http://fhir.healthintersections.com.au/open");
|
||||
{
|
||||
// START SNIPPET: create
|
||||
|
@ -205,6 +205,7 @@ public class GenericClientExample {
|
|||
.forResource(Patient.class)
|
||||
.where(Patient.BIRTHDATE.beforeOrEquals().day("2011-01-01"))
|
||||
.and(Patient.CAREPROVIDER.hasChainedProperty(Organization.NAME.matches().value("Health")))
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
// END SNIPPET: search
|
||||
|
||||
|
@ -212,6 +213,7 @@ public class GenericClientExample {
|
|||
response = client.search()
|
||||
.forResource(Patient.class)
|
||||
.where(Patient.FAMILY.matches().values("Smith", "Smyth"))
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
// END SNIPPET: searchOr
|
||||
|
||||
|
@ -221,6 +223,7 @@ public class GenericClientExample {
|
|||
.where(Patient.ADDRESS.matches().values("Toronto"))
|
||||
.and(Patient.ADDRESS.matches().values("Ontario"))
|
||||
.and(Patient.ADDRESS.matches().values("Canada"))
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
// END SNIPPET: searchAnd
|
||||
|
||||
|
@ -229,6 +232,7 @@ public class GenericClientExample {
|
|||
.forResource(Patient.class)
|
||||
.withIdAndCompartment("123", "condition")
|
||||
.where(Patient.ADDRESS.matches().values("Toronto"))
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
// END SNIPPET: searchCompartment
|
||||
|
||||
|
@ -241,6 +245,7 @@ public class GenericClientExample {
|
|||
.include(Patient.INCLUDE_ORGANIZATION)
|
||||
.sort().ascending(Patient.BIRTHDATE)
|
||||
.sort().descending(Patient.NAME).limitTo(123)
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
// END SNIPPET: searchAdv
|
||||
|
||||
|
@ -249,6 +254,7 @@ public class GenericClientExample {
|
|||
.forResource("Patient")
|
||||
.where(Patient.NAME.matches().value("Tester"))
|
||||
.usingStyle(SearchStyleEnum.POST)
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
// END SNIPPET: searchPost
|
||||
|
||||
|
@ -258,16 +264,9 @@ public class GenericClientExample {
|
|||
.where(Observation.CODE_VALUE_DATE
|
||||
.withLeft(Observation.CODE.exactly().code("FOO$BAR"))
|
||||
.withRight(Observation.VALUE_DATE.exactly().day("2001-01-01")))
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
// 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
|
||||
|
@ -330,7 +329,7 @@ public class GenericClientExample {
|
|||
public static void history() {
|
||||
IGenericClient client = FhirContext.forDstu2().newRestfulGenericClient("");
|
||||
{
|
||||
Bundle response;
|
||||
ca.uhn.fhir.model.api.Bundle response;
|
||||
// START SNIPPET: historyDstu1
|
||||
response = client
|
||||
.history()
|
||||
|
@ -364,8 +363,30 @@ public class GenericClientExample {
|
|||
}
|
||||
|
||||
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")
|
||||
private static void operationHttpGet() {
|
||||
// START SNIPPET: operationHttpGet
|
||||
|
@ -410,6 +431,17 @@ public class GenericClientExample {
|
|||
.named("$everything")
|
||||
.withParameters(inParams)
|
||||
.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
|
||||
}
|
||||
|
||||
|
|
|
@ -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.IBaseResource;
|
||||
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.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.IGetPage;
|
||||
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.IHistory;
|
||||
import ca.uhn.fhir.rest.gclient.IHistoryTyped;
|
||||
|
@ -402,7 +404,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
if (def == null) {
|
||||
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
|
||||
|
@ -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 Class<? extends IBaseBundle> myBundleType;
|
||||
|
||||
public GetPageInternal(String theUrl) {
|
||||
myUrl = theUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle execute() {
|
||||
public GetPageInternal(String theUrl, Class<? extends IBaseBundle> theBundleType) {
|
||||
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);
|
||||
|
||||
Map<String, List<String>> params = null;
|
||||
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
|
||||
public IGetPageTyped next(Bundle theBundle) {
|
||||
|
@ -1039,6 +1056,64 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
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")
|
||||
|
@ -1326,7 +1401,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
ResourceResponseHandler<IBaseResource> handler = new ResourceResponseHandler<IBaseResource>((Class<IBaseResource>) bundleType, null);
|
||||
IBaseResource response = handler.invokeClient(theResponseMimeType, theResponseReader, theResponseStatusCode, theHeaders);
|
||||
IVersionSpecificBundleFactory bundleFactory = myContext.newBundleFactory();
|
||||
bundleFactory.initializeWithBundleResource((IBaseResource) response);
|
||||
bundleFactory.initializeWithBundleResource(response);
|
||||
return bundleFactory.toListOfResources();
|
||||
} else {
|
||||
return new ArrayList<IBaseResource>(new BundleResponseHandler(myType).invokeClient(theResponseMimeType, theResponseReader, theResponseStatusCode, theHeaders).toListOfResources());
|
||||
|
|
|
@ -20,14 +20,51 @@ package ca.uhn.fhir.rest.gclient;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
|
||||
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%
|
||||
*/
|
||||
|
||||
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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
}
|
|
@ -33,9 +33,9 @@ public interface IBaseBundle extends IBaseResource {
|
|||
/**
|
||||
* Constant for links provided in the bundle. This constant is used in the
|
||||
* 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
|
||||
|
|
|
@ -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.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.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}
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
|
|||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
import org.apache.http.message.BasicHeader;
|
||||
import org.apache.http.message.BasicStatusLine;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
|
@ -32,7 +33,6 @@ import org.mockito.stubbing.Answer;
|
|||
|
||||
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.Include;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Observation;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Parameters;
|
||||
|
@ -57,7 +57,7 @@ public class GenericClientDstu2Test {
|
|||
public void before() {
|
||||
myHttpClient = mock(HttpClient.class, new ReturnsDeepStubs());
|
||||
ourCtx.getRestfulClientFactory().setHttpClient(myHttpClient);
|
||||
ourCtx.getRestfulClientFactory().setServerValidationModeEnum(ServerValidationModeEnum.NEVER);
|
||||
ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
|
||||
myHttpResponse = mock(HttpResponse.class, new ReturnsDeepStubs());
|
||||
}
|
||||
|
||||
|
@ -83,13 +83,10 @@ public class GenericClientDstu2Test {
|
|||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
assertEquals(
|
||||
"http://example.com/fhir/Patient?_revinclude=Provenance%3Atarget&_format=json",
|
||||
capt.getValue().getURI().toString());
|
||||
assertEquals("http://example.com/fhir/Patient?_revinclude=Provenance%3Atarget&_format=json", capt.getValue().getURI().toString());
|
||||
|
||||
}
|
||||
|
||||
|
||||
private String getPatientFeedWithOneResult() {
|
||||
//@formatter:off
|
||||
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());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testTransactionWithString() throws Exception {
|
||||
|
||||
|
@ -638,8 +634,9 @@ public class GenericClientDstu2Test {
|
|||
@Override
|
||||
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
return new ReaderInputStream(new StringReader(respStringJson), Charset.forName("UTF-8"));
|
||||
}});
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
//@formatter:off
|
||||
|
@ -654,7 +651,7 @@ public class GenericClientDstu2Test {
|
|||
IOUtils.closeQuietly(((HttpEntityEnclosingRequest) capt.getValue()).getEntity().getContent());
|
||||
assertEquals(reqStringJson, requestString);
|
||||
assertEquals("application/json+fhir; charset=UTF-8", capt.getValue().getFirstHeader("Content-Type").getValue());
|
||||
|
||||
|
||||
//@formatter:off
|
||||
response = client.transaction()
|
||||
.withBundle(reqStringJson)
|
||||
|
@ -670,9 +667,7 @@ public class GenericClientDstu2Test {
|
|||
assertEquals("application/xml+fhir; charset=UTF-8", capt.getValue().getFirstHeader("Content-Type").getValue());
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testTransactionWithTransactionResource() throws Exception {
|
||||
|
||||
|
@ -808,7 +803,7 @@ public class GenericClientDstu2Test {
|
|||
p.addName().addFamily("FOOFAMILY");
|
||||
|
||||
client.create().resource(p).execute();
|
||||
|
||||
|
||||
assertEquals(1, capt.getAllValues().get(idx).getHeaders(Constants.HEADER_CONTENT_TYPE).length);
|
||||
assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue());
|
||||
assertThat(extractBody(capt, idx), containsString("<family value=\"FOOFAMILY\"/>"));
|
||||
|
@ -817,7 +812,7 @@ public class GenericClientDstu2Test {
|
|||
idx++;
|
||||
|
||||
p.setId("123");
|
||||
|
||||
|
||||
client.create().resource(p).execute();
|
||||
assertEquals(1, capt.getAllValues().get(idx).getHeaders(Constants.HEADER_CONTENT_TYPE).length);
|
||||
assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue());
|
||||
|
@ -888,4 +883,101 @@ public class GenericClientDstu2Test {
|
|||
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" 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.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Unfortunately HAPI is not immune to this issue.
|
||||
</p>
|
||||
<subsection name="Quick Start: Using Logback">
|
||||
|
||||
<p>
|
||||
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>
|
||||
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">
|
||||
|
||||
|
|
|
@ -93,8 +93,24 @@
|
|||
|
||||
<p>
|
||||
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>
|
||||
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>
|
||||
The following example shows how to query using the generic client:
|
||||
</p>
|
||||
|
|
|
@ -8,8 +8,18 @@
|
|||
|
||||
<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>
|
||||
<b>This section is still incomplete: </b> Note that HAPI 0.8 has not
|
||||
|
@ -123,8 +133,8 @@
|
|||
|
||||
</subsection>
|
||||
|
||||
-->
|
||||
</section>
|
||||
-->
|
||||
|
||||
</body>
|
||||
|
||||
|
|
Loading…
Reference in New Issue