Merge branch 'master' of github.com:jamesagnew/hapi-fhir

This commit is contained in:
jamesagnew 2015-03-06 13:36:20 -05:00
commit 6732efc733
5 changed files with 208 additions and 98 deletions

View File

@ -337,7 +337,7 @@ public class GenericClientExample {
// START SNIPPET: historyDstu1
response = client
.history()
.ofServer()
.onServer()
.andReturnDstu1Bundle()
.execute();
// END SNIPPET: historyDstu1
@ -347,7 +347,7 @@ public class GenericClientExample {
// START SNIPPET: historyDstu2
response = client
.history()
.ofServer()
.onServer()
.andReturnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class)
.execute();
// END SNIPPET: historyDstu2
@ -357,7 +357,7 @@ public class GenericClientExample {
// START SNIPPET: historyFeatures
response = client
.history()
.ofServer()
.onServer()
.andReturnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class)
.since(new InstantDt("2012-01-01T12:22:32.038Z"))
.count(100)
@ -384,7 +384,7 @@ public class GenericClientExample {
Parameters outParams = client
.operation()
.ofInstance(new IdDt("Patient", "1"))
.onInstance(new IdDt("Patient", "1"))
.named("$everything")
.withParameters(inParams)
.execute();

View File

@ -36,10 +36,14 @@ import org.apache.commons.lang3.StringUtils;
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.IBase;
import org.hl7.fhir.instance.model.IBaseResource;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IBaseParameters;
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
@ -57,6 +61,7 @@ import ca.uhn.fhir.model.primitive.UriDt;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.client.exceptions.InvalidResponseException;
import ca.uhn.fhir.rest.client.exceptions.NonFhirResponseException;
import ca.uhn.fhir.rest.gclient.IClientExecutable;
import ca.uhn.fhir.rest.gclient.ICreate;
@ -122,83 +127,17 @@ import ca.uhn.fhir.util.ICallable;
*/
public class GenericClient extends BaseClient implements IGenericClient {
@SuppressWarnings("rawtypes")
public class OperationInternal extends BaseClientExecutable implements IOperation, IOperationUnnamed, IOperationUntyped, IOperationUntypedWithInput {
private IdDt myId;
private Class<? extends IBaseResource> myType;
private IBaseParameters myParameters;
private String myOperationName;
@Override
public IOperationUnnamed ofServer() {
return this;
}
@Override
public IOperationUnnamed ofType(Class<? extends IBaseResource> theResourceType) {
myType = theResourceType;
return this;
}
@Override
public IOperationUnnamed ofInstance(IdDt theId) {
myId = theId;
return this;
}
@SuppressWarnings({ "unchecked" })
@Override
public IOperationUntypedWithInput withParameters(IBaseParameters theParameters) {
Validate.notNull(theParameters, "theParameters can not be null");
myParameters = theParameters;
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;
}
HttpPostClientInvocation invocation = OperationMethodBinding.createOperationInvocation(myContext, resourceName, id, myOperationName, myParameters);
IClientResponseHandler handler;
handler = new ResourceResponseHandler(myParameters.getClass(), null);
return invoke(null, handler, invocation);
}
@Override
public IOperationUntyped named(String theName) {
Validate.notBlank(theName, "theName can not be null");
myOperationName =theName;
return this;
}
}
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;
private boolean myLogRequestAndResponse;
/**
* For now, this is a part of the internal API of HAPI - Use with caution as this method may change!
*/
@ -262,6 +201,11 @@ public class GenericClient extends BaseClient implements IGenericClient {
return resp;
}
@Override
public MethodOutcome delete(Class<? extends IResource> theType, String theId) {
return delete(theType, new IdDt(theId));
}
// public IResource read(UriDt url) {
// return read(inferResourceClass(url), url);
// }
@ -275,11 +219,6 @@ public class GenericClient extends BaseClient implements IGenericClient {
// return search(inferResourceClass(url), url);
// }
@Override
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;
@ -395,15 +334,15 @@ public class GenericClient extends BaseClient implements IGenericClient {
}
public boolean isLogRequestAndResponse() {
return myLogRequestAndResponse;
}
// @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;
}
@Override
public IGetPage loadPage() {
return new LoadPageInternal();
@ -411,6 +350,9 @@ public class GenericClient extends BaseClient implements IGenericClient {
@Override
public IOperation operation() {
if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1) == false) {
throw new IllegalStateException("Operations are only supported in FHIR DSTU2 and later. This client was created using a context configured for " + myContext.getVersion().getVersion().name());
}
return new OperationInternal();
}
@ -968,7 +910,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
}
@SuppressWarnings("rawtypes")
public class HistoryInternal extends BaseClientExecutable implements IHistory, IHistoryUntyped, IHistoryTyped {
private class HistoryInternal extends BaseClientExecutable implements IHistory, IHistoryUntyped, IHistoryTyped {
private Integer myCount;
private IdDt myId;
@ -1024,7 +966,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
}
@Override
public IHistoryUntyped ofInstance(IdDt theId) {
public IHistoryUntyped onInstance(IdDt theId) {
if (theId.hasResourceType() == false) {
throw new IllegalArgumentException("Resource ID does not have a resource type: " + theId.getValue());
}
@ -1033,12 +975,12 @@ public class GenericClient extends BaseClient implements IGenericClient {
}
@Override
public IHistoryUntyped ofServer() {
public IHistoryUntyped onServer() {
return this;
}
@Override
public IHistoryUntyped ofType(Class<? extends IBaseResource> theResourceType) {
public IHistoryUntyped onType(Class<? extends IBaseResource> theResourceType) {
myType = theResourceType;
return this;
}
@ -1080,6 +1022,88 @@ public class GenericClient extends BaseClient implements IGenericClient {
}
@SuppressWarnings("rawtypes")
private class OperationInternal extends BaseClientExecutable implements IOperation, IOperationUnnamed, IOperationUntyped, IOperationUntypedWithInput {
private IdDt myId;
private String myOperationName;
private IBaseParameters myParameters;
private Class<? extends IBaseResource> myType;
@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;
}
HttpPostClientInvocation invocation = OperationMethodBinding.createOperationInvocation(myContext, resourceName, id, myOperationName, myParameters);
IClientResponseHandler handler;
handler = new ResourceResponseHandler(myParameters.getClass(), null);
Object retVal = invoke(null, handler, invocation);
if (myContext.getResourceDefinition((IBaseResource)retVal).getName().equals("Parameters")) {
return retVal;
} else {
RuntimeResourceDefinition def = myContext.getResourceDefinition("Parameters");
IBaseResource parameters = def.newInstance();
BaseRuntimeChildDefinition paramChild = def.getChildByName("parameter");
BaseRuntimeElementCompositeDefinition<?> paramChildElem = (BaseRuntimeElementCompositeDefinition<?>) paramChild.getChildByName("parameter");
IBase parameter = paramChildElem.newInstance();
paramChild.getMutator().addValue(parameters, parameter);
BaseRuntimeChildDefinition resourceElem = paramChildElem.getChildByName("resource");
resourceElem.getMutator().addValue(parameter, (IBase) retVal);
return parameters;
}
}
@Override
public IOperationUntyped named(String theName) {
Validate.notBlank(theName, "theName can not be null");
myOperationName =theName;
return this;
}
@Override
public IOperationUnnamed onInstance(IdDt theId) {
myId = theId;
return this;
}
@Override
public IOperationUnnamed onServer() {
return this;
}
@Override
public IOperationUnnamed onType(Class<? extends IBaseResource> theResourceType) {
myType = theResourceType;
return this;
}
@SuppressWarnings({ "unchecked" })
@Override
public IOperationUntypedWithInput withParameters(IBaseParameters theParameters) {
Validate.notNull(theParameters, "theParameters can not be null");
myParameters = theParameters;
return this;
}
}
private final class OperationOutcomeResponseHandler implements IClientResponseHandler<BaseOperationOutcome> {
@Override

View File

@ -9,12 +9,12 @@ public interface IBaseOn<T> {
/**
* Perform the operation across all versions of all resources of all types on the server
*/
T ofServer();
T onServer();
/**
* Perform the operation across all versions of all resources of the given type on the server
*/
T ofType(Class<? extends IBaseResource> theResourceType);
T onType(Class<? extends IBaseResource> theResourceType);
/**
* Perform the operation across all versions of a specific resource (by ID and type) on the server.
@ -23,6 +23,6 @@ public interface IBaseOn<T> {
*
* @throws IllegalArgumentException If <code>theId</code> does not contain at least a resource type and ID
*/
T ofInstance(IdDt theId);
T onInstance(IdDt theId);
}

View File

@ -665,7 +665,7 @@ public class GenericClientTest {
//@formatter:off
response = client
.history()
.ofServer()
.onServer()
.andReturnDstu1Bundle()
.execute();
//@formatter:on
@ -676,7 +676,7 @@ public class GenericClientTest {
//@formatter:off
response = client
.history()
.ofType(Patient.class)
.onType(Patient.class)
.andReturnDstu1Bundle()
.execute();
//@formatter:on
@ -687,7 +687,7 @@ public class GenericClientTest {
//@formatter:off
response = client
.history()
.ofInstance(new IdDt("Patient", "123"))
.onInstance(new IdDt("Patient", "123"))
.andReturnDstu1Bundle()
.execute();
//@formatter:on

View File

@ -105,7 +105,7 @@ public class GenericClientTestDstu2 {
//@formatter:off
response = client
.history()
.ofServer()
.onServer()
.andReturnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class)
.execute();
//@formatter:on
@ -116,7 +116,7 @@ public class GenericClientTestDstu2 {
//@formatter:off
response = client
.history()
.ofType(Patient.class)
.onType(Patient.class)
.andReturnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class)
.execute();
//@formatter:on
@ -127,7 +127,7 @@ public class GenericClientTestDstu2 {
//@formatter:off
response = client
.history()
.ofInstance(new IdDt("Patient", "123"))
.onInstance(new IdDt("Patient", "123"))
.andReturnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class)
.execute();
//@formatter:on
@ -163,7 +163,7 @@ public class GenericClientTestDstu2 {
@Test
public void testOperationWithListOfParameterResponse() throws Exception {
IParser p = ourCtx.newXmlParser();
Parameters inParams = new Parameters();
inParams.addParameter().setValue(new StringDt("STRINGVALIN1"));
inParams.addParameter().setValue(new StringDt("STRINGVALIN2"));
@ -188,15 +188,101 @@ public class GenericClientTestDstu2 {
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
int idx = 0;
Parameters resp = client.operation().ofServer().named("$SOMEOPERATION").withParameters(inParams).execute();
//@formatter:off
Parameters resp = client
.operation()
.onServer()
.named("$SOMEOPERATION")
.withParameters(inParams).execute();
//@formatter:on
assertEquals("http://example.com/fhir/$SOMEOPERATION", capt.getAllValues().get(idx).getURI().toASCIIString());
assertEquals(respString, p.encodeResourceToString(resp));
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());
assertEquals(extractBody(capt, idx), reqString);
assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod());
idx++;
//@formatter:off
resp = client
.operation()
.onType(Patient.class)
.named("$SOMEOPERATION")
.withParameters(inParams).execute();
//@formatter:on
assertEquals("http://example.com/fhir/Patient/$SOMEOPERATION", capt.getAllValues().get(idx).getURI().toASCIIString());
assertEquals(respString, p.encodeResourceToString(resp));
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());
assertEquals(extractBody(capt, idx), reqString);
assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod());
idx++;
//@formatter:off
resp = client
.operation()
.onInstance(new IdDt("Patient", "123"))
.named("$SOMEOPERATION")
.withParameters(inParams).execute();
//@formatter:on
assertEquals("http://example.com/fhir/Patient/123/$SOMEOPERATION", capt.getAllValues().get(idx).getURI().toASCIIString());
assertEquals(respString, p.encodeResourceToString(resp));
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());
assertEquals(extractBody(capt, idx), reqString);
assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod());
idx++;
resp = client.operation().onInstance(new IdDt("http://foo.com/bar/baz/Patient/123/_history/22")).named("$SOMEOPERATION").withParameters(inParams).execute();
// @formatter:on
assertEquals("http://example.com/fhir/Patient/123/$SOMEOPERATION", capt.getAllValues().get(idx).getURI().toASCIIString());
idx++;
}
@Test
public void testOperationWithBundleResponse() throws Exception {
IParser p = ourCtx.newXmlParser();
Parameters inParams = new Parameters();
inParams.addParameter().setValue(new StringDt("STRINGVALIN1"));
inParams.addParameter().setValue(new StringDt("STRINGVALIN2"));
String reqString = p.encodeResourceToString(inParams);
ca.uhn.fhir.model.dstu2.resource.Bundle outParams = new ca.uhn.fhir.model.dstu2.resource.Bundle();
outParams.setTotal(123);
final String respString = p.encodeResourceToString(outParams);
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(respString), Charset.forName("UTF-8"));
}
});
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
int idx = 0;
//@formatter:off
Parameters resp = client
.operation()
.onServer()
.named("$SOMEOPERATION")
.withParameters(inParams).execute();
//@formatter:on
assertEquals("http://example.com/fhir/$SOMEOPERATION", capt.getAllValues().get(idx).getURI().toASCIIString());
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());
assertEquals(extractBody(capt, idx), reqString);
assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod());
assertEquals(1, resp.getParameter().size());
assertEquals(ca.uhn.fhir.model.dstu2.resource.Bundle.class, resp.getParameter().get(0).getResource().getClass());
idx++;
}
@Test