package ca.uhn.fhir.rest.client; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.io.InputStream; import java.io.StringReader; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.apache.commons.io.IOUtils; import org.apache.commons.io.input.ReaderInputStream; import org.apache.http.HttpResponse; import org.apache.http.ProtocolVersion; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.message.BasicHeader; import org.apache.http.message.BasicStatusLine; import org.junit.AfterClass; import org.junit.Before; 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.dstu2.resource.Bundle; import ca.uhn.fhir.model.dstu2.resource.Parameters; import ca.uhn.fhir.model.dstu2.resource.Patient; import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.model.primitive.StringDt; import ca.uhn.fhir.rest.annotation.IdParam; import ca.uhn.fhir.rest.annotation.Operation; import ca.uhn.fhir.rest.annotation.OperationParam; import ca.uhn.fhir.rest.client.api.IBasicClient; import ca.uhn.fhir.rest.server.Constants; import ca.uhn.fhir.util.TestUtil; public class OperationClientDstu2Test { private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(OperationClientDstu2Test.class); private FhirContext ourCtx; private HttpClient ourHttpClient; private HttpResponse ourHttpResponse; @AfterClass public static void afterClassClearContext() { TestUtil.clearAllStaticFieldsForUnitTest(); } @Before public void before() { ourCtx = FhirContext.forDstu2(); ourHttpClient = mock(HttpClient.class, new ReturnsDeepStubs()); ourCtx.getRestfulClientFactory().setHttpClient(ourHttpClient); ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER); ourHttpResponse = mock(HttpResponse.class, new ReturnsDeepStubs()); } @Test public void testOpInstance() throws Exception { Parameters outParams = new Parameters(); outParams.addParameter().setName("FOO"); final String retVal = ourCtx.newXmlParser().encodeResourceToString(outParams); ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class); when(ourHttpClient.execute(capt.capture())).thenReturn(ourHttpResponse); when(ourHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK")); when(ourHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8")); when(ourHttpResponse.getEntity().getContent()).thenAnswer(new Answer<InputStream>() { @Override public InputStream answer(InvocationOnMock theInvocation) throws Throwable { return new ReaderInputStream(new StringReader(retVal), Charset.forName("UTF-8")); } }); IOpClient client = ourCtx.newRestfulClient(IOpClient.class, "http://foo"); int idx = 0; Parameters response = client.opInstance(new IdDt("222"), new StringDt("PARAM1str"), new Patient().setActive(true)); assertEquals("FOO", response.getParameter().get(0).getName()); HttpPost value = (HttpPost) capt.getAllValues().get(idx); String requestBody = IOUtils.toString(((HttpPost) value).getEntity().getContent()); IOUtils.closeQuietly(((HttpPost) value).getEntity().getContent()); ourLog.info(requestBody); Parameters request = ourCtx.newXmlParser().parseResource(Parameters.class, requestBody); assertEquals("http://foo/Patient/222/$OP_INSTANCE", value.getURI().toASCIIString()); assertEquals(2, request.getParameter().size()); assertEquals("PARAM1", request.getParameter().get(0).getName()); assertEquals("PARAM1str", ((StringDt) request.getParameter().get(0).getValue()).getValue()); assertEquals("PARAM2", request.getParameter().get(1).getName()); assertEquals(Boolean.TRUE, ((Patient) request.getParameter().get(1).getResource()).getActive()); idx++; } @Test public void testOpInstanceWithBundleReturn() throws Exception { Bundle retResource = new Bundle(); retResource.setTotal(100); // Parameters outParams = new Parameters(); // outParams.addParameter().setName("return").setResource(retResource); final String retVal = ourCtx.newXmlParser().encodeResourceToString(retResource); ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class); when(ourHttpClient.execute(capt.capture())).thenReturn(ourHttpResponse); when(ourHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK")); when(ourHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8")); when(ourHttpResponse.getEntity().getContent()).thenAnswer(new Answer<InputStream>() { @Override public InputStream answer(InvocationOnMock theInvocation) throws Throwable { return new ReaderInputStream(new StringReader(retVal), Charset.forName("UTF-8")); } }); IOpClient client = ourCtx.newRestfulClient(IOpClient.class, "http://foo"); int idx = 0; Bundle response = client.opInstanceWithBundleReturn(new IdDt("222"), new StringDt("PARAM1str"), new Patient().setActive(true)); assertEquals(100, response.getTotal().intValue()); HttpPost value = (HttpPost) capt.getAllValues().get(idx); String requestBody = IOUtils.toString(((HttpPost) value).getEntity().getContent()); IOUtils.closeQuietly(((HttpPost) value).getEntity().getContent()); ourLog.info(requestBody); Parameters request = ourCtx.newXmlParser().parseResource(Parameters.class, requestBody); assertEquals("http://foo/Patient/222/$OP_INSTANCE_WITH_BUNDLE_RETURN", value.getURI().toASCIIString()); assertEquals(2, request.getParameter().size()); assertEquals("PARAM1", request.getParameter().get(0).getName()); assertEquals("PARAM1str", ((StringDt) request.getParameter().get(0).getValue()).getValue()); assertEquals("PARAM2", request.getParameter().get(1).getName()); assertEquals(Boolean.TRUE, ((Patient) request.getParameter().get(1).getResource()).getActive()); idx++; } @Test public void testOpServer() throws Exception { Parameters outParams = new Parameters(); outParams.addParameter().setName("FOO"); final String retVal = ourCtx.newXmlParser().encodeResourceToString(outParams); ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class); when(ourHttpClient.execute(capt.capture())).thenReturn(ourHttpResponse); when(ourHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK")); when(ourHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8")); when(ourHttpResponse.getEntity().getContent()).thenAnswer(new Answer<InputStream>() { @Override public InputStream answer(InvocationOnMock theInvocation) throws Throwable { return new ReaderInputStream(new StringReader(retVal), Charset.forName("UTF-8")); } }); IOpClient client = ourCtx.newRestfulClient(IOpClient.class, "http://foo"); int idx = 0; Parameters response = client.opServer(new StringDt("PARAM1str"), new Patient().setActive(true)); assertEquals("FOO", response.getParameter().get(0).getName()); HttpPost value = (HttpPost) capt.getAllValues().get(idx); String requestBody = IOUtils.toString(((HttpPost) value).getEntity().getContent()); IOUtils.closeQuietly(((HttpPost) value).getEntity().getContent()); ourLog.info(requestBody); Parameters request = ourCtx.newXmlParser().parseResource(Parameters.class, requestBody); assertEquals("http://foo/$OP_SERVER", value.getURI().toASCIIString()); assertEquals(2, request.getParameter().size()); assertEquals("PARAM1", request.getParameter().get(0).getName()); assertEquals("PARAM1str", ((StringDt) request.getParameter().get(0).getValue()).getValue()); assertEquals("PARAM2", request.getParameter().get(1).getName()); assertEquals(Boolean.TRUE, ((Patient) request.getParameter().get(1).getResource()).getActive()); idx++; response = client.opServer(null, new Patient().setActive(true)); assertEquals("FOO", response.getParameter().get(0).getName()); value = (HttpPost) capt.getAllValues().get(idx); requestBody = IOUtils.toString(((HttpPost) value).getEntity().getContent()); IOUtils.closeQuietly(((HttpPost) value).getEntity().getContent()); ourLog.info(requestBody); request = ourCtx.newXmlParser().parseResource(Parameters.class, requestBody); assertEquals(1, request.getParameter().size()); assertEquals("PARAM2", request.getParameter().get(0).getName()); assertEquals(Boolean.TRUE, ((Patient) request.getParameter().get(0).getResource()).getActive()); idx++; response = client.opServer(null, null); assertEquals("FOO", response.getParameter().get(0).getName()); value = (HttpPost) capt.getAllValues().get(idx); requestBody = IOUtils.toString(((HttpPost) value).getEntity().getContent()); IOUtils.closeQuietly(((HttpPost) value).getEntity().getContent()); ourLog.info(requestBody); request = ourCtx.newXmlParser().parseResource(Parameters.class, requestBody); assertEquals(0, request.getParameter().size()); idx++; } @Test public void testOpWithListParam() throws Exception { Parameters outParams = new Parameters(); outParams.addParameter().setName("FOO"); final String retVal = ourCtx.newXmlParser().encodeResourceToString(outParams); ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class); when(ourHttpClient.execute(capt.capture())).thenReturn(ourHttpResponse); when(ourHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK")); when(ourHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8")); when(ourHttpResponse.getEntity().getContent()).thenAnswer(new Answer<InputStream>() { @Override public InputStream answer(InvocationOnMock theInvocation) throws Throwable { return new ReaderInputStream(new StringReader(retVal), Charset.forName("UTF-8")); } }); IOpClient client = ourCtx.newRestfulClient(IOpClient.class, "http://foo"); int idx = 0; Parameters response = client.opServerListParam(new Patient().setActive(true), Arrays.asList(new StringDt("PARAM3str1"), new StringDt("PARAM3str2"))); assertEquals("FOO", response.getParameter().get(0).getName()); HttpPost value = (HttpPost) capt.getAllValues().get(idx); String requestBody = IOUtils.toString(((HttpPost) value).getEntity().getContent()); IOUtils.closeQuietly(((HttpPost) value).getEntity().getContent()); ourLog.info(requestBody); Parameters request = ourCtx.newXmlParser().parseResource(Parameters.class, requestBody); assertEquals("http://foo/$OP_SERVER_LIST_PARAM", value.getURI().toASCIIString()); assertEquals(3, request.getParameter().size()); assertEquals("PARAM2", request.getParameter().get(0).getName()); assertEquals(Boolean.TRUE, ((Patient) request.getParameter().get(0).getResource()).getActive()); assertEquals("PARAM3", request.getParameter().get(1).getName()); assertEquals("PARAM3str1", ((StringDt) request.getParameter().get(1).getValue()).getValue()); assertEquals("PARAM3", request.getParameter().get(2).getName()); assertEquals("PARAM3str2", ((StringDt) request.getParameter().get(2).getValue()).getValue()); idx++; response = client.opServerListParam(null, Arrays.asList(new StringDt("PARAM3str1"), new StringDt("PARAM3str2"))); assertEquals("FOO", response.getParameter().get(0).getName()); value = (HttpPost) capt.getAllValues().get(idx); requestBody = IOUtils.toString(((HttpPost) value).getEntity().getContent()); IOUtils.closeQuietly(((HttpPost) value).getEntity().getContent()); ourLog.info(requestBody); request = ourCtx.newXmlParser().parseResource(Parameters.class, requestBody); assertEquals("http://foo/$OP_SERVER_LIST_PARAM", value.getURI().toASCIIString()); assertEquals(2, request.getParameter().size()); assertEquals("PARAM3", request.getParameter().get(0).getName()); assertEquals("PARAM3str1", ((StringDt) request.getParameter().get(0).getValue()).getValue()); assertEquals("PARAM3", request.getParameter().get(1).getName()); assertEquals("PARAM3str2", ((StringDt) request.getParameter().get(1).getValue()).getValue()); idx++; response = client.opServerListParam(null, new ArrayList<StringDt>()); assertEquals("FOO", response.getParameter().get(0).getName()); value = (HttpPost) capt.getAllValues().get(idx); requestBody = IOUtils.toString(((HttpPost) value).getEntity().getContent()); IOUtils.closeQuietly(((HttpPost) value).getEntity().getContent()); ourLog.info(requestBody); request = ourCtx.newXmlParser().parseResource(Parameters.class, requestBody); assertEquals("http://foo/$OP_SERVER_LIST_PARAM", value.getURI().toASCIIString()); assertEquals(0, request.getParameter().size()); idx++; response = client.opServerListParam(null, null); assertEquals("FOO", response.getParameter().get(0).getName()); value = (HttpPost) capt.getAllValues().get(idx); requestBody = IOUtils.toString(((HttpPost) value).getEntity().getContent()); IOUtils.closeQuietly(((HttpPost) value).getEntity().getContent()); ourLog.info(requestBody); request = ourCtx.newXmlParser().parseResource(Parameters.class, requestBody); assertEquals("http://foo/$OP_SERVER_LIST_PARAM", value.getURI().toASCIIString()); assertEquals(0, request.getParameter().size()); idx++; } @Test public void testOpType() throws Exception { Parameters outParams = new Parameters(); outParams.addParameter().setName("FOO"); final String retVal = ourCtx.newXmlParser().encodeResourceToString(outParams); ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class); when(ourHttpClient.execute(capt.capture())).thenReturn(ourHttpResponse); when(ourHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK")); when(ourHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8")); when(ourHttpResponse.getEntity().getContent()).thenAnswer(new Answer<InputStream>() { @Override public InputStream answer(InvocationOnMock theInvocation) throws Throwable { return new ReaderInputStream(new StringReader(retVal), Charset.forName("UTF-8")); } }); IOpClient client = ourCtx.newRestfulClient(IOpClient.class, "http://foo"); int idx = 0; Parameters response = client.opType(new StringDt("PARAM1str"), new Patient().setActive(true)); assertEquals("FOO", response.getParameter().get(0).getName()); HttpPost value = (HttpPost) capt.getAllValues().get(idx); String requestBody = IOUtils.toString(((HttpPost) value).getEntity().getContent()); IOUtils.closeQuietly(((HttpPost) value).getEntity().getContent()); ourLog.info(requestBody); Parameters request = ourCtx.newXmlParser().parseResource(Parameters.class, requestBody); assertEquals("http://foo/Patient/$OP_TYPE", value.getURI().toASCIIString()); assertEquals(2, request.getParameter().size()); assertEquals("PARAM1", request.getParameter().get(0).getName()); assertEquals("PARAM1str", ((StringDt) request.getParameter().get(0).getValue()).getValue()); assertEquals("PARAM2", request.getParameter().get(1).getName()); assertEquals(Boolean.TRUE, ((Patient) request.getParameter().get(1).getResource()).getActive()); idx++; } public interface IOpClient extends IBasicClient { //@formatter:off @Operation(name="$OP_INSTANCE", type=Patient.class) public Parameters opInstance( @IdParam IdDt theId, @OperationParam(name="PARAM1") StringDt theParam1, @OperationParam(name="PARAM2") Patient theParam2 ); //@formatter:on //@formatter:off @Operation(name="$OP_INSTANCE_WITH_BUNDLE_RETURN", type=Patient.class) public Bundle opInstanceWithBundleReturn( @IdParam IdDt theId, @OperationParam(name="PARAM1") StringDt theParam1, @OperationParam(name="PARAM2") Patient theParam2 ); //@formatter:on //@formatter:off @Operation(name="$OP_SERVER") public Parameters opServer( @OperationParam(name="PARAM1") StringDt theParam1, @OperationParam(name="PARAM2") Patient theParam2 ); //@formatter:on //@formatter:off @Operation(name="$OP_SERVER_LIST_PARAM") public Parameters opServerListParam( @OperationParam(name="PARAM2") Patient theParam2, @OperationParam(name="PARAM3") List<StringDt> theParam3 ); //@formatter:on //@formatter:off @Operation(name="$OP_TYPE", type=Patient.class) public Parameters opType( @OperationParam(name="PARAM1") StringDt theParam1, @OperationParam(name="PARAM2") Patient theParam2 ); //@formatter:on } }