add unit tests
This commit is contained in:
parent
1afaea81d6
commit
9f7a104315
|
@ -39,229 +39,58 @@
|
|||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu</artifactId>
|
||||
<version>1.3-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<!-- conformance profile -->
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu2</artifactId>
|
||||
<version>1.3-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-hl7org-dstu2</artifactId>
|
||||
<version>1.3-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-validation-resources-dstu2</artifactId>
|
||||
<version>1.3-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<!-- UNKNOWN -->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.thymeleaf</groupId>
|
||||
<artifactId>thymeleaf</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.phloc</groupId>
|
||||
<artifactId>phloc-schematron</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.phloc</groupId>
|
||||
<artifactId>phloc-commons</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- PREVIOUS TESTING
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-servlets</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-servlet</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-server</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-util</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-webapp</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
-->
|
||||
<!-- own api -->
|
||||
<!--dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-jaxrs</artifactId>
|
||||
<version>2.2.1.GA</version>
|
||||
<scope>test</scope>
|
||||
</dependency-->
|
||||
<dependency>
|
||||
<groupId>javax.ws.rs</groupId>
|
||||
<artifactId>javax.ws.rs-api</artifactId>
|
||||
<version>2.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.ejb</groupId>
|
||||
<artifactId>ejb-api</artifactId>
|
||||
<version>3.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
<!-- Jetty -->
|
||||
<!-- http://stackoverflow.com/questions/10048004/integrating-jetty-with-jax-rs-jersey -->
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-server</artifactId>
|
||||
<version>${jetty_version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-util</artifactId>
|
||||
<artifactId>jetty-servlet</artifactId>
|
||||
<version>${jetty_version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-webapp</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Jersey (JAX-RS) -->
|
||||
<!--
|
||||
<dependency>
|
||||
<groupId>com.sun.jersey</groupId>
|
||||
<groupId>org.glassfish.jersey.core</groupId>
|
||||
<artifactId>jersey-server</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.jersey.contribs</groupId>
|
||||
<artifactId>jersey-spring</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.ws.rs</groupId>
|
||||
<artifactId>jsr311-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.jersey</groupId>
|
||||
<artifactId>jersey-test-framework</artifactId>
|
||||
<version>${jersey_version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.grizzly</groupId>
|
||||
<artifactId>grizzly-servlet-webserver</artifactId>
|
||||
<groupId>org.glassfish.jersey.containers</groupId>
|
||||
<artifactId>jersey-container-servlet-core</artifactId>
|
||||
<version>${jersey_version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.containers</groupId>
|
||||
<artifactId>jersey-container-jetty-http</artifactId>
|
||||
<version>${jersey_version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
-->
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
||||
<!--
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-site-plugin</artifactId>
|
||||
<configuration>
|
||||
<skipDeploy>true</skipDeploy>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-tinder-plugin</artifactId>
|
||||
<version>1.3-SNAPSHOT</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>build_dstu1</id>
|
||||
<goals>
|
||||
<goal>generate-jparest-server</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<version>dstu</version>
|
||||
<packageBase>ca.uhn.fhir.jpa.rp.dstu</packageBase>
|
||||
<targetResourceSpringBeansFile>hapi-fhir-server-resourceproviders-dstu1.xml</targetResourceSpringBeansFile>
|
||||
<baseResourceNames/>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>build_dstu2</id>
|
||||
<goals>
|
||||
<goal>generate-jparest-server</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<version>dstu2</version>
|
||||
<packageBase>ca.uhn.fhir.jpa.rp.dstu2</packageBase>
|
||||
<targetResourceSpringBeansFile>hapi-fhir-server-resourceproviders-dstu2.xml</targetResourceSpringBeansFile>
|
||||
<baseResourceNames/>
|
||||
<excludeResourceNames>
|
||||
<excludeResourceName>OperationDefinition</excludeResourceName>
|
||||
<excludeResourceName>OperationOutcome</excludeResourceName>
|
||||
</excludeResourceNames>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu</artifactId>
|
||||
<version>1.3-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu2</artifactId>
|
||||
<version>1.3-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>${basedir}/src/main/resources</directory>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>${basedir}/target/generated-sources/tinder</directory>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>${basedir}/target/generated-resources/tinder</directory>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
-->
|
||||
|
||||
<reporting>
|
||||
<plugins>
|
||||
<plugin>
|
||||
|
|
|
@ -8,7 +8,7 @@ import javax.ws.rs.core.MultivaluedMap;
|
|||
import javax.ws.rs.core.UriInfo;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jaxrs.server.util.JaxRsRequestDetails;
|
||||
import ca.uhn.fhir.jaxrs.server.util.JaxRsRequest;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||
|
@ -30,18 +30,19 @@ public abstract class AbstractJaxRsProvider implements IRestfulServerDefaults {
|
|||
public static FhirContext CTX = FhirContext.forDstu2();
|
||||
|
||||
@Context
|
||||
private UriInfo info;
|
||||
private UriInfo theUriInfo;
|
||||
@Context
|
||||
private HttpHeaders headers;
|
||||
private HttpHeaders theHeaders;
|
||||
|
||||
public FhirContext getFhirContext() {
|
||||
@Override
|
||||
public FhirContext getFhirContext() {
|
||||
return CTX;
|
||||
}
|
||||
|
||||
/**
|
||||
* param and query methods
|
||||
*/
|
||||
protected HashMap<String, String[]> getQueryMap() {
|
||||
public HashMap<String, String[]> getQueryMap() {
|
||||
MultivaluedMap<String, String> queryParameters = getInfo().getQueryParameters();
|
||||
HashMap<String, String[]> params = new HashMap<String, String[]>();
|
||||
for (String key : queryParameters.keySet()) {
|
||||
|
@ -56,48 +57,42 @@ public abstract class AbstractJaxRsProvider implements IRestfulServerDefaults {
|
|||
return addressStrategy;
|
||||
}
|
||||
|
||||
protected String getBaseUri() {
|
||||
public String getBaseUri() {
|
||||
return getInfo().getBaseUri().toASCIIString();
|
||||
}
|
||||
|
||||
/**
|
||||
* PARSING METHODS
|
||||
*/
|
||||
public IParser getParser(JaxRsRequestDetails theRequestDetails) {
|
||||
public IParser getParser(JaxRsRequest theRequestDetails) {
|
||||
return RestfulServerUtils.getNewParser(getFhirContext(), theRequestDetails);
|
||||
}
|
||||
|
||||
protected JaxRsRequestDetails createRequestDetails(final String resourceString, RequestTypeEnum requestType, RestOperationTypeEnum restOperation) {
|
||||
JaxRsRequestDetails theRequest = new JaxRsRequestDetails(headers, resourceString);
|
||||
theRequest.setFhirServerBase(getBaseUri());
|
||||
theRequest.setRestOperationType(restOperation);
|
||||
theRequest.setServer(this);
|
||||
theRequest.setParameters(getQueryMap());
|
||||
theRequest.setRequestType(requestType);
|
||||
return theRequest;
|
||||
protected JaxRsRequest createRequestDetails(final String resourceString, RequestTypeEnum requestType, RestOperationTypeEnum restOperation) {
|
||||
return new JaxRsRequest(this, resourceString, requestType, restOperation);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the info
|
||||
* @return the info
|
||||
*/
|
||||
public UriInfo getInfo() {
|
||||
return info;
|
||||
return theUriInfo;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the info
|
||||
* @param info the info to set
|
||||
* Get the headers
|
||||
* @return the headers
|
||||
*/
|
||||
public void setInfo(UriInfo info) {
|
||||
this.info = info;
|
||||
}
|
||||
public HttpHeaders getHeaders() {
|
||||
return theHeaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* DEFAULT VALUES
|
||||
*/
|
||||
public EncodingEnum getDefaultResponseEncoding() {
|
||||
@Override
|
||||
public EncodingEnum getDefaultResponseEncoding() {
|
||||
return EncodingEnum.JSON;
|
||||
}
|
||||
|
||||
|
@ -119,5 +114,6 @@ public abstract class AbstractJaxRsProvider implements IRestfulServerDefaults {
|
|||
@Override
|
||||
public boolean isUseBrowserFriendlyContentTypes() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ package ca.uhn.fhir.jaxrs.server;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.interceptor.Interceptors;
|
||||
import javax.ws.rs.Consumes;
|
||||
|
@ -18,7 +20,7 @@ import javax.ws.rs.core.Response;
|
|||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import ca.uhn.fhir.jaxrs.server.interceptor.JaxRsExceptionInterceptor;
|
||||
import ca.uhn.fhir.jaxrs.server.util.JaxRsRequestDetails;
|
||||
import ca.uhn.fhir.jaxrs.server.util.JaxRsRequest;
|
||||
import ca.uhn.fhir.jaxrs.server.util.MethodBindings;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
|
@ -26,9 +28,12 @@ import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
|||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||
import ca.uhn.fhir.rest.method.BaseMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.BundleInclusionRule;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.IPagingProvider;
|
||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||
import ca.uhn.fhir.util.UrlUtil;
|
||||
|
||||
/**
|
||||
|
@ -40,22 +45,18 @@ import ca.uhn.fhir.util.UrlUtil;
|
|||
@Consumes({MediaType.APPLICATION_FORM_URLENCODED,MediaType.APPLICATION_JSON, "application/json+fhir", "application/xml+fhir"})
|
||||
public abstract class AbstractJaxRsResourceProvider<R extends IResource> extends AbstractJaxRsProvider implements IJaxRsResourceProvider<R> {
|
||||
|
||||
private static MethodBindings bindings;
|
||||
private final MethodBindings bindings;
|
||||
|
||||
protected AbstractJaxRsResourceProvider() {
|
||||
bindings = MethodBindings.getMethodBindings(this, getClass());
|
||||
}
|
||||
|
||||
public AbstractJaxRsResourceProvider(Class<?> subclass) {
|
||||
initBindings(subclass);
|
||||
protected AbstractJaxRsResourceProvider(Class<?> subclass) {
|
||||
bindings = MethodBindings.getMethodBindings(this, subclass);
|
||||
}
|
||||
|
||||
private void initBindings(Class<?> subclass) {
|
||||
if(bindings == null) {
|
||||
MethodBindings methodBindings = new MethodBindings();
|
||||
methodBindings.findMethods(this, subclass, getFhirContext());
|
||||
bindings = methodBindings;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getBaseUri() {
|
||||
public String getBaseUri() {
|
||||
try {
|
||||
return new URL(getInfo().getBaseUri().toURL(), getResourceType().getSimpleName()).toExternalForm();
|
||||
} catch(Exception e) {
|
||||
|
@ -115,7 +116,7 @@ public abstract class AbstractJaxRsResourceProvider<R extends IResource> extends
|
|||
|
||||
protected Response customOperation(final String resource, RequestTypeEnum requestType, String id, String operationName, RestOperationTypeEnum operationType)
|
||||
throws Exception {
|
||||
return executeMethod(resource, requestType, operationType, id, bindings.getBinding(operationType, operationName));
|
||||
return executeMethod(resource, requestType, operationType, id, getBindings().getBinding(operationType, operationName));
|
||||
}
|
||||
|
||||
@GET
|
||||
|
@ -124,7 +125,7 @@ public abstract class AbstractJaxRsResourceProvider<R extends IResource> extends
|
|||
@Interceptors(JaxRsExceptionInterceptor.class)
|
||||
public Response findHistory(@PathParam("id") final String id, @PathParam("version") final String versionString)
|
||||
throws BaseServerResponseException, IOException {
|
||||
BaseMethodBinding<?> method = bindings.getBinding(RestOperationTypeEnum.VREAD);
|
||||
BaseMethodBinding<?> method = getBindings().getBinding(RestOperationTypeEnum.VREAD);
|
||||
final RequestDetails theRequest = createRequestDetails(null, RequestTypeEnum.GET, RestOperationTypeEnum.VREAD);
|
||||
if (id == null) {
|
||||
throw new InvalidRequestException("Don't know how to handle request path: " + getInfo().getRequestUri().toASCIIString());
|
||||
|
@ -138,7 +139,7 @@ public abstract class AbstractJaxRsResourceProvider<R extends IResource> extends
|
|||
@Path("/{id}/{compartment}")
|
||||
@Interceptors(JaxRsExceptionInterceptor.class)
|
||||
public Response findCompartment(@PathParam("id") final String id, @PathParam("compartment") final String compartment) throws BaseServerResponseException, IOException {
|
||||
BaseMethodBinding<?> method = bindings.getBinding(RestOperationTypeEnum.SEARCH_TYPE, compartment);
|
||||
BaseMethodBinding<?> method = getBindings().getBinding(RestOperationTypeEnum.SEARCH_TYPE, compartment);
|
||||
final RequestDetails theRequest = createRequestDetails(null, RequestTypeEnum.GET, RestOperationTypeEnum.VREAD);
|
||||
if (id == null) {
|
||||
throw new InvalidRequestException("Don't know how to handle request path: " + getInfo().getRequestUri().toASCIIString());
|
||||
|
@ -150,7 +151,7 @@ public abstract class AbstractJaxRsResourceProvider<R extends IResource> extends
|
|||
|
||||
private <T extends BaseMethodBinding<?>> Response executeMethod(final String resourceString, RequestTypeEnum requestType, RestOperationTypeEnum restOperation, String id)
|
||||
throws BaseServerResponseException, IOException {
|
||||
BaseMethodBinding<?> method = bindings.getBinding(restOperation);
|
||||
BaseMethodBinding<?> method = getBindings().getBinding(restOperation);
|
||||
return executeMethod(resourceString, requestType, restOperation, id, method);
|
||||
}
|
||||
|
||||
|
@ -162,8 +163,8 @@ public abstract class AbstractJaxRsResourceProvider<R extends IResource> extends
|
|||
}
|
||||
|
||||
|
||||
protected JaxRsRequestDetails createRequestDetails(final String resourceString, RequestTypeEnum requestType, RestOperationTypeEnum restOperation, String id) {
|
||||
JaxRsRequestDetails theRequest = super.createRequestDetails(resourceString, requestType, restOperation);
|
||||
protected JaxRsRequest createRequestDetails(final String resourceString, RequestTypeEnum requestType, RestOperationTypeEnum restOperation, String id) {
|
||||
JaxRsRequest theRequest = super.createRequestDetails(resourceString, requestType, restOperation);
|
||||
theRequest.setId(StringUtils.isBlank(id) ? null : new IdDt(getResourceType().getName(), UrlUtil.unescape(id)));
|
||||
if(restOperation == RestOperationTypeEnum.UPDATE) {
|
||||
String contentLocation = theRequest.getHeader(Constants.HEADER_CONTENT_LOCATION);
|
||||
|
@ -173,8 +174,27 @@ public abstract class AbstractJaxRsResourceProvider<R extends IResource> extends
|
|||
}
|
||||
return theRequest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IServerInterceptor> getInterceptors() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPagingProvider getPagingProvider() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BundleInclusionRule getBundleInclusionRule() {
|
||||
return BundleInclusionRule.BASED_ON_INCLUDES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract Class<R> getResourceType();
|
||||
|
||||
|
||||
public MethodBindings getBindings() {
|
||||
return bindings;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,12 +4,12 @@ import java.io.IOException;
|
|||
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import ca.uhn.fhir.jaxrs.server.util.JaxRsRequestDetails;
|
||||
import ca.uhn.fhir.jaxrs.server.util.JaxRsRequest;
|
||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||
import ca.uhn.fhir.rest.server.IRestfulServer;
|
||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||
|
||||
public interface IJaxRsResourceProvider<T> extends IRestfulServer<JaxRsRequestDetails>, IResourceProvider {
|
||||
public interface IJaxRsResourceProvider<T> extends IRestfulServer<JaxRsRequest>, IResourceProvider {
|
||||
|
||||
Response search()
|
||||
throws Exception;
|
||||
|
|
|
@ -9,17 +9,34 @@ import java.util.List;
|
|||
import javax.ws.rs.core.HttpHeaders;
|
||||
|
||||
import ca.uhn.fhir.jaxrs.server.AbstractJaxRsProvider;
|
||||
import ca.uhn.fhir.jaxrs.server.JaxRsResponse;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
import ca.uhn.fhir.rest.param.ResourceParameter;
|
||||
import ca.uhn.fhir.rest.server.IRestfulResponse;
|
||||
|
||||
public class JaxRsRequestDetails extends RequestDetails {
|
||||
public class JaxRsRequest extends RequestDetails {
|
||||
|
||||
private String theResourceString;
|
||||
private HttpHeaders headers;
|
||||
private AbstractJaxRsProvider myServer;
|
||||
|
||||
public AbstractJaxRsProvider getServer() {
|
||||
public JaxRsRequest() {
|
||||
}
|
||||
|
||||
public JaxRsRequest(AbstractJaxRsProvider server, String resourceString,
|
||||
RequestTypeEnum requestType, RestOperationTypeEnum restOperation) {
|
||||
this.headers = server.getHeaders();
|
||||
this.theResourceString = resourceString;
|
||||
this.setRestOperationType(restOperation);
|
||||
setServer(server);
|
||||
setFhirServerBase(server.getBaseUri());
|
||||
setParameters(server.getQueryMap());
|
||||
setRequestType(requestType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractJaxRsProvider getServer() {
|
||||
return myServer;
|
||||
}
|
||||
|
||||
|
@ -27,16 +44,10 @@ public class JaxRsRequestDetails extends RequestDetails {
|
|||
this.myServer = theServer;
|
||||
}
|
||||
|
||||
public JaxRsRequestDetails(HttpHeaders headers, String resourceString) {
|
||||
this.headers = headers;
|
||||
this.theResourceString = resourceString;
|
||||
setResponse(new JaxRsResponse(resourceString, this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHeader(String headerIfNoneExist) {
|
||||
List<String> requestHeader = headers.getRequestHeader(headerIfNoneExist);
|
||||
return (requestHeader == null || requestHeader.size() == 0) ? null : requestHeader.get(0);
|
||||
public String getHeader(String headerKey) {
|
||||
List<String> requestHeader = getHeaders(headerKey);
|
||||
return requestHeader.isEmpty() ? null : requestHeader.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -55,14 +66,24 @@ public class JaxRsRequestDetails extends RequestDetails {
|
|||
return theResourceString.getBytes(ResourceParameter.determineRequestCharset(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public IRestfulResponse getResponse() {
|
||||
if(super.getResponse() == null) {
|
||||
setResponse(new JaxRsResponse(this));
|
||||
}
|
||||
return super.getResponse();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Reader getReader()
|
||||
throws IOException {
|
||||
// not yet implemented
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() {
|
||||
// not yet implemented
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package ca.uhn.fhir.jaxrs.server;
|
||||
package ca.uhn.fhir.jaxrs.server.util;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
@ -15,7 +15,6 @@ import javax.ws.rs.core.Response.ResponseBuilder;
|
|||
|
||||
import org.hl7.fhir.instance.model.api.IBaseBinary;
|
||||
|
||||
import ca.uhn.fhir.jaxrs.server.util.JaxRsRequestDetails;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.method.ParseAction;
|
||||
|
@ -24,9 +23,9 @@ import ca.uhn.fhir.rest.server.EncodingEnum;
|
|||
import ca.uhn.fhir.rest.server.RestfulResponse;
|
||||
import ca.uhn.fhir.rest.server.RestfulServerUtils;
|
||||
|
||||
public class JaxRsResponse extends RestfulResponse<JaxRsRequestDetails> {
|
||||
public class JaxRsResponse extends RestfulResponse<JaxRsRequest> {
|
||||
|
||||
public JaxRsResponse(String resourceString, JaxRsRequestDetails jaxRsRequestDetails) {
|
||||
public JaxRsResponse(JaxRsRequest jaxRsRequestDetails) {
|
||||
super(jaxRsRequestDetails);
|
||||
}
|
||||
|
||||
|
@ -43,15 +42,13 @@ public class JaxRsResponse extends RestfulResponse<JaxRsRequestDetails> {
|
|||
|
||||
@Override
|
||||
public Response sendWriterResponse(int status, String contentType, String charset, Writer writer) {
|
||||
return Response.status(status)/*.header(HttpHeaders.CONTENT_TYPE, charset)*/.header(Constants.HEADER_CONTENT_TYPE, contentType).entity(writer.toString()).build();
|
||||
Object entity = writer instanceof StringWriter ? writer.toString() : writer;
|
||||
return buildResponse(status)/*.header(HttpHeaders.CONTENT_TYPE, charset)*/.header(Constants.HEADER_CONTENT_TYPE, contentType).entity(entity).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object sendAttachmentResponse(IBaseBinary bin, int statusCode, String contentType) throws IOException {
|
||||
ResponseBuilder response = Response.status(statusCode);
|
||||
for (Entry<String, String> header : getHeaders().entrySet()) {
|
||||
response.header(header.getKey(), header.getValue());
|
||||
}
|
||||
public Response sendAttachmentResponse(IBaseBinary bin, int statusCode, String contentType) throws IOException {
|
||||
ResponseBuilder response = buildResponse(statusCode);
|
||||
if (bin.getContent() != null && bin.getContent().length > 0) {
|
||||
response.header(Constants.HEADER_CONTENT_TYPE, contentType).entity(bin.getContent());
|
||||
}
|
||||
|
@ -59,20 +56,28 @@ public class JaxRsResponse extends RestfulResponse<JaxRsRequestDetails> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object returnResponse(ParseAction<?> outcome, int operationStatus, boolean allowPrefer, MethodOutcome response,
|
||||
public Response returnResponse(ParseAction<?> outcome, int operationStatus, boolean allowPrefer, MethodOutcome response,
|
||||
String resourceName)
|
||||
throws IOException {
|
||||
Writer writer = new StringWriter();
|
||||
IParser parser = RestfulServerUtils.getNewParser(getRequestDetails().getServer().getFhirContext(), getRequestDetails());
|
||||
StringWriter writer = new StringWriter();
|
||||
if(outcome != null) {
|
||||
IParser parser = RestfulServerUtils.getNewParser(getRequestDetails().getServer().getFhirContext(), getRequestDetails());
|
||||
outcome.execute(parser, writer);
|
||||
}
|
||||
return Response.status(operationStatus).header(Constants.HEADER_CONTENT_TYPE, getParserType()).entity(writer.toString()).build();
|
||||
return sendWriterResponse(operationStatus, getParserType(), null, writer);
|
||||
}
|
||||
|
||||
protected String getParserType() {
|
||||
EncodingEnum encodingEnum = RestfulServerUtils.determineResponseEncodingWithDefault(getRequestDetails());
|
||||
return encodingEnum == EncodingEnum.JSON ? MediaType.APPLICATION_JSON : MediaType.APPLICATION_XML;
|
||||
}
|
||||
|
||||
private ResponseBuilder buildResponse(int statusCode) {
|
||||
ResponseBuilder response = Response.status(statusCode);
|
||||
for (Entry<String, String> header : getHeaders().entrySet()) {
|
||||
response.header(header.getKey(), header.getValue());
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
}
|
|
@ -5,7 +5,6 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jaxrs.server.AbstractJaxRsResourceProvider;
|
||||
import ca.uhn.fhir.rest.annotation.Search;
|
||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||
|
@ -14,55 +13,73 @@ import ca.uhn.fhir.rest.method.OperationMethodBinding;
|
|||
import ca.uhn.fhir.rest.method.SearchMethodBinding;
|
||||
import ca.uhn.fhir.util.ReflectionUtil;
|
||||
|
||||
/**
|
||||
* @author Peter Van Houte
|
||||
* Class that contains the method bindings defined by a ResourceProvider
|
||||
*/
|
||||
public class MethodBindings {
|
||||
|
||||
/** ALL METHOD BINDINGS */
|
||||
ConcurrentHashMap<RestOperationTypeEnum, ConcurrentHashMap<String, BaseMethodBinding<?>>> allBindings = new ConcurrentHashMap<RestOperationTypeEnum, ConcurrentHashMap<String,BaseMethodBinding<?>>>();
|
||||
/** Static collection of bindings mapped to a class*/
|
||||
private static final ConcurrentHashMap<Class<?>, MethodBindings> classBindings = new ConcurrentHashMap<Class<?>, MethodBindings>();
|
||||
/** Static collection of operationBindings mapped to a class */
|
||||
private ConcurrentHashMap<RestOperationTypeEnum, ConcurrentHashMap<String, BaseMethodBinding<?>>> operationBindings = new ConcurrentHashMap<RestOperationTypeEnum, ConcurrentHashMap<String,BaseMethodBinding<?>>>();
|
||||
|
||||
public <T extends AbstractJaxRsResourceProvider<?>> void findMethods(T theProvider, Class<?> subclass, FhirContext fhirContext) {
|
||||
for (final Method m : ReflectionUtil.getDeclaredMethods(subclass)) {
|
||||
final BaseMethodBinding<?> foundMethodBinding = BaseMethodBinding.bindMethod(m, fhirContext, theProvider);
|
||||
public <T extends AbstractJaxRsResourceProvider<?>> MethodBindings(T theProvider, Class<?> clazz) {
|
||||
for (final Method m : ReflectionUtil.getDeclaredMethods(clazz)) {
|
||||
final BaseMethodBinding<?> foundMethodBinding = BaseMethodBinding.bindMethod(m, theProvider.getFhirContext(), theProvider);
|
||||
if (foundMethodBinding == null) {
|
||||
continue;
|
||||
}
|
||||
ConcurrentHashMap<String, BaseMethodBinding<?>> map = getAllBindingsMap(foundMethodBinding.getRestOperationType());
|
||||
if (foundMethodBinding instanceof OperationMethodBinding) {
|
||||
OperationMethodBinding binding = (OperationMethodBinding) foundMethodBinding;
|
||||
putIfAbsent(map, binding.getName(), binding);
|
||||
} else if (foundMethodBinding instanceof SearchMethodBinding) {
|
||||
Search search = m.getAnnotation(Search.class);
|
||||
String compartmentName = StringUtils.defaultIfBlank(search.compartmentName(), "");
|
||||
putIfAbsent(map, compartmentName, foundMethodBinding);
|
||||
} else {
|
||||
putIfAbsent(map, "", foundMethodBinding);
|
||||
}
|
||||
String bindingKey = getBindingKey(foundMethodBinding);
|
||||
putIfAbsent(bindingKey, foundMethodBinding);
|
||||
}
|
||||
}
|
||||
|
||||
private void putIfAbsent(ConcurrentHashMap<String, BaseMethodBinding<?>> map, String key, BaseMethodBinding binding) {
|
||||
private String getBindingKey(final BaseMethodBinding<?> foundMethodBinding) {
|
||||
if (foundMethodBinding instanceof OperationMethodBinding) {
|
||||
return ((OperationMethodBinding) foundMethodBinding).getName();
|
||||
} else if (foundMethodBinding instanceof SearchMethodBinding) {
|
||||
Search search = foundMethodBinding.getMethod().getAnnotation(Search.class);
|
||||
return search.compartmentName();
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
private void putIfAbsent(String key, BaseMethodBinding<?> binding) {
|
||||
operationBindings.putIfAbsent(binding.getRestOperationType(), new ConcurrentHashMap<String, BaseMethodBinding<?>>());
|
||||
ConcurrentHashMap<String, BaseMethodBinding<?>> map = operationBindings.get(binding.getRestOperationType());
|
||||
if (map.containsKey(key)) {
|
||||
throw new IllegalArgumentException("Multiple Search Method Bindings Found : " + map.get(key) + " -- " + binding.getMethod());
|
||||
}
|
||||
}
|
||||
map.put(key, binding);
|
||||
}
|
||||
|
||||
private ConcurrentHashMap<String,BaseMethodBinding<?>> getAllBindingsMap(final RestOperationTypeEnum restOperationTypeEnum) {
|
||||
allBindings.putIfAbsent(restOperationTypeEnum, new ConcurrentHashMap<String, BaseMethodBinding<?>>());
|
||||
return allBindings.get(restOperationTypeEnum);
|
||||
}
|
||||
public BaseMethodBinding<?> getBinding(RestOperationTypeEnum operationType) {
|
||||
return getBinding(operationType, "");
|
||||
}
|
||||
|
||||
public BaseMethodBinding<?> getBinding(RestOperationTypeEnum operationType, String qualifier) {
|
||||
String nonEmptyQualifier = StringUtils.defaultIfBlank(qualifier, "");
|
||||
ConcurrentHashMap<String, BaseMethodBinding<?>> map = getAllBindingsMap(operationType);
|
||||
if(!map.containsKey(nonEmptyQualifier)) {
|
||||
String nonEmptyQualifier = StringUtils.defaultIfBlank(qualifier, "");
|
||||
ConcurrentHashMap<String, BaseMethodBinding<?>> map = operationBindings.get(operationType);
|
||||
if(map == null || !map.containsKey(nonEmptyQualifier)) {
|
||||
throw new UnsupportedOperationException();
|
||||
} else {
|
||||
return map.get(nonEmptyQualifier);
|
||||
}
|
||||
}
|
||||
|
||||
public BaseMethodBinding<?> getBinding(RestOperationTypeEnum operationType) {
|
||||
return getBinding(operationType, "");
|
||||
}
|
||||
public static <T extends AbstractJaxRsResourceProvider<?>> MethodBindings getMethodBindings(T theProvider, Class<?> clazz) {
|
||||
if(!getClassBindings().containsKey(clazz)) {
|
||||
MethodBindings foundBindings = new MethodBindings(theProvider, clazz);
|
||||
getClassBindings().putIfAbsent(clazz, foundBindings);
|
||||
}
|
||||
return getClassBindings().get(clazz);
|
||||
}
|
||||
|
||||
public static ConcurrentHashMap<Class<?>, MethodBindings> getClassBindings() {
|
||||
return classBindings;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,318 @@
|
|||
package ca.uhn.fhir.jaxrs.server;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jaxrs.server.example.JaxRsPatientRestProvider;
|
||||
import ca.uhn.fhir.jaxrs.server.example.RandomServerPortProvider;
|
||||
import ca.uhn.fhir.model.api.BundleEntry;
|
||||
import ca.uhn.fhir.model.dstu2.composite.HumanNameDt;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Conformance;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Parameters;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.model.primitive.BoundCodeDt;
|
||||
import ca.uhn.fhir.model.primitive.DateDt;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.model.valueset.BundleEntryTransactionMethodEnum;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.api.PreferReturnEnum;
|
||||
import ca.uhn.fhir.rest.client.IGenericClient;
|
||||
import ca.uhn.fhir.rest.client.ServerValidationModeEnum;
|
||||
import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
|
||||
import ca.uhn.fhir.rest.method.SearchStyleEnum;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
|
||||
public class JaxRsPatientProviderTest {
|
||||
|
||||
private static IGenericClient client;
|
||||
private static final FhirContext ourCtx = FhirContext.forDstu2();
|
||||
private static final String PATIENT_NAME = "Van Houte";
|
||||
private static int ourPort;
|
||||
private static Server jettyServer;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass()
|
||||
throws Exception {
|
||||
ourPort = RandomServerPortProvider.findFreePort();
|
||||
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
|
||||
context.setContextPath("/");
|
||||
System.out.println(ourPort);
|
||||
jettyServer = new Server(ourPort);
|
||||
jettyServer.setHandler(context);
|
||||
ServletHolder jerseyServlet = context.addServlet(org.glassfish.jersey.servlet.ServletContainer.class, "/*");
|
||||
jerseyServlet.setInitOrder(0);
|
||||
jerseyServlet.setInitParameter("jersey.config.server.provider.classnames", JaxRsPatientRestProvider.class.getCanonicalName());
|
||||
jettyServer.start();
|
||||
|
||||
ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
|
||||
ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000);
|
||||
client = ourCtx.newRestfulGenericClient("http://localhost:" + ourPort + "/");
|
||||
client.setEncoding(EncodingEnum.JSON);
|
||||
client.registerInterceptor(new LoggingInterceptor(true));
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownClass()
|
||||
throws Exception {
|
||||
try {
|
||||
jettyServer.destroy();
|
||||
}
|
||||
catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
/** Search/Query - Type */
|
||||
@Test
|
||||
public void findUsingGenericClientBySearch() {
|
||||
// Perform a search
|
||||
final ca.uhn.fhir.model.api.Bundle results = client.search().forResource(Patient.class)
|
||||
.where(Patient.NAME.matchesExactly().value(PATIENT_NAME)).execute();
|
||||
System.out.println(results.getEntries().get(0));
|
||||
assertEquals(results.getEntries().size(), 1);
|
||||
}
|
||||
|
||||
/** Search - Multi-valued Parameters (ANY/OR) */
|
||||
@Test
|
||||
public void findUsingGenericClientBySearchWithMultiValues() {
|
||||
final ca.uhn.fhir.model.api.Bundle response = client.search().forResource(Patient.class)
|
||||
.where(Patient.ADDRESS.matches().values("Toronto")).and(Patient.ADDRESS.matches().values("Ontario"))
|
||||
.and(Patient.ADDRESS.matches().values("Canada"))
|
||||
.where(Patient.IDENTIFIER.exactly().systemAndIdentifier("SHORTNAME", "TOYS")).execute();
|
||||
System.out.println(response.getEntries().get(0));
|
||||
}
|
||||
|
||||
/** Search - Paging */
|
||||
@Test
|
||||
public void findWithPaging() {
|
||||
// Perform a search
|
||||
final Bundle results = client.search().forResource(Patient.class).limitTo(8).returnBundle(Bundle.class).execute();
|
||||
System.out.println(results.getEntry().size());
|
||||
|
||||
if (results.getLink(Bundle.LINK_NEXT) != null) {
|
||||
|
||||
// load next page
|
||||
final Bundle nextPage = client.loadPage().next(results).execute();
|
||||
System.out.println(nextPage.getEntry().size());
|
||||
}
|
||||
}
|
||||
|
||||
/** Search using other query options */
|
||||
public void testOther() {
|
||||
//missing
|
||||
}
|
||||
|
||||
/** */
|
||||
@Test
|
||||
public void testSearchPost() {
|
||||
Bundle response = client.search()
|
||||
.forResource("Patient")
|
||||
.usingStyle(SearchStyleEnum.POST)
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
assertTrue(response.getEntry().size() > 0);
|
||||
}
|
||||
|
||||
/** Search - Compartments */
|
||||
@Test
|
||||
public void testSearchCompartements() {
|
||||
Bundle response = client.search()
|
||||
.forResource(Patient.class)
|
||||
.withIdAndCompartment("1", "Condition")
|
||||
.returnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class)
|
||||
.execute();
|
||||
assertTrue(response.getEntry().size() > 0);
|
||||
}
|
||||
|
||||
/** Search - Subsetting (_summary and _elements) */
|
||||
@Test
|
||||
@Ignore
|
||||
public void testSummary() {
|
||||
Object response = client.search()
|
||||
.forResource(Patient.class)
|
||||
.returnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class)
|
||||
.execute();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreatePatient() {
|
||||
final Patient existing = new Patient();
|
||||
existing.setId((IdDt) null);
|
||||
existing.getNameFirstRep().addFamily("Created Patient 54");
|
||||
client.setEncoding(EncodingEnum.JSON);
|
||||
final MethodOutcome results = client.create().resource(existing).prefer(PreferReturnEnum.REPRESENTATION).execute();
|
||||
System.out.println(results.getId());
|
||||
final Patient patient = (Patient) results.getResource();
|
||||
System.out.println(patient);
|
||||
assertNotNull(client.read(patient.getId()));
|
||||
client.setEncoding(EncodingEnum.JSON);
|
||||
}
|
||||
|
||||
|
||||
/** Conditional Creates */
|
||||
@Test
|
||||
public void testConditionalCreate() {
|
||||
final Patient existing = new Patient();
|
||||
existing.setId((IdDt) null);
|
||||
existing.getNameFirstRep().addFamily("Created Patient 54");
|
||||
client.setEncoding(EncodingEnum.XML);
|
||||
final MethodOutcome results = client.create().resource(existing).prefer(PreferReturnEnum.REPRESENTATION).execute();
|
||||
System.out.println(results.getId());
|
||||
final Patient patient = (Patient) results.getResource();
|
||||
|
||||
client.create()
|
||||
.resource(patient)
|
||||
.conditional()
|
||||
.where(Patient.IDENTIFIER.exactly().identifier(patient.getIdentifierFirstRep()))
|
||||
.execute();
|
||||
}
|
||||
|
||||
|
||||
/** Find By Id */
|
||||
@Test
|
||||
public void findUsingGenericClientById() {
|
||||
final Patient results = client.read(Patient.class, "1");
|
||||
assertEquals(results.getId().getIdPartAsLong().longValue(), 1L);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateById() {
|
||||
final Patient existing = client.read(Patient.class, "1");
|
||||
final List<HumanNameDt> name = existing.getName();
|
||||
name.get(0).addSuffix("The Second");
|
||||
existing.setName(name);
|
||||
client.setEncoding(EncodingEnum.XML);
|
||||
final MethodOutcome results = client.update("1", existing);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeletePatient() {
|
||||
final Patient existing = new Patient();
|
||||
existing.getNameFirstRep().addFamily("Created Patient XYZ");
|
||||
final MethodOutcome results = client.create().resource(existing).prefer(PreferReturnEnum.REPRESENTATION).execute();
|
||||
System.out.println(results.getId());
|
||||
final Patient patient = (Patient) results.getResource();
|
||||
client.delete(Patient.class, patient.getId());
|
||||
try {
|
||||
client.read(patient.getId());
|
||||
fail();
|
||||
}
|
||||
catch (final Exception e) {
|
||||
//assertEquals(e.getStatusCode(), Constants.STATUS_HTTP_404_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
/** Transaction - Server */
|
||||
@Ignore
|
||||
@Test
|
||||
public void testTransaction() {
|
||||
ca.uhn.fhir.model.api.Bundle bundle = new ca.uhn.fhir.model.api.Bundle();
|
||||
BundleEntry entry = bundle.addEntry();
|
||||
final Patient existing = new Patient();
|
||||
existing.getNameFirstRep().addFamily("Created with bundle");
|
||||
entry.setResource(existing);
|
||||
|
||||
BoundCodeDt<BundleEntryTransactionMethodEnum> theTransactionOperation =
|
||||
new BoundCodeDt(
|
||||
BundleEntryTransactionMethodEnum.VALUESET_BINDER,
|
||||
BundleEntryTransactionMethodEnum.POST);
|
||||
entry.setTransactionMethod(theTransactionOperation);
|
||||
ca.uhn.fhir.model.api.Bundle response = client.transaction().withBundle(bundle).execute();
|
||||
}
|
||||
|
||||
/** Conformance - Server */
|
||||
@Test
|
||||
@Ignore
|
||||
public void testConformance() {
|
||||
final Conformance conf = client.fetchConformance().ofType(Conformance.class).execute();
|
||||
System.out.println(conf.getRest().get(0).getResource().get(0).getType());
|
||||
assertEquals(conf.getRest().get(0).getResource().get(0).getType().toString(), "Patient");
|
||||
}
|
||||
|
||||
/** Extended Operations */
|
||||
// Create a client to talk to the HeathIntersections server
|
||||
@Test
|
||||
public void testExtendedOperations() {
|
||||
client.registerInterceptor(new LoggingInterceptor(true));
|
||||
|
||||
// Create the input parameters to pass to the server
|
||||
Parameters inParams = new Parameters();
|
||||
inParams.addParameter().setName("start").setValue(new DateDt("2001-01-01"));
|
||||
inParams.addParameter().setName("end").setValue(new DateDt("2015-03-01"));
|
||||
inParams.addParameter().setName("dummy").setValue(new StringDt("myAwesomeDummyValue"));
|
||||
|
||||
// Invoke $everything on "Patient/1"
|
||||
Parameters outParams = client
|
||||
.operation()
|
||||
.onInstance(new IdDt("Patient", "1"))
|
||||
.named("$last")
|
||||
.withParameters(inParams)
|
||||
//.useHttpGet() // Use HTTP GET instead of POST
|
||||
.execute();
|
||||
String resultValue = outParams.getParameter().get(0).getValue().toString();
|
||||
System.out.println(resultValue);
|
||||
assertEquals("expected but found : "+ resultValue, resultValue.contains("myAwesomeDummyValue"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtendedOperationsUsingGet() {
|
||||
client.registerInterceptor(new LoggingInterceptor(true));
|
||||
|
||||
// Create the input parameters to pass to the server
|
||||
Parameters inParams = new Parameters();
|
||||
inParams.addParameter().setName("start").setValue(new DateDt("2001-01-01"));
|
||||
inParams.addParameter().setName("end").setValue(new DateDt("2015-03-01"));
|
||||
inParams.addParameter().setName("dummy").setValue(new StringDt("myAwesomeDummyValue"));
|
||||
|
||||
// Invoke $everything on "Patient/1"
|
||||
Parameters outParams = client
|
||||
.operation()
|
||||
.onInstance(new IdDt("Patient", "1"))
|
||||
.named("$last")
|
||||
.withParameters(inParams)
|
||||
.useHttpGet() // Use HTTP GET instead of POST
|
||||
.execute();
|
||||
String resultValue = outParams.getParameter().get(0).getValue().toString();
|
||||
System.out.println(resultValue);
|
||||
assertEquals("expected but found : "+ resultValue, resultValue.contains("myAwesomeDummyValue"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindUnknownPatient() {
|
||||
try {
|
||||
final Patient existing = client.read(Patient.class, "999955541264");
|
||||
fail();
|
||||
}
|
||||
catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
//assertEquals(e.getStatusCode(), 404);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVRead() {
|
||||
final Patient patient = client.vread(Patient.class, "1", "1");
|
||||
System.out.println(patient);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRead() {
|
||||
final Patient patient = client.read(Patient.class, "1");
|
||||
System.out.println(patient);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,269 @@
|
|||
package ca.uhn.fhir.jaxrs.server.example;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import javax.ejb.Stateless;
|
||||
import javax.interceptor.Interceptors;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import ca.uhn.fhir.jaxrs.server.AbstractJaxRsResourceProvider;
|
||||
import ca.uhn.fhir.jaxrs.server.interceptor.JaxRsExceptionInterceptor;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Condition;
|
||||
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.ConditionalUrlParam;
|
||||
import ca.uhn.fhir.rest.annotation.Create;
|
||||
import ca.uhn.fhir.rest.annotation.Delete;
|
||||
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.annotation.Read;
|
||||
import ca.uhn.fhir.rest.annotation.RequiredParam;
|
||||
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
||||
import ca.uhn.fhir.rest.annotation.Search;
|
||||
import ca.uhn.fhir.rest.annotation.Update;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import ca.uhn.fhir.rest.server.AddProfileTagEnum;
|
||||
import ca.uhn.fhir.rest.server.BundleInclusionRule;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.ETagSupportEnum;
|
||||
import ca.uhn.fhir.rest.server.FifoMemoryPagingProvider;
|
||||
import ca.uhn.fhir.rest.server.IPagingProvider;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||
|
||||
/**
|
||||
* Fhir Physician Rest Service
|
||||
* @author axmpm
|
||||
*
|
||||
*/
|
||||
@Path(JaxRsPatientRestProvider.PATH)
|
||||
@Stateless
|
||||
@Produces({MediaType.APPLICATION_JSON, Constants.CT_FHIR_JSON, Constants.CT_FHIR_XML})
|
||||
public class JaxRsPatientRestProvider extends AbstractJaxRsResourceProvider<Patient> /*implements IJaxRsPatientProvider*/ {
|
||||
|
||||
static final String PATH = "/Patient";
|
||||
|
||||
private static Long counter = 1L;
|
||||
private static final ConcurrentHashMap<String, List<Patient>> patients = new ConcurrentHashMap<String, List<Patient>>();
|
||||
|
||||
public JaxRsPatientRestProvider() throws Exception {
|
||||
super(JaxRsPatientRestProvider.class);
|
||||
}
|
||||
|
||||
static {
|
||||
patients.put(""+counter, createPatient("Van Houte"));
|
||||
patients.put(""+(counter), createPatient("Agnew"));
|
||||
for(int i = 0 ; i<20 ; i++) {
|
||||
patients.put(""+(counter), createPatient("Random Patient " + counter));
|
||||
}
|
||||
}
|
||||
|
||||
private static List<Patient> createPatient(final String name) {
|
||||
final Patient patient = new Patient();
|
||||
patient.getNameFirstRep().addFamily(name);
|
||||
return createPatient(patient);
|
||||
}
|
||||
|
||||
private static List<Patient> createPatient(final Patient patient) {
|
||||
patient.setId(createId(counter, 1L));
|
||||
final LinkedList<Patient> list = new LinkedList<Patient>();
|
||||
list.add(patient);
|
||||
counter++;
|
||||
return list ;
|
||||
}
|
||||
|
||||
private static IdDt createId(final Long id, final Long theVersionId) {
|
||||
return new IdDt("Patient", "" + id, "" + theVersionId);
|
||||
}
|
||||
|
||||
@Search
|
||||
public List<Patient> search(@RequiredParam(name = Patient.SP_NAME) final StringParam name) {
|
||||
final List<Patient> result = new LinkedList<Patient>();
|
||||
for (final List<Patient> patientIterator : patients.values()) {
|
||||
Patient single = null;
|
||||
for (Patient patient : patientIterator) {
|
||||
if (name == null || patient.getNameFirstRep().getFamilyFirstRep().getValueNotNull().equals(name.getValueNotNull())) {
|
||||
single = patient;
|
||||
}
|
||||
}
|
||||
if (single != null) {
|
||||
result.add(single);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Update
|
||||
public MethodOutcome update(@IdParam final IdDt theId, @ResourceParam final Patient patient)
|
||||
throws Exception {
|
||||
final String idPart = theId.getIdPart();
|
||||
if(patients.containsKey(idPart)) {
|
||||
final List<Patient> patientList = patients.get(idPart);
|
||||
final Patient lastPatient = getLast(patientList);
|
||||
patient.setId(createId(theId.getIdPartAsLong(), lastPatient.getId().getVersionIdPartAsLong()+1));
|
||||
patientList.add(patient);
|
||||
final MethodOutcome result = new MethodOutcome().setCreated(false);
|
||||
result.setResource(patient);
|
||||
result.setId(patient.getId());
|
||||
return result;
|
||||
} else {
|
||||
throw new ResourceNotFoundException(theId);
|
||||
}
|
||||
}
|
||||
|
||||
@Read
|
||||
public Patient find(@IdParam final IdDt theId) {
|
||||
if(patients.containsKey(theId.getIdPart())) {
|
||||
return getLast(patients.get(theId.getIdPart()));
|
||||
} else {
|
||||
throw new ResourceNotFoundException(theId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Patient getLast(final List<Patient> list) {
|
||||
return list.get(list.size()-1);
|
||||
}
|
||||
|
||||
@Read(version = true)
|
||||
public Patient findHistory(@IdParam final IdDt theId) {
|
||||
if (patients.containsKey(theId.getIdPart())) {
|
||||
final List<Patient> list = patients.get(theId.getIdPart());
|
||||
for (final Patient patient : list) {
|
||||
if (patient.getId().getVersionIdPartAsLong().equals(theId.getVersionIdPartAsLong())) {
|
||||
return patient;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new ResourceNotFoundException(theId);
|
||||
}
|
||||
|
||||
@Create
|
||||
public MethodOutcome create(@ResourceParam final Patient patient, @ConditionalUrlParam String theConditional)
|
||||
throws Exception {
|
||||
patients.put(""+counter, createPatient(patient));
|
||||
final MethodOutcome result = new MethodOutcome().setCreated(true);
|
||||
result.setResource(patient);
|
||||
result.setId(patient.getId());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Delete
|
||||
public MethodOutcome delete(@IdParam final IdDt theId) {
|
||||
final Patient deletedPatient = find(theId);
|
||||
patients.remove(deletedPatient.getId().getIdPart());
|
||||
final MethodOutcome result = new MethodOutcome().setCreated(true);
|
||||
result.setResource(deletedPatient);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@GET
|
||||
@Path("/{id}/$last")
|
||||
@Interceptors(JaxRsExceptionInterceptor.class)
|
||||
public Response operationLastGet(@PathParam("id") String id)
|
||||
throws Exception {
|
||||
return customOperation(null, RequestTypeEnum.GET, id, "$last", RestOperationTypeEnum.EXTENDED_OPERATION_TYPE);
|
||||
}
|
||||
|
||||
@Search(compartmentName="Condition")
|
||||
public List<IResource> searchCompartment(@IdParam IdDt thePatientId) {
|
||||
List<IResource> retVal=new ArrayList<IResource>();
|
||||
Condition condition = new Condition();
|
||||
condition.setId(new IdDt("665577"));
|
||||
retVal.add(condition);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("/{id}/$last")
|
||||
@Interceptors(JaxRsExceptionInterceptor.class)
|
||||
public Response operationLast(final String resource)
|
||||
throws Exception {
|
||||
return customOperation(resource, RequestTypeEnum.POST, null, "$last", RestOperationTypeEnum.EXTENDED_OPERATION_TYPE);
|
||||
}
|
||||
|
||||
// @ca.uhn.fhir.rest.annotation.Validate
|
||||
// public MethodOutcome validate(
|
||||
// @ResourceParam T theResource,
|
||||
// @ResourceParam String theRawResource,
|
||||
// @ResourceParam EncodingEnum theEncoding,
|
||||
// @ca.uhn.fhir.rest.annotation.Validate.Mode ValidationModeEnum theMode,
|
||||
// @ca.uhn.fhir.rest.annotation.Validate.Profile String theProfile) {
|
||||
// return validate(theResource, null, theRawResource, theEncoding, theMode, theProfile);
|
||||
// }
|
||||
|
||||
@Operation(name="last", idempotent=true, returnParameters= {
|
||||
@OperationParam(name="return", type=StringDt.class)
|
||||
})
|
||||
public Parameters last(@OperationParam(name = "dummy") StringDt dummyInput) {
|
||||
System.out.println("inputparameter");
|
||||
Parameters parameters = new Parameters();
|
||||
Patient patient = find(new IdDt(counter.intValue()-1));
|
||||
parameters
|
||||
.addParameter()
|
||||
.setName("return")
|
||||
.setResource(patient)
|
||||
.setValue(new StringDt((counter-1)+"" + "inputVariable [ " + dummyInput.getValue()+ "]"));
|
||||
return parameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Patient> getResourceType() {
|
||||
return Patient.class;
|
||||
}
|
||||
|
||||
/** THE DEFAULTS */
|
||||
@Override
|
||||
public List<IServerInterceptor> getInterceptors() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ETagSupportEnum getETagSupport() {
|
||||
return ETagSupportEnum.DISABLED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDefaultPrettyPrint() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AddProfileTagEnum getAddProfileTag() {
|
||||
return AddProfileTagEnum.NEVER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUseBrowserFriendlyContentTypes() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPagingProvider getPagingProvider() {
|
||||
return new FifoMemoryPagingProvider(10);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BundleInclusionRule getBundleInclusionRule() {
|
||||
return BundleInclusionRule.BASED_ON_INCLUDES;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package ca.uhn.fhir.jaxrs.server.example;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Provides server ports
|
||||
*/
|
||||
public class RandomServerPortProvider {
|
||||
|
||||
private static List<Integer> ourPorts = new ArrayList<Integer>();
|
||||
|
||||
public static int findFreePort() {
|
||||
ServerSocket server;
|
||||
try {
|
||||
server = new ServerSocket(0);
|
||||
int port = server.getLocalPort();
|
||||
ourPorts.add(port);
|
||||
server.close();
|
||||
Thread.sleep(500);
|
||||
return port;
|
||||
} catch (IOException e) {
|
||||
throw new Error(e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<Integer> list() {
|
||||
return ourPorts;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package ca.uhn.fhir.jaxrs.server.example;
|
||||
|
||||
import ca.uhn.fhir.jaxrs.server.AbstractJaxRsResourceProvider;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
|
||||
public class TestDummyPatientProvider extends AbstractJaxRsResourceProvider<Patient> {
|
||||
|
||||
@Override
|
||||
public Class<Patient> getResourceType() {
|
||||
return Patient.class;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
package ca.uhn.fhir.jaxrs.server.util;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.ws.rs.HttpMethod;
|
||||
import javax.ws.rs.core.MultivaluedHashMap;
|
||||
import javax.ws.rs.core.MultivaluedMap;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.glassfish.jersey.internal.MapPropertiesDelegate;
|
||||
import org.glassfish.jersey.server.ContainerRequest;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.jaxrs.server.example.TestDummyPatientProvider;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||
|
||||
public class JaxRsRequestTest {
|
||||
|
||||
private static final String RESOURCE_STRING = "</Patient>";
|
||||
private static final String BASEURI = "http://baseuri";
|
||||
private static final String REQUESTURI = "http://baseuri/test";
|
||||
|
||||
private JaxRsRequest details;
|
||||
private MultivaluedMap<String, String> queryParameters = new MultivaluedHashMap<String, String>();
|
||||
private ContainerRequest headers;
|
||||
private TestDummyPatientProvider provider;
|
||||
|
||||
@Before
|
||||
public void setUp() throws URISyntaxException {
|
||||
details = createRequestDetails();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetHeader() {
|
||||
String headerKey = "key";
|
||||
String headerValue = "location_value";
|
||||
String headerValue2 = "location_value_2";
|
||||
assertTrue(StringUtils.isBlank(details.getHeader(headerKey)));
|
||||
headers.header(headerKey, headerValue);
|
||||
assertEquals(headerValue, details.getHeader(headerKey));
|
||||
assertEquals(Arrays.asList(headerValue), details.getHeaders(headerKey));
|
||||
|
||||
headers.header(headerKey, headerValue2);
|
||||
assertEquals(headerValue, details.getHeader(headerKey));
|
||||
assertEquals(Arrays.asList(headerValue, headerValue2), details.getHeaders(headerKey));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetByteStreamRequestContents() {
|
||||
assertEquals(RESOURCE_STRING, new String(details.getByteStreamRequestContents()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServerBaseForRequest() {
|
||||
assertEquals(BASEURI, new String(details.getServerBaseForRequest()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetResponse() {
|
||||
JaxRsResponse response = (JaxRsResponse) details.getResponse();
|
||||
assertEquals(details, response.getRequestDetails());
|
||||
assertTrue(response == details.getResponse());
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void testGetReader() throws IOException {
|
||||
details.getReader();
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void testGetInputStream() {
|
||||
details.getInputStream();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetServerBaseForRequest() {
|
||||
assertEquals(JaxRsRequestTest.BASEURI, details.getFhirServerBase());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetServer() {
|
||||
assertEquals(this.provider, details.getServer());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJaxRsRequestDetails() {
|
||||
Validate.notNull(new JaxRsRequest());
|
||||
}
|
||||
|
||||
public JaxRsRequest createRequestDetails() throws URISyntaxException {
|
||||
//headers
|
||||
headers = new ContainerRequest(new URI(BASEURI), new URI(REQUESTURI), HttpMethod.GET, null, new MapPropertiesDelegate());
|
||||
|
||||
//uri info
|
||||
UriInfo uriInfo = mock(UriInfo.class);
|
||||
when(uriInfo.getQueryParameters()).thenReturn(queryParameters);
|
||||
|
||||
//mocks
|
||||
provider = spy(TestDummyPatientProvider.class);
|
||||
doReturn(uriInfo).when(provider).getInfo();
|
||||
doReturn(BASEURI).when(provider).getBaseUri();
|
||||
doReturn(headers).when(provider).getHeaders();
|
||||
|
||||
return new JaxRsRequest(provider, RESOURCE_STRING, RequestTypeEnum.GET, RestOperationTypeEnum.HISTORY_TYPE);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,196 @@
|
|||
package ca.uhn.fhir.jaxrs.server.util;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseBinary;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Binary;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.api.SummaryEnum;
|
||||
import ca.uhn.fhir.rest.method.ParseAction;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.RestfulServerUtils;
|
||||
|
||||
public class JaxRsResponseTest {
|
||||
|
||||
private JaxRsResponse response;
|
||||
private JaxRsRequest request;
|
||||
private Bundle bundle;
|
||||
private Set<SummaryEnum> theSummaryMode;
|
||||
|
||||
@Before
|
||||
public void setUp() throws URISyntaxException {
|
||||
request = new JaxRsRequestTest().createRequestDetails();
|
||||
this.response = (JaxRsResponse) request.getResponse();
|
||||
bundle = getSinglePatientResource();
|
||||
theSummaryMode = Collections.<SummaryEnum>emptySet();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetResponseWriterNoZipNoBrowser() throws IOException {
|
||||
boolean theRequestIsBrowser = false;
|
||||
boolean respondGzip = false;
|
||||
Set<SummaryEnum> theSummaryMode = Collections.<SummaryEnum>emptySet();
|
||||
Response result = (Response) RestfulServerUtils.streamResponseAsBundle(request.getServer(), bundle, theSummaryMode, theRequestIsBrowser, respondGzip, request);
|
||||
assertEquals(200, result.getStatus());
|
||||
assertEquals(Constants.CT_FHIR_JSON, result.getHeaderString(Constants.HEADER_CONTENT_TYPE));
|
||||
assertTrue(result.getEntity().toString().contains("Patient"));
|
||||
assertTrue(result.getEntity().toString().contains("15"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetResponseWriterBrowserNoZip() throws IOException {
|
||||
boolean theRequestIsBrowser = true;
|
||||
boolean respondGzip = false;
|
||||
Response result = (Response) RestfulServerUtils.streamResponseAsBundle(request.getServer(), bundle, theSummaryMode, theRequestIsBrowser, respondGzip, request);
|
||||
assertEquals(200, result.getStatus());
|
||||
assertEquals(Constants.CT_JSON, result.getHeaderString(Constants.HEADER_CONTENT_TYPE));
|
||||
assertTrue(result.getEntity().toString().contains("Patient"));
|
||||
assertTrue(result.getEntity().toString().contains("15"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetResponseWriterWithZip() throws IOException {
|
||||
boolean theRequestIsBrowser = true;
|
||||
boolean respondGzip = true;
|
||||
Response result = (Response) RestfulServerUtils.streamResponseAsBundle(request.getServer(), bundle, theSummaryMode, theRequestIsBrowser, respondGzip, request);
|
||||
assertEquals(200, result.getStatus());
|
||||
assertEquals(Constants.CT_JSON, result.getHeaderString(Constants.HEADER_CONTENT_TYPE));
|
||||
assertEquals(Constants.ENCODING_GZIP, result.getHeaderString(Constants.HEADER_CONTENT_ENCODING));
|
||||
// assertTrue(unzip(result.getEntity()).contains("Patient"));
|
||||
// assertTrue(result.getEntity().toString().contains("15"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendAttachmentResponse() throws IOException {
|
||||
boolean theRequestIsBrowser = true;
|
||||
boolean respondGzip = true;
|
||||
IBaseBinary binary = new Binary();
|
||||
String contentType = "foo";
|
||||
byte[] content = new byte[] { 1, 2, 3, 4 };
|
||||
binary.setContentType(contentType);
|
||||
binary.setContent(content);
|
||||
boolean theAddContentLocationHeader = false;
|
||||
Response result = (Response) RestfulServerUtils.streamResponseAsResource(request.getServer(), binary, theRequestIsBrowser, theSummaryMode, 200, respondGzip, theAddContentLocationHeader, respondGzip, this.request);
|
||||
assertEquals(200, result.getStatus());
|
||||
assertEquals(contentType, result.getHeaderString(Constants.HEADER_CONTENT_TYPE));
|
||||
assertEquals(content, result.getEntity());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendAttachmentResponseNoContent() throws IOException {
|
||||
boolean theRequestIsBrowser = true;
|
||||
boolean respondGzip = true;
|
||||
IBaseBinary binary = new Binary();
|
||||
binary.setContent(new byte[]{});
|
||||
boolean theAddContentLocationHeader = false;
|
||||
Response result = (Response) RestfulServerUtils.streamResponseAsResource(request.getServer(), binary, theRequestIsBrowser, theSummaryMode, 200, respondGzip, theAddContentLocationHeader, respondGzip, this.request);
|
||||
assertEquals(200, result.getStatus());
|
||||
assertEquals(null, result.getHeaderString(Constants.HEADER_CONTENT_TYPE));
|
||||
assertEquals(null, result.getEntity());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendAttachmentResponseEmptyContent() throws IOException {
|
||||
boolean theRequestIsBrowser = true;
|
||||
boolean respondGzip = true;
|
||||
IBaseBinary binary = new Binary();
|
||||
boolean theAddContentLocationHeader = false;
|
||||
Response result = (Response) RestfulServerUtils.streamResponseAsResource(request.getServer(), binary, theRequestIsBrowser, theSummaryMode, 200, respondGzip, theAddContentLocationHeader, respondGzip, this.request);
|
||||
assertEquals(200, result.getStatus());
|
||||
assertEquals(null, result.getHeaderString(Constants.HEADER_CONTENT_TYPE));
|
||||
assertEquals(null, result.getEntity());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testReturnResponse() throws IOException {
|
||||
IdDt theId = new IdDt(15L);
|
||||
ParseAction<?> outcome = ParseAction.create(createPatient());
|
||||
int operationStatus = 200;
|
||||
boolean allowPrefer = true;
|
||||
String resourceName = "Patient";
|
||||
MethodOutcome methodOutcome = new MethodOutcome(theId);
|
||||
Response result = response.returnResponse(outcome, operationStatus, allowPrefer, methodOutcome, resourceName);
|
||||
assertEquals(200, result.getStatus());
|
||||
assertEquals(Constants.CT_JSON, result.getHeaderString(Constants.HEADER_CONTENT_TYPE));
|
||||
System.out.println(result.getEntity().toString());
|
||||
assertTrue(result.getEntity().toString().contains("resourceType\":\"Patient"));
|
||||
assertTrue(result.getEntity().toString().contains("15"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReturnResponseAsXml() throws IOException {
|
||||
IdDt theId = new IdDt(15L);
|
||||
ParseAction<?> outcome = ParseAction.create(createPatient());
|
||||
int operationStatus = 200;
|
||||
boolean allowPrefer = true;
|
||||
String resourceName = "Patient";
|
||||
MethodOutcome methodOutcome = new MethodOutcome(theId);
|
||||
response.getRequestDetails().getParameters().put(Constants.PARAM_FORMAT, new String[]{Constants.CT_XML});
|
||||
Response result = response.returnResponse(outcome, operationStatus, allowPrefer, methodOutcome, resourceName);
|
||||
assertEquals(200, result.getStatus());
|
||||
assertEquals(Constants.CT_XML, result.getHeaderString(Constants.HEADER_CONTENT_TYPE));
|
||||
assertTrue(result.getEntity().toString().contains("<Patient"));
|
||||
assertTrue(result.getEntity().toString().contains("15"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoOutcomeXml() throws IOException {
|
||||
ParseAction<?> outcome = ParseAction.create((IBaseResource) null);
|
||||
int operationStatus = Constants.STATUS_HTTP_204_NO_CONTENT;
|
||||
boolean allowPrefer = true;
|
||||
String resourceName = "Patient";
|
||||
MethodOutcome methodOutcome = new MethodOutcome(null);
|
||||
response.getRequestDetails().getParameters().put(Constants.PARAM_FORMAT, new String[]{Constants.CT_XML});
|
||||
Response result = response.returnResponse(outcome, operationStatus, allowPrefer, methodOutcome, resourceName);
|
||||
assertEquals(204, result.getStatus());
|
||||
assertEquals(Constants.CT_XML, result.getHeaderString(Constants.HEADER_CONTENT_TYPE));
|
||||
}
|
||||
|
||||
private String unzip(Object entity) throws IOException {
|
||||
byte[] compressed = ((String) entity).getBytes(Constants.CHARSET_NAME_UTF8);
|
||||
final int BUFFER_SIZE = 32;
|
||||
ByteArrayInputStream is = new ByteArrayInputStream(compressed);
|
||||
GZIPInputStream gis = new GZIPInputStream(is, BUFFER_SIZE);
|
||||
StringBuilder string = new StringBuilder();
|
||||
byte[] data = new byte[BUFFER_SIZE];
|
||||
int bytesRead;
|
||||
while ((bytesRead = gis.read(data)) != -1) {
|
||||
string.append(new String(data, 0, bytesRead));
|
||||
}
|
||||
gis.close();
|
||||
is.close();
|
||||
return string.toString();
|
||||
}
|
||||
|
||||
private Bundle getSinglePatientResource() {
|
||||
Patient theResource = createPatient();
|
||||
Bundle bundle = Bundle.withSingleResource(theResource);
|
||||
return bundle;
|
||||
}
|
||||
|
||||
private Patient createPatient() {
|
||||
Patient theResource = new Patient();
|
||||
theResource.setId(new IdDt(15L));
|
||||
return theResource;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,127 @@
|
|||
package ca.uhn.fhir.jaxrs.server.util;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.FixMethodOrder;
|
||||
import org.junit.Test;
|
||||
import org.junit.runners.MethodSorters;
|
||||
|
||||
import ca.uhn.fhir.jaxrs.server.example.TestDummyPatientProvider;
|
||||
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.annotation.RequiredParam;
|
||||
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
||||
import ca.uhn.fhir.rest.annotation.Search;
|
||||
import ca.uhn.fhir.rest.annotation.Update;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
|
||||
@FixMethodOrder(MethodSorters.DEFAULT)
|
||||
public class MethodBindingsTest {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MethodBindings.getClassBindings().clear();
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void testFindMethodsForProviderNotDefinedMappingMethods() {
|
||||
new TestDummyPatientProvider().getBindings().getBinding(RestOperationTypeEnum.UPDATE, "");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindMethodsForProviderWithMethods() {
|
||||
class TestFindPatientProvider extends TestDummyPatientProvider {
|
||||
@Search
|
||||
public List<Patient> search(@RequiredParam(name = Patient.SP_NAME) final StringParam name) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
new TestFindPatientProvider();
|
||||
assertEquals(TestFindPatientProvider.class, new TestFindPatientProvider().getBindings().getBinding(RestOperationTypeEnum.SEARCH_TYPE).getMethod().getDeclaringClass());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindMethodsFor2ProvidersWithMethods() {
|
||||
class TestFindPatientProvider extends TestDummyPatientProvider {
|
||||
@Search
|
||||
public List<Patient> search(@RequiredParam(name = Patient.SP_NAME) final StringParam name) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
class TestUpdatePatientProvider extends TestDummyPatientProvider {
|
||||
@Update
|
||||
public MethodOutcome update(@IdParam final IdDt theId, @ResourceParam final Patient patient) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
assertEquals(TestFindPatientProvider.class, new TestFindPatientProvider().getBindings().getBinding(RestOperationTypeEnum.SEARCH_TYPE).getMethod().getDeclaringClass());
|
||||
assertEquals(TestUpdatePatientProvider.class, new TestUpdatePatientProvider().getBindings().getBinding(RestOperationTypeEnum.UPDATE).getMethod().getDeclaringClass());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindMethodsWithDoubleMethodsDeclaration() {
|
||||
class TestDoubleSearchProvider extends TestDummyPatientProvider {
|
||||
@Search
|
||||
public List<Patient> search1(@RequiredParam(name = Patient.SP_NAME) final StringParam name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Search
|
||||
public List<Patient> search2(@RequiredParam(name = Patient.SP_NAME) final StringParam name) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
try {
|
||||
new TestDoubleSearchProvider();
|
||||
fail();
|
||||
} catch(IllegalArgumentException e) {
|
||||
assertTrue(e.getMessage().contains("search1"));
|
||||
assertTrue(e.getMessage().contains("search2"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindMethodsWithMultipleMethods() {
|
||||
class TestFindPatientProvider extends TestDummyPatientProvider {
|
||||
@Search
|
||||
public List<Patient> search(@RequiredParam(name = Patient.SP_NAME) final StringParam name) {
|
||||
return null;
|
||||
}
|
||||
@Update
|
||||
public MethodOutcome update(@IdParam final IdDt theId, @ResourceParam final Patient patient) {
|
||||
return null;
|
||||
}
|
||||
@Operation(name = "firstMethod", idempotent = true, returnParameters = { @OperationParam(name = "return", type = StringDt.class) })
|
||||
public Parameters firstMethod(@OperationParam(name = "dummy") StringDt dummyInput) {
|
||||
return null;
|
||||
}
|
||||
@Operation(name = "secondMethod", returnParameters = { @OperationParam(name = "return", type = StringDt.class) })
|
||||
public Parameters secondMethod(@OperationParam(name = "dummy") StringDt dummyInput) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
MethodBindings bindings = new TestFindPatientProvider().getBindings();
|
||||
assertEquals("search", bindings.getBinding(RestOperationTypeEnum.SEARCH_TYPE).getMethod().getName());
|
||||
assertEquals("update", bindings.getBinding(RestOperationTypeEnum.UPDATE).getMethod().getName());
|
||||
assertEquals("firstMethod", bindings.getBinding(RestOperationTypeEnum.EXTENDED_OPERATION_TYPE, "$firstMethod").getMethod().getName());
|
||||
assertEquals("secondMethod", bindings.getBinding(RestOperationTypeEnum.EXTENDED_OPERATION_TYPE, "$secondMethod").getMethod().getName());
|
||||
try {
|
||||
bindings.getBinding(RestOperationTypeEnum.EXTENDED_OPERATION_TYPE, "$thirdMethod");
|
||||
fail();
|
||||
} catch(UnsupportedOperationException e){
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue