Updated jaxrsserver base and example for DSTU3
Added support for specifying DSTU3 in the constructors, where the default is DSTU2, to maintain backwards compatibility. Updated interface usage to IBase... (e.g., IResource -> IBaseResource), which is compatible with DSTU3. Added tests specifically for DSTU3; kept the existing tests as DSTU2. Provided examples for DSTU3.
This commit is contained in:
parent
2bc1950bc1
commit
31d16fca03
|
@ -43,6 +43,7 @@ import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseConformance;
|
import org.hl7.fhir.instance.model.api.IBaseConformance;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseMetaType;
|
import org.hl7.fhir.instance.model.api.IBaseMetaType;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
@ -169,7 +170,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BaseConformance conformance() {
|
public IBaseConformance conformance() {
|
||||||
if (myContext.getVersion().getVersion().equals(FhirVersionEnum.DSTU2_HL7ORG)) {
|
if (myContext.getVersion().getVersion().equals(FhirVersionEnum.DSTU2_HL7ORG)) {
|
||||||
throw new IllegalArgumentException("Must call fetchConformance() instead of conformance() for RI/DSTU3+ structures");
|
throw new IllegalArgumentException("Must call fetchConformance() instead of conformance() for RI/DSTU3+ structures");
|
||||||
}
|
}
|
||||||
|
@ -183,7 +184,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||||
Class<BaseConformance> conformance = (Class<BaseConformance>) myContext.getResourceDefinition("Conformance").getImplementingClass();
|
Class<BaseConformance> conformance = (Class<BaseConformance>) myContext.getResourceDefinition("Conformance").getImplementingClass();
|
||||||
|
|
||||||
ResourceResponseHandler<? extends BaseConformance> binding = new ResourceResponseHandler<BaseConformance>(conformance);
|
ResourceResponseHandler<? extends BaseConformance> binding = new ResourceResponseHandler<BaseConformance>(conformance);
|
||||||
BaseConformance resp = invokeClient(myContext, binding, invocation, myLogRequestAndResponse);
|
IBaseConformance resp = invokeClient(myContext, binding, invocation, myLogRequestAndResponse);
|
||||||
return resp;
|
return resp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2308,7 +2309,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||||
public MethodOutcome execute() {
|
public MethodOutcome execute() {
|
||||||
BaseHttpClientInvocation invocation = ValidateMethodBindingDstu2.createValidateInvocation(myContext, myResource);
|
BaseHttpClientInvocation invocation = ValidateMethodBindingDstu2.createValidateInvocation(myContext, myResource);
|
||||||
ResourceResponseHandler<BaseOperationOutcome> handler = new ResourceResponseHandler<BaseOperationOutcome>(null, null);
|
ResourceResponseHandler<BaseOperationOutcome> handler = new ResourceResponseHandler<BaseOperationOutcome>(null, null);
|
||||||
BaseOperationOutcome outcome = invoke(null, handler, invocation);
|
IBaseOperationOutcome outcome = invoke(null, handler, invocation);
|
||||||
MethodOutcome retVal = new MethodOutcome();
|
MethodOutcome retVal = new MethodOutcome();
|
||||||
retVal.setOperationOutcome(outcome);
|
retVal.setOperationOutcome(outcome);
|
||||||
return retVal;
|
return retVal;
|
||||||
|
|
|
@ -23,6 +23,7 @@ package ca.uhn.fhir.rest.client;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseConformance;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
|
||||||
import ca.uhn.fhir.model.api.Bundle;
|
import ca.uhn.fhir.model.api.Bundle;
|
||||||
|
@ -58,7 +59,7 @@ public interface IGenericClient extends IRestfulClient {
|
||||||
* @deprecated Use {@link #fetchConformance()} instead
|
* @deprecated Use {@link #fetchConformance()} instead
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
BaseConformance conformance();
|
IBaseConformance conformance();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fluent method for the "create" operation, which creates a new resource instance on the server
|
* Fluent method for the "create" operation, which creates a new resource instance on the server
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
package ca.uhn.fhir.rest.method;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR - Core Library
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 - 2016 University Health Network
|
||||||
|
* %%
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
||||||
|
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||||
|
import ca.uhn.fhir.rest.annotation.Validate;
|
||||||
|
import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
|
||||||
|
import ca.uhn.fhir.rest.param.ResourceParameter;
|
||||||
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
|
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||||
|
import ca.uhn.fhir.util.ParametersUtil;
|
||||||
|
|
||||||
|
public class ValidateMethodBindingDstu3 extends OperationMethodBinding {
|
||||||
|
|
||||||
|
public ValidateMethodBindingDstu3(Class<?> theReturnResourceType, Class<? extends IBaseResource> theReturnTypeFromRp, Method theMethod, FhirContext theContext, Object theProvider,
|
||||||
|
Validate theAnnotation) {
|
||||||
|
super(theReturnResourceType, theReturnTypeFromRp, theMethod, theContext, theProvider, true, Constants.EXTOP_VALIDATE, theAnnotation.type(), new OperationParam[0], BundleTypeEnum.COLLECTION);
|
||||||
|
|
||||||
|
List<IParameter> newParams = new ArrayList<IParameter>();
|
||||||
|
int idx = 0;
|
||||||
|
for (IParameter next : getParameters()) {
|
||||||
|
if (next instanceof ResourceParameter) {
|
||||||
|
if (IBaseResource.class.isAssignableFrom(((ResourceParameter) next).getResourceType())) {
|
||||||
|
Class<?> parameterType = theMethod.getParameterTypes()[idx];
|
||||||
|
if (String.class.equals(parameterType) || EncodingEnum.class.equals(parameterType)) {
|
||||||
|
newParams.add(next);
|
||||||
|
} else {
|
||||||
|
OperationParameter parameter = new OperationParameter(theContext, Constants.EXTOP_VALIDATE, Constants.EXTOP_VALIDATE_RESOURCE, 0, 1);
|
||||||
|
parameter.initializeTypes(theMethod, null, null, parameterType);
|
||||||
|
newParams.add(parameter);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
newParams.add(next);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
newParams.add(next);
|
||||||
|
}
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
setParameters(newParams);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static BaseHttpClientInvocation createValidateInvocation(FhirContext theContext, IBaseResource theResource) {
|
||||||
|
IBaseParameters parameters = (IBaseParameters) theContext.getResourceDefinition("Parameters").newInstance();
|
||||||
|
ParametersUtil.addParameterToParameters(theContext, parameters, theResource, "resource");
|
||||||
|
|
||||||
|
String resourceName = theContext.getResourceDefinition(theResource).getName();
|
||||||
|
String resourceId = theResource.getIdElement().getIdPart();
|
||||||
|
|
||||||
|
BaseHttpClientInvocation retVal = createOperationInvocation(theContext, resourceName, resourceId, Constants.EXTOP_VALIDATE, parameters, false);
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -40,6 +40,11 @@
|
||||||
<artifactId>hapi-fhir-structures-dstu2</artifactId>
|
<artifactId>hapi-fhir-structures-dstu2</artifactId>
|
||||||
<version>1.6-SNAPSHOT</version>
|
<version>1.6-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
|
<artifactId>hapi-fhir-structures-dstu3</artifactId>
|
||||||
|
<version>1.6-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.ws.rs</groupId>
|
<groupId>javax.ws.rs</groupId>
|
||||||
|
|
|
@ -39,12 +39,16 @@ import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.hl7.fhir.dstu3.hapi.rest.server.ServerConformanceProvider;
|
||||||
|
import org.hl7.fhir.dstu3.model.Conformance;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.ConfigurationException;
|
import ca.uhn.fhir.context.ConfigurationException;
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||||
import ca.uhn.fhir.jaxrs.server.util.JaxRsRequest.Builder;
|
import ca.uhn.fhir.jaxrs.server.util.JaxRsRequest.Builder;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Conformance;
|
|
||||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||||
|
@ -56,7 +60,6 @@ import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||||
import ca.uhn.fhir.rest.server.IRestfulResponse;
|
import ca.uhn.fhir.rest.server.IRestfulResponse;
|
||||||
import ca.uhn.fhir.rest.server.ResourceBinding;
|
import ca.uhn.fhir.rest.server.ResourceBinding;
|
||||||
import ca.uhn.fhir.rest.server.RestulfulServerConfiguration;
|
import ca.uhn.fhir.rest.server.RestulfulServerConfiguration;
|
||||||
import ca.uhn.fhir.rest.server.provider.dstu2.ServerConformanceProvider;
|
|
||||||
import ca.uhn.fhir.util.ReflectionUtil;
|
import ca.uhn.fhir.util.ReflectionUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -78,7 +81,8 @@ public abstract class AbstractJaxRsConformanceProvider extends AbstractJaxRsProv
|
||||||
private RestulfulServerConfiguration serverConfiguration = new RestulfulServerConfiguration();
|
private RestulfulServerConfiguration serverConfiguration = new RestulfulServerConfiguration();
|
||||||
|
|
||||||
/** the conformance. It is created once during startup */
|
/** the conformance. It is created once during startup */
|
||||||
private Conformance myConformance;
|
private Conformance myDstu3Conformance;
|
||||||
|
private ca.uhn.fhir.model.dstu2.resource.Conformance myDstu2Conformance;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor allowing the description, servername and server to be set
|
* Constructor allowing the description, servername and server to be set
|
||||||
|
@ -93,6 +97,21 @@ public abstract class AbstractJaxRsConformanceProvider extends AbstractJaxRsProv
|
||||||
serverConfiguration.setServerVersion(StringUtils.defaultIfEmpty(serverVersion, ""));
|
serverConfiguration.setServerVersion(StringUtils.defaultIfEmpty(serverVersion, ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor allowing the description, servername and server to be set
|
||||||
|
* @param ctx the {@link FhirContext} instance.
|
||||||
|
* @param implementationDescription the implementation description. If null, "" is used
|
||||||
|
* @param serverName the server name. If null, "" is used
|
||||||
|
* @param serverVersion the server version. If null, "" is used
|
||||||
|
*/
|
||||||
|
protected AbstractJaxRsConformanceProvider(FhirContext ctx, String implementationDescription, String serverName, String serverVersion) {
|
||||||
|
super(ctx);
|
||||||
|
serverConfiguration.setFhirContext(ctx);
|
||||||
|
serverConfiguration.setImplementationDescription(StringUtils.defaultIfEmpty(implementationDescription, ""));
|
||||||
|
serverConfiguration.setServerName(StringUtils.defaultIfEmpty(serverName, ""));
|
||||||
|
serverConfiguration.setServerVersion(StringUtils.defaultIfEmpty(serverVersion, ""));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method will set the conformance during the postconstruct phase. The
|
* This method will set the conformance during the postconstruct phase. The
|
||||||
* method {@link AbstractJaxRsConformanceProvider#getProviders()} is used to
|
* method {@link AbstractJaxRsConformanceProvider#getProviders()} is used to
|
||||||
|
@ -112,9 +131,15 @@ public abstract class AbstractJaxRsConformanceProvider extends AbstractJaxRsProv
|
||||||
HardcodedServerAddressStrategy hardcodedServerAddressStrategy = new HardcodedServerAddressStrategy();
|
HardcodedServerAddressStrategy hardcodedServerAddressStrategy = new HardcodedServerAddressStrategy();
|
||||||
hardcodedServerAddressStrategy.setValue(getBaseForServer());
|
hardcodedServerAddressStrategy.setValue(getBaseForServer());
|
||||||
serverConfiguration.setServerAddressStrategy(hardcodedServerAddressStrategy);
|
serverConfiguration.setServerAddressStrategy(hardcodedServerAddressStrategy);
|
||||||
|
if (super.getFhirContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU3)) {
|
||||||
ServerConformanceProvider serverConformanceProvider = new ServerConformanceProvider(serverConfiguration);
|
ServerConformanceProvider serverConformanceProvider = new ServerConformanceProvider(serverConfiguration);
|
||||||
serverConformanceProvider.initializeOperations();
|
serverConformanceProvider.initializeOperations();
|
||||||
myConformance = serverConformanceProvider.getServerConformance(null);
|
myDstu3Conformance = serverConformanceProvider.getServerConformance(null);
|
||||||
|
} else if (super.getFhirContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU2)) {
|
||||||
|
ca.uhn.fhir.rest.server.provider.dstu2.ServerConformanceProvider serverConformanceProvider = new ca.uhn.fhir.rest.server.provider.dstu2.ServerConformanceProvider(serverConfiguration);
|
||||||
|
serverConformanceProvider.initializeOperations();
|
||||||
|
myDstu2Conformance = serverConformanceProvider.getServerConformance(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -145,7 +170,12 @@ public abstract class AbstractJaxRsConformanceProvider extends AbstractJaxRsProv
|
||||||
Builder request = getRequest(RequestTypeEnum.OPTIONS, RestOperationTypeEnum.METADATA);
|
Builder request = getRequest(RequestTypeEnum.OPTIONS, RestOperationTypeEnum.METADATA);
|
||||||
IRestfulResponse response = request.build().getResponse();
|
IRestfulResponse response = request.build().getResponse();
|
||||||
response.addHeader(Constants.HEADER_CORS_ALLOW_ORIGIN, "*");
|
response.addHeader(Constants.HEADER_CORS_ALLOW_ORIGIN, "*");
|
||||||
return (Response) response.returnResponse(ParseAction.create(myConformance), Constants.STATUS_HTTP_200_OK, true, null, getResourceType().getSimpleName());
|
if (super.getFhirContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU3)) {
|
||||||
|
return (Response) response.returnResponse(ParseAction.create(myDstu3Conformance), Constants.STATUS_HTTP_200_OK, true, null, getResourceType().getSimpleName());
|
||||||
|
} else if (super.getFhirContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU2)) {
|
||||||
|
return (Response) response.returnResponse(ParseAction.create(myDstu2Conformance), Constants.STATUS_HTTP_200_OK, true, null, getResourceType().getSimpleName());
|
||||||
|
}
|
||||||
|
return (Response) response.returnResponse(null, Constants.STATUS_HTTP_500_INTERNAL_ERROR, true, null, getResourceType().getSimpleName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -217,9 +247,15 @@ public abstract class AbstractJaxRsConformanceProvider extends AbstractJaxRsProv
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public Class<Conformance> getResourceType() {
|
public Class<IBaseResource> getResourceType() {
|
||||||
return Conformance.class;
|
if (super.getFhirContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU3)) {
|
||||||
|
return Class.class.cast(Conformance.class);
|
||||||
|
} else if (super.getFhirContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU2)) {
|
||||||
|
return Class.class.cast(ca.uhn.fhir.model.dstu2.resource.Conformance.class);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ import javax.ws.rs.QueryParam;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.jaxrs.server.interceptor.JaxRsExceptionInterceptor;
|
import ca.uhn.fhir.jaxrs.server.interceptor.JaxRsExceptionInterceptor;
|
||||||
import ca.uhn.fhir.jaxrs.server.interceptor.JaxRsResponseException;
|
import ca.uhn.fhir.jaxrs.server.interceptor.JaxRsResponseException;
|
||||||
import ca.uhn.fhir.jaxrs.server.util.JaxRsRequest;
|
import ca.uhn.fhir.jaxrs.server.util.JaxRsRequest;
|
||||||
|
@ -65,6 +66,19 @@ public abstract class AbstractJaxRsPageProvider extends AbstractJaxRsProvider im
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides the ability to set the {@link FhirContext} instance.
|
||||||
|
* @param ctx the {@link FhirContext} instance.
|
||||||
|
*/
|
||||||
|
protected AbstractJaxRsPageProvider(FhirContext ctx) {
|
||||||
|
super(ctx);
|
||||||
|
try {
|
||||||
|
myBinding = new PageMethodBinding(getFhirContext(), PageProvider.class.getMethod("getPage"));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new ca.uhn.fhir.context.ConfigurationException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getBaseForRequest() {
|
public String getBaseForRequest() {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -53,8 +53,7 @@ import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractJaxRsProvider implements IRestfulServerDefaults {
|
public abstract class AbstractJaxRsProvider implements IRestfulServerDefaults {
|
||||||
|
|
||||||
/** a static initialization for the fhircontext. Only DSTU2 is supported */
|
private final FhirContext CTX;
|
||||||
private static final FhirContext CTX = FhirContext.forDstu2();
|
|
||||||
|
|
||||||
/** the uri info */
|
/** the uri info */
|
||||||
@Context
|
@Context
|
||||||
|
@ -68,6 +67,21 @@ public abstract class AbstractJaxRsProvider implements IRestfulServerDefaults {
|
||||||
return CTX;
|
return CTX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default is DSTU2. Use {@link AbstractJaxRsProvider#AbstractJaxRsProvider(FhirContext)} to specify a DSTU3 context.
|
||||||
|
*/
|
||||||
|
protected AbstractJaxRsProvider() {
|
||||||
|
CTX = FhirContext.forDstu2();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param ctx the {@link FhirContext} to support.
|
||||||
|
*/
|
||||||
|
protected AbstractJaxRsProvider(FhirContext ctx) {
|
||||||
|
CTX = ctx;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the query parameters
|
* This method returns the query parameters
|
||||||
* @return the query parameters
|
* @return the query parameters
|
||||||
|
|
|
@ -22,8 +22,6 @@ package ca.uhn.fhir.jaxrs.server;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.interceptor.Interceptors;
|
import javax.interceptor.Interceptors;
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.Consumes;
|
||||||
|
@ -37,12 +35,14 @@ import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.jaxrs.server.interceptor.JaxRsExceptionInterceptor;
|
import ca.uhn.fhir.jaxrs.server.interceptor.JaxRsExceptionInterceptor;
|
||||||
import ca.uhn.fhir.jaxrs.server.interceptor.JaxRsResponseException;
|
import ca.uhn.fhir.jaxrs.server.interceptor.JaxRsResponseException;
|
||||||
import ca.uhn.fhir.jaxrs.server.util.JaxRsMethodBindings;
|
import ca.uhn.fhir.jaxrs.server.util.JaxRsMethodBindings;
|
||||||
import ca.uhn.fhir.jaxrs.server.util.JaxRsRequest;
|
import ca.uhn.fhir.jaxrs.server.util.JaxRsRequest;
|
||||||
import ca.uhn.fhir.jaxrs.server.util.JaxRsRequest.Builder;
|
import ca.uhn.fhir.jaxrs.server.util.JaxRsRequest.Builder;
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
|
||||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||||
import ca.uhn.fhir.rest.method.BaseMethodBinding;
|
import ca.uhn.fhir.rest.method.BaseMethodBinding;
|
||||||
|
@ -51,7 +51,6 @@ import ca.uhn.fhir.rest.server.Constants;
|
||||||
import ca.uhn.fhir.rest.server.IPagingProvider;
|
import ca.uhn.fhir.rest.server.IPagingProvider;
|
||||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||||
import ca.uhn.fhir.rest.server.IRestfulServer;
|
import ca.uhn.fhir.rest.server.IRestfulServer;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This server is the abstract superclass for all resource providers. It exposes
|
* This server is the abstract superclass for all resource providers. It exposes
|
||||||
|
@ -62,7 +61,7 @@ import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||||
@Consumes({ MediaType.APPLICATION_FORM_URLENCODED, MediaType.APPLICATION_JSON, Constants.CT_FHIR_JSON,
|
@Consumes({ MediaType.APPLICATION_FORM_URLENCODED, MediaType.APPLICATION_JSON, Constants.CT_FHIR_JSON,
|
||||||
Constants.CT_FHIR_XML })
|
Constants.CT_FHIR_XML })
|
||||||
@Interceptors(JaxRsExceptionInterceptor.class)
|
@Interceptors(JaxRsExceptionInterceptor.class)
|
||||||
public abstract class AbstractJaxRsResourceProvider<R extends IResource> extends AbstractJaxRsProvider
|
public abstract class AbstractJaxRsResourceProvider<R extends IBaseResource> extends AbstractJaxRsProvider
|
||||||
implements IRestfulServer<JaxRsRequest>, IResourceProvider {
|
implements IRestfulServer<JaxRsRequest>, IResourceProvider {
|
||||||
|
|
||||||
/** the method bindings for this class */
|
/** the method bindings for this class */
|
||||||
|
@ -73,6 +72,16 @@ public abstract class AbstractJaxRsResourceProvider<R extends IResource> extends
|
||||||
* being constructed.
|
* being constructed.
|
||||||
*/
|
*/
|
||||||
protected AbstractJaxRsResourceProvider() {
|
protected AbstractJaxRsResourceProvider() {
|
||||||
|
super();
|
||||||
|
theBindings = JaxRsMethodBindings.getMethodBindings(this, getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides the ability to specify the {@link FhirContext}.
|
||||||
|
* @param ctx the {@link FhirContext} instance.
|
||||||
|
*/
|
||||||
|
protected AbstractJaxRsResourceProvider(FhirContext ctx) {
|
||||||
|
super(ctx);
|
||||||
theBindings = JaxRsMethodBindings.getMethodBindings(this, getClass());
|
theBindings = JaxRsMethodBindings.getMethodBindings(this, getClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,6 +94,21 @@ public abstract class AbstractJaxRsResourceProvider<R extends IResource> extends
|
||||||
* @param theProviderClass the interface of the class
|
* @param theProviderClass the interface of the class
|
||||||
*/
|
*/
|
||||||
protected AbstractJaxRsResourceProvider(Class<? extends AbstractJaxRsProvider> theProviderClass) {
|
protected AbstractJaxRsResourceProvider(Class<? extends AbstractJaxRsProvider> theProviderClass) {
|
||||||
|
super();
|
||||||
|
theBindings = JaxRsMethodBindings.getMethodBindings(this, theProviderClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This constructor takes in an explicit interface class. This subclass
|
||||||
|
* should be identical to the class being constructed but is given
|
||||||
|
* explicitly in order to avoid issues with proxy classes in a jee
|
||||||
|
* environment.
|
||||||
|
*
|
||||||
|
* @param ctx the {@link FhirContext} instance.
|
||||||
|
* @param theProviderClass the interface of the class
|
||||||
|
*/
|
||||||
|
protected AbstractJaxRsResourceProvider(FhirContext ctx, Class<? extends AbstractJaxRsProvider> theProviderClass) {
|
||||||
|
super(ctx);
|
||||||
theBindings = JaxRsMethodBindings.getMethodBindings(this, theProviderClass);
|
theBindings = JaxRsMethodBindings.getMethodBindings(this, theProviderClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,9 @@ import javax.ws.rs.core.HttpHeaders;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.hl7.fhir.dstu3.model.IdType;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||||
import ca.uhn.fhir.jaxrs.server.AbstractJaxRsProvider;
|
import ca.uhn.fhir.jaxrs.server.AbstractJaxRsProvider;
|
||||||
import ca.uhn.fhir.model.primitive.IdDt;
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||||
|
@ -130,19 +132,34 @@ public class JaxRsRequest extends RequestDetails {
|
||||||
+ myServer.getUriInfo().getRequestUri().toASCIIString());
|
+ myServer.getUriInfo().getRequestUri().toASCIIString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FhirVersionEnum fhirContextVersion = myServer.getFhirContext().getVersion().getVersion();
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(myVersion)) {
|
if (StringUtils.isNotBlank(myVersion)) {
|
||||||
|
if (FhirVersionEnum.DSTU3.equals(fhirContextVersion)) {
|
||||||
|
result.setId(
|
||||||
|
new IdType(myServer.getBaseForRequest(), UrlUtil.unescape(myId), UrlUtil.unescape(myVersion)));
|
||||||
|
} else if (FhirVersionEnum.DSTU2.equals(fhirContextVersion)) {
|
||||||
result.setId(
|
result.setId(
|
||||||
new IdDt(myServer.getBaseForRequest(), UrlUtil.unescape(myId), UrlUtil.unescape(myVersion)));
|
new IdDt(myServer.getBaseForRequest(), UrlUtil.unescape(myId), UrlUtil.unescape(myVersion)));
|
||||||
|
}
|
||||||
} else if (StringUtils.isNotBlank(myId)) {
|
} else if (StringUtils.isNotBlank(myId)) {
|
||||||
|
if (FhirVersionEnum.DSTU3.equals(fhirContextVersion)) {
|
||||||
|
result.setId(new IdType(myServer.getBaseForRequest(), UrlUtil.unescape(myId)));
|
||||||
|
} else if (FhirVersionEnum.DSTU2.equals(fhirContextVersion)) {
|
||||||
result.setId(new IdDt(myServer.getBaseForRequest(), UrlUtil.unescape(myId)));
|
result.setId(new IdDt(myServer.getBaseForRequest(), UrlUtil.unescape(myId)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (myRestOperation == RestOperationTypeEnum.UPDATE) {
|
if (myRestOperation == RestOperationTypeEnum.UPDATE) {
|
||||||
String contentLocation = result.getHeader(Constants.HEADER_CONTENT_LOCATION);
|
String contentLocation = result.getHeader(Constants.HEADER_CONTENT_LOCATION);
|
||||||
if (contentLocation != null) {
|
if (contentLocation != null) {
|
||||||
|
if (FhirVersionEnum.DSTU3.equals(fhirContextVersion)) {
|
||||||
|
result.setId(new IdType(contentLocation));
|
||||||
|
} else if (FhirVersionEnum.DSTU2.equals(fhirContextVersion)) {
|
||||||
result.setId(new IdDt(contentLocation));
|
result.setId(new IdDt(contentLocation));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
result.setCompartmentName(myCompartment);
|
result.setCompartmentName(myCompartment);
|
||||||
result.setCompleteUrl(myRequestUrl);
|
result.setCompleteUrl(myRequestUrl);
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,110 @@
|
||||||
|
package ca.uhn.fhir.jaxrs.server;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import javax.ws.rs.HttpMethod;
|
||||||
|
import javax.ws.rs.core.MultivaluedHashMap;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
import javax.ws.rs.core.UriInfo;
|
||||||
|
|
||||||
|
import org.glassfish.jersey.internal.MapPropertiesDelegate;
|
||||||
|
import org.glassfish.jersey.server.ContainerRequest;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.jaxrs.server.test.TestJaxRsDummyPatientProvider;
|
||||||
|
import ca.uhn.fhir.jaxrs.server.test.TestJaxRsMockPatientRestProviderDstu3;
|
||||||
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
|
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||||
|
|
||||||
|
public class AbstractJaxRsConformanceProviderDstu3Test {
|
||||||
|
|
||||||
|
private static final String BASEURI = "http://basiuri";
|
||||||
|
private static final String REQUESTURI = BASEURI + "/metadata";
|
||||||
|
AbstractJaxRsConformanceProvider provider;
|
||||||
|
private ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider> providers;
|
||||||
|
private ContainerRequest headers;
|
||||||
|
private MultivaluedHashMap<String, String> queryParameters;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
// headers
|
||||||
|
headers = new ContainerRequest(new URI(BASEURI), new URI(REQUESTURI), HttpMethod.GET, null,
|
||||||
|
new MapPropertiesDelegate());
|
||||||
|
// uri info
|
||||||
|
queryParameters = new MultivaluedHashMap<String, String>();
|
||||||
|
|
||||||
|
|
||||||
|
providers = new ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider>();
|
||||||
|
provider = createConformanceProvider(providers);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testConformance() throws Exception {
|
||||||
|
providers.put(AbstractJaxRsConformanceProvider.class, provider);
|
||||||
|
providers.put(TestJaxRsDummyPatientProvider.class, new TestJaxRsDummyPatientProvider());
|
||||||
|
Response response = createConformanceProvider(providers).conformance();
|
||||||
|
System.out.println(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testConformanceUsingOptions() throws Exception {
|
||||||
|
providers.put(AbstractJaxRsConformanceProvider.class, provider);
|
||||||
|
providers.put(TestJaxRsDummyPatientProvider.class, new TestJaxRsDummyPatientProvider());
|
||||||
|
Response response = createConformanceProvider(providers).conformanceUsingOptions();
|
||||||
|
System.out.println(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testConformanceWithMethods() throws Exception {
|
||||||
|
providers.put(AbstractJaxRsConformanceProvider.class, provider);
|
||||||
|
providers.put(TestJaxRsMockPatientRestProviderDstu3.class, new TestJaxRsMockPatientRestProviderDstu3());
|
||||||
|
Response response = createConformanceProvider(providers).conformance();
|
||||||
|
assertEquals(Constants.STATUS_HTTP_200_OK, response.getStatus());
|
||||||
|
assertTrue(response.getEntity().toString().contains("\"type\":\"Patient\""));
|
||||||
|
assertTrue(response.getEntity().toString().contains("\"$someCustomOperation"));
|
||||||
|
System.out.println(response);
|
||||||
|
System.out.println(response.getEntity());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testConformanceInXml() throws Exception {
|
||||||
|
queryParameters.put(Constants.PARAM_FORMAT, Arrays.asList(Constants.CT_XML));
|
||||||
|
providers.put(AbstractJaxRsConformanceProvider.class, provider);
|
||||||
|
providers.put(TestJaxRsMockPatientRestProviderDstu3.class, new TestJaxRsMockPatientRestProviderDstu3());
|
||||||
|
Response response = createConformanceProvider(providers).conformance();
|
||||||
|
assertEquals(Constants.STATUS_HTTP_200_OK, response.getStatus());
|
||||||
|
System.out.println(response.getEntity());
|
||||||
|
assertTrue(response.getEntity().toString().contains(" <type value=\"Patient\"/>"));
|
||||||
|
assertTrue(response.getEntity().toString().contains("\"$someCustomOperation"));
|
||||||
|
System.out.println(response.getEntity());
|
||||||
|
}
|
||||||
|
|
||||||
|
private AbstractJaxRsConformanceProvider createConformanceProvider(final ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider> providers)
|
||||||
|
throws Exception {
|
||||||
|
AbstractJaxRsConformanceProvider result = new AbstractJaxRsConformanceProvider(FhirContext.forDstu3(), null, null, null) {
|
||||||
|
@Override
|
||||||
|
protected ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider> getProviders() {
|
||||||
|
return providers;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// mocks
|
||||||
|
UriInfo uriInfo = mock(UriInfo.class);
|
||||||
|
when(uriInfo.getQueryParameters()).thenReturn(queryParameters);
|
||||||
|
when(uriInfo.getBaseUri()).thenReturn(new URI(BASEURI));
|
||||||
|
when(uriInfo.getRequestUri()).thenReturn(new URI(BASEURI + "/foo"));
|
||||||
|
result.setUriInfo(uriInfo);
|
||||||
|
result.setHeaders(headers);
|
||||||
|
result.setUpPostConstruct();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,443 @@
|
||||||
|
package ca.uhn.fhir.jaxrs.server;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
import static org.mockito.Matchers.any;
|
||||||
|
import static org.mockito.Matchers.argThat;
|
||||||
|
import static org.mockito.Matchers.eq;
|
||||||
|
import static org.mockito.Matchers.isNull;
|
||||||
|
import static org.mockito.Mockito.reset;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.eclipse.jetty.server.Server;
|
||||||
|
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||||
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
|
import org.hl7.fhir.dstu3.model.Bundle;
|
||||||
|
import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
|
||||||
|
import org.hl7.fhir.dstu3.model.Conformance;
|
||||||
|
import org.hl7.fhir.dstu3.model.DateType;
|
||||||
|
import org.hl7.fhir.dstu3.model.IdType;
|
||||||
|
import org.hl7.fhir.dstu3.model.Identifier;
|
||||||
|
import org.hl7.fhir.dstu3.model.Parameters;
|
||||||
|
import org.hl7.fhir.dstu3.model.Patient;
|
||||||
|
import org.hl7.fhir.dstu3.model.Resource;
|
||||||
|
import org.hl7.fhir.dstu3.model.StringType;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.FixMethodOrder;
|
||||||
|
import org.junit.Ignore;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runners.MethodSorters;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
import org.mockito.ArgumentMatcher;
|
||||||
|
import org.mockito.Matchers;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.jaxrs.client.JaxRsRestfulClientFactory;
|
||||||
|
import ca.uhn.fhir.jaxrs.server.interceptor.JaxRsExceptionInterceptor;
|
||||||
|
import ca.uhn.fhir.jaxrs.server.interceptor.JaxRsResponseException;
|
||||||
|
import ca.uhn.fhir.jaxrs.server.test.RandomServerPortProvider;
|
||||||
|
import ca.uhn.fhir.jaxrs.server.test.TestJaxRsConformanceRestProviderDstu3;
|
||||||
|
import ca.uhn.fhir.jaxrs.server.test.TestJaxRsMockPageProviderDstu3;
|
||||||
|
import ca.uhn.fhir.jaxrs.server.test.TestJaxRsMockPatientRestProviderDstu3;
|
||||||
|
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
||||||
|
import ca.uhn.fhir.model.primitive.UriDt;
|
||||||
|
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.param.StringAndListParam;
|
||||||
|
import ca.uhn.fhir.rest.param.StringParam;
|
||||||
|
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||||
|
|
||||||
|
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||||
|
public class AbstractJaxRsResourceProviderDstu3Test {
|
||||||
|
|
||||||
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(AbstractJaxRsResourceProviderDstu3Test.class);
|
||||||
|
private static IGenericClient client;
|
||||||
|
|
||||||
|
|
||||||
|
private static final FhirContext ourCtx = FhirContext.forDstu3();
|
||||||
|
private static final String PATIENT_NAME = "Van Houte";
|
||||||
|
|
||||||
|
private static int ourPort;
|
||||||
|
private static String serverBase;
|
||||||
|
private static Server jettyServer;
|
||||||
|
private TestJaxRsMockPatientRestProviderDstu3 mock;
|
||||||
|
private ArgumentCaptor<IdType> idCaptor;
|
||||||
|
private ArgumentCaptor<Patient> patientCaptor;
|
||||||
|
|
||||||
|
private void compareResultId(int id, IBaseResource resource) {
|
||||||
|
assertEquals(id, Integer.parseInt(resource.getIdElement().getIdPart()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void compareResultUrl(String url, IBaseResource resource) {
|
||||||
|
assertEquals(url, resource.getIdElement().getValueAsString().substring(serverBase.length() - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Patient createPatient(long id) {
|
||||||
|
Patient theResource = new Patient();
|
||||||
|
theResource.setId(new IdType(id));
|
||||||
|
return theResource;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Patient> createPatients(int firstId, int lastId) {
|
||||||
|
List<Patient> result = new ArrayList<Patient>(lastId - firstId);
|
||||||
|
for (long i = firstId; i <= lastId; i++) {
|
||||||
|
result.add(createPatient(i));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Find By Id */
|
||||||
|
@Test
|
||||||
|
public void findUsingGenericClientById() {
|
||||||
|
when(mock.find(any(IdType.class))).thenReturn(createPatient(1));
|
||||||
|
Patient result = client.read(Patient.class, "1");
|
||||||
|
compareResultId(1, result);
|
||||||
|
compareResultUrl("/Patient/1", result);
|
||||||
|
reset(mock);
|
||||||
|
when(mock.find(eq(result.getIdElement()))).thenReturn(createPatient(1));
|
||||||
|
result = (Patient) client.read(new UriDt(result.getId()));
|
||||||
|
compareResultId(1, result);
|
||||||
|
compareResultUrl("/Patient/1", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Bundle getPatientBundle(int size) {
|
||||||
|
Bundle result = new Bundle();
|
||||||
|
for (long i = 0; i < size; i++) {
|
||||||
|
Patient patient = createPatient(i);
|
||||||
|
BundleEntryComponent entry = new BundleEntryComponent();
|
||||||
|
entry.setResource(patient);
|
||||||
|
result.addEntry(entry);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
this.mock = TestJaxRsMockPatientRestProviderDstu3.mock;
|
||||||
|
idCaptor = ArgumentCaptor.forClass(IdType.class);
|
||||||
|
patientCaptor = ArgumentCaptor.forClass(Patient.class);
|
||||||
|
reset(mock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Conditional Creates */
|
||||||
|
@Test
|
||||||
|
public void testConditionalCreate() throws Exception {
|
||||||
|
Patient toCreate = createPatient(1);
|
||||||
|
MethodOutcome outcome = new MethodOutcome();
|
||||||
|
toCreate.getIdentifier().add(new Identifier().setValue("myIdentifier"));
|
||||||
|
outcome.setResource(toCreate);
|
||||||
|
|
||||||
|
when(mock.create(patientCaptor.capture(), eq("Patient?_format=json&identifier=2"))).thenReturn(outcome);
|
||||||
|
client.setEncoding(EncodingEnum.JSON);
|
||||||
|
|
||||||
|
MethodOutcome response = client.create().resource(toCreate).conditional()
|
||||||
|
.where(Patient.IDENTIFIER.exactly().identifier("2")).prefer(PreferReturnEnum.REPRESENTATION).execute();
|
||||||
|
|
||||||
|
assertEquals("myIdentifier", patientCaptor.getValue().getIdentifier().get(0).getValue());
|
||||||
|
IBaseResource resource = response.getResource();
|
||||||
|
compareResultId(1, resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Conformance - Server */
|
||||||
|
@Test
|
||||||
|
public void testConformance() {
|
||||||
|
final Conformance conf = client.fetchConformance().ofType(Conformance.class).execute();
|
||||||
|
assertEquals(conf.getRest().get(0).getResource().get(0).getType().toString(), "Patient");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreatePatient() throws Exception {
|
||||||
|
Patient toCreate = createPatient(1);
|
||||||
|
MethodOutcome outcome = new MethodOutcome();
|
||||||
|
toCreate.getIdentifier().add(new Identifier().setValue("myIdentifier"));
|
||||||
|
outcome.setResource(toCreate);
|
||||||
|
|
||||||
|
when(mock.create(patientCaptor.capture(), isNull(String.class))).thenReturn(outcome);
|
||||||
|
client.setEncoding(EncodingEnum.JSON);
|
||||||
|
final MethodOutcome response = client.create().resource(toCreate).prefer(PreferReturnEnum.REPRESENTATION)
|
||||||
|
.execute();
|
||||||
|
IBaseResource resource = (IBaseResource) response.getResource();
|
||||||
|
compareResultId(1, resource);
|
||||||
|
assertEquals("myIdentifier", patientCaptor.getValue().getIdentifier().get(0).getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDeletePatient() {
|
||||||
|
when(mock.delete(idCaptor.capture())).thenReturn(new MethodOutcome());
|
||||||
|
final BaseOperationOutcome results = client.delete().resourceById("Patient", "1").execute();
|
||||||
|
assertEquals("1", idCaptor.getValue().getIdPart());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Extended Operations */
|
||||||
|
@Test
|
||||||
|
public void testExtendedOperations() {
|
||||||
|
// prepare mock
|
||||||
|
Parameters resultParameters = new Parameters();
|
||||||
|
resultParameters.addParameter().setName("return").setResource(createPatient(1)).setValue(new StringType("outputValue"));
|
||||||
|
when(mock.someCustomOperation(any(IdType.class), argThat(new StringTypeMatcher(new StringType("myAwesomeDummyValue"))))).thenReturn(resultParameters);
|
||||||
|
// Create the input parameters to pass to the server
|
||||||
|
Parameters inParams = new Parameters();
|
||||||
|
inParams.addParameter().setName("start").setValue(new DateType("2001-01-01"));
|
||||||
|
inParams.addParameter().setName("end").setValue(new DateType("2015-03-01"));
|
||||||
|
inParams.addParameter().setName("dummy").setValue(new StringType("myAwesomeDummyValue"));
|
||||||
|
//invoke
|
||||||
|
Parameters outParams = client.operation().onInstance(new IdType("Patient", "1")).named("$someCustomOperation")
|
||||||
|
.withParameters(inParams).execute();
|
||||||
|
//verify
|
||||||
|
assertEquals("outputValue", ((StringType)outParams.getParameter().get(0).getValue()).getValueAsString());
|
||||||
|
}
|
||||||
|
|
||||||
|
class StringTypeMatcher extends ArgumentMatcher<StringType> {
|
||||||
|
private StringType myStringType;
|
||||||
|
|
||||||
|
public StringTypeMatcher(StringType stringType) {
|
||||||
|
myStringType = stringType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean matches(Object argument) {
|
||||||
|
return myStringType.getValue().equals(((StringType)argument).getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExtendedOperationsUsingGet() {
|
||||||
|
// prepare mock
|
||||||
|
Parameters resultParameters = new Parameters();
|
||||||
|
resultParameters.addParameter().setName("return").setResource(createPatient(1)).setValue(new StringType("outputValue"));
|
||||||
|
when(mock.someCustomOperation(any(IdType.class), argThat(new StringTypeMatcher(new StringType("myAwesomeDummyValue"))))).thenReturn(resultParameters);
|
||||||
|
// Create the input parameters to pass to the server
|
||||||
|
Parameters inParams = new Parameters();
|
||||||
|
inParams.addParameter().setName("start").setValue(new DateType("2001-01-01"));
|
||||||
|
inParams.addParameter().setName("end").setValue(new DateType("2015-03-01"));
|
||||||
|
inParams.addParameter().setName("dummy").setValue(new StringType("myAwesomeDummyValue"));
|
||||||
|
|
||||||
|
// invoke
|
||||||
|
Parameters outParams = client.operation().onInstance(new IdType("Patient", "1")).named("$someCustomOperation")
|
||||||
|
.withParameters(inParams).useHttpGet().execute();
|
||||||
|
// verify
|
||||||
|
assertEquals("outputValue", ((StringType)outParams.getParameter().get(0).getValue()).getValueAsString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Search using other query options */
|
||||||
|
public void testOther() {
|
||||||
|
// missing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRead() {
|
||||||
|
when(mock.find(idCaptor.capture())).thenReturn(createPatient(1));
|
||||||
|
final Patient patient = client.read(Patient.class, "1");
|
||||||
|
compareResultId(1, patient);
|
||||||
|
compareResultUrl("/Patient/1", patient);
|
||||||
|
assertEquals("1", idCaptor.getValue().getIdPart());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Search - Compartments */
|
||||||
|
@Test
|
||||||
|
public void testSearchCompartements() {
|
||||||
|
when(mock.searchCompartment(any(IdType.class))).thenReturn(Arrays.asList((IBaseResource) createPatient(1)));
|
||||||
|
org.hl7.fhir.dstu3.model.Bundle response = client.search().forResource(Patient.class).withIdAndCompartment("1", "Condition")
|
||||||
|
.returnBundle(org.hl7.fhir.dstu3.model.Bundle.class).execute();
|
||||||
|
Resource resource = response.getEntry().get(0).getResource();
|
||||||
|
compareResultId(1, resource);
|
||||||
|
compareResultUrl("/Patient/1", resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** */
|
||||||
|
@Test
|
||||||
|
public void testSearchPost() {
|
||||||
|
when(mock.search(any(StringParam.class), Matchers.isNull(StringAndListParam.class)))
|
||||||
|
.thenReturn(createPatients(1, 13));
|
||||||
|
org.hl7.fhir.dstu3.model.Bundle result = client.search().forResource("Patient").usingStyle(SearchStyleEnum.POST)
|
||||||
|
.returnBundle(org.hl7.fhir.dstu3.model.Bundle.class).execute();
|
||||||
|
Resource resource = result.getEntry().get(0).getResource();
|
||||||
|
compareResultId(1, resource);
|
||||||
|
compareResultUrl("/Patient/1", resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Search/Query - Type */
|
||||||
|
@Test
|
||||||
|
public void testSearchUsingGenericClientBySearch() {
|
||||||
|
// Perform a search
|
||||||
|
when(mock.search(any(StringParam.class), Matchers.isNull(StringAndListParam.class)))
|
||||||
|
.thenReturn(Arrays.asList(createPatient(1)));
|
||||||
|
final Bundle results = client.search().forResource(Patient.class)
|
||||||
|
.where(Patient.NAME.matchesExactly().value(PATIENT_NAME)).returnBundle(Bundle.class).execute();
|
||||||
|
verify(mock).search(any(StringParam.class), Matchers.isNull(StringAndListParam.class));
|
||||||
|
IBaseResource resource = results.getEntry().get(0).getResource();
|
||||||
|
|
||||||
|
compareResultId(1, resource);
|
||||||
|
compareResultUrl("/Patient/1", resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Search - Multi-valued Parameters (ANY/OR) */
|
||||||
|
@Test
|
||||||
|
public void testSearchUsingGenericClientBySearchWithMultiValues() {
|
||||||
|
when(mock.search(any(StringParam.class), Matchers.isNotNull(StringAndListParam.class)))
|
||||||
|
.thenReturn(Arrays.asList(createPatient(1)));
|
||||||
|
final Bundle results = 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")).returnBundle(Bundle.class).execute();
|
||||||
|
IBaseResource resource = results.getEntry().get(0).getResource();
|
||||||
|
|
||||||
|
compareResultId(1, resource);
|
||||||
|
compareResultUrl("/Patient/1", resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Search - Paging */
|
||||||
|
@Test
|
||||||
|
public void testSearchWithPaging() {
|
||||||
|
// Perform a search
|
||||||
|
when(mock.search(any(StringParam.class), Matchers.isNull(StringAndListParam.class)))
|
||||||
|
.thenReturn(createPatients(1, 13));
|
||||||
|
final org.hl7.fhir.dstu3.model.Bundle results = client.search().forResource(Patient.class).count(8).returnBundle(org.hl7.fhir.dstu3.model.Bundle.class)
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
assertEquals(results.getEntry().size(), 8);
|
||||||
|
IBaseResource resource = results.getEntry().get(0).getResource();
|
||||||
|
compareResultId(1, resource);
|
||||||
|
compareResultUrl("/Patient/1", resource);
|
||||||
|
compareResultId(8, results.getEntry().get(7).getResource());
|
||||||
|
|
||||||
|
// ourLog.info("Next: " + results.getLink("next").getUrl());
|
||||||
|
// String url = results.getLink("next").getUrl().replace("?", "Patient?");
|
||||||
|
// results.getLink("next").setUrl(url);
|
||||||
|
// ourLog.info("New Next: " + results.getLink("next").getUrl());
|
||||||
|
|
||||||
|
// load next page
|
||||||
|
final org.hl7.fhir.dstu3.model.Bundle nextPage = client.loadPage().next(results).execute();
|
||||||
|
resource = nextPage.getEntry().get(0).getResource();
|
||||||
|
compareResultId(9, resource);
|
||||||
|
compareResultUrl("/Patient/9", resource);
|
||||||
|
assertNull(nextPage.getLink(org.hl7.fhir.dstu3.model.Bundle.LINK_NEXT));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Search - Subsetting (_summary and _elements) */
|
||||||
|
@Test
|
||||||
|
@Ignore
|
||||||
|
public void testSummary() {
|
||||||
|
Object response = client.search().forResource(Patient.class)
|
||||||
|
.returnBundle(org.hl7.fhir.dstu3.model.Bundle.class).execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 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.getName().get(0).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();
|
||||||
|
// }
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUpdateById() throws Exception {
|
||||||
|
when(mock.update(idCaptor.capture(), patientCaptor.capture())).thenReturn(new MethodOutcome());
|
||||||
|
client.update("1", createPatient(1));
|
||||||
|
assertEquals("1", idCaptor.getValue().getIdPart());
|
||||||
|
compareResultId(1, patientCaptor.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Ignore
|
||||||
|
@Test
|
||||||
|
public void testResourceNotFound() throws Exception {
|
||||||
|
when(mock.update(idCaptor.capture(), patientCaptor.capture())).thenThrow(ResourceNotFoundException.class);
|
||||||
|
try {
|
||||||
|
client.update("1", createPatient(2));
|
||||||
|
fail();
|
||||||
|
} catch (ResourceNotFoundException e) {
|
||||||
|
// good
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testVRead() {
|
||||||
|
when(mock.findHistory(idCaptor.capture())).thenReturn(createPatient(1));
|
||||||
|
final Patient patient = client.vread(Patient.class, "1", "2");
|
||||||
|
compareResultId(1, patient);
|
||||||
|
compareResultUrl("/Patient/1", patient);
|
||||||
|
assertEquals("1", idCaptor.getValue().getIdPart());
|
||||||
|
assertEquals("2", idCaptor.getValue().getVersionIdPart());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testXFindUnknownPatient() {
|
||||||
|
try {
|
||||||
|
JaxRsResponseException notFoundException = new JaxRsResponseException(new ResourceNotFoundException(new IdType("999955541264")));
|
||||||
|
when(mock.find(idCaptor.capture())).thenThrow(notFoundException);
|
||||||
|
client.read(Patient.class, "999955541264");
|
||||||
|
fail();
|
||||||
|
} catch (final ResourceNotFoundException e) {
|
||||||
|
assertEquals(ResourceNotFoundException.STATUS_CODE, e.getStatusCode());
|
||||||
|
assertTrue(e.getMessage().contains("999955541264"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@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);
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
jerseyServlet.setInitParameter("jersey.config.server.provider.classnames",
|
||||||
|
StringUtils.join(Arrays.asList(
|
||||||
|
TestJaxRsMockPatientRestProviderDstu3.class.getCanonicalName(),
|
||||||
|
JaxRsExceptionInterceptor.class.getCanonicalName(),
|
||||||
|
TestJaxRsConformanceRestProviderDstu3.class.getCanonicalName(),
|
||||||
|
TestJaxRsMockPageProviderDstu3.class.getCanonicalName()
|
||||||
|
), ";"));
|
||||||
|
//@formatter:on
|
||||||
|
|
||||||
|
jettyServer.start();
|
||||||
|
|
||||||
|
ourCtx.setRestfulClientFactory(new JaxRsRestfulClientFactory(ourCtx));
|
||||||
|
ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
|
||||||
|
ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000);
|
||||||
|
serverBase = "http://localhost:" + ourPort + "/";
|
||||||
|
client = ourCtx.newRestfulGenericClient(serverBase);
|
||||||
|
client.setEncoding(EncodingEnum.JSON);
|
||||||
|
client.registerInterceptor(new LoggingInterceptor(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void tearDownClass() throws Exception {
|
||||||
|
try {
|
||||||
|
jettyServer.destroy();
|
||||||
|
} catch (Exception e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package ca.uhn.fhir.jaxrs.server.test;
|
||||||
|
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import javax.ejb.Stateless;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.jaxrs.server.AbstractJaxRsConformanceProvider;
|
||||||
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
|
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A conformance provider exposes the mock patient and this provider
|
||||||
|
*/
|
||||||
|
@Path("")
|
||||||
|
@Stateless
|
||||||
|
@Produces({ MediaType.APPLICATION_JSON, Constants.CT_FHIR_JSON, Constants.CT_FHIR_XML })
|
||||||
|
public class TestJaxRsConformanceRestProviderDstu3 extends AbstractJaxRsConformanceProvider {
|
||||||
|
|
||||||
|
public TestJaxRsConformanceRestProviderDstu3() {
|
||||||
|
super(FhirContext.forDstu3(), "description", "name", "version");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider> getProviders() {
|
||||||
|
ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider> map = new ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider>();
|
||||||
|
map.put(TestJaxRsMockPatientRestProviderDstu3.class, new TestJaxRsMockPatientRestProviderDstu3());
|
||||||
|
map.put(TestJaxRsConformanceRestProviderDstu3.class, new TestJaxRsConformanceRestProviderDstu3());
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package ca.uhn.fhir.jaxrs.server.test;
|
||||||
|
|
||||||
|
import org.hl7.fhir.dstu3.model.Patient;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.jaxrs.server.AbstractJaxRsResourceProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A dummy patient provider exposing no methods
|
||||||
|
*/
|
||||||
|
public class TestJaxRsDummyPatientProviderDstu3 extends AbstractJaxRsResourceProvider<Patient> {
|
||||||
|
|
||||||
|
public TestJaxRsDummyPatientProviderDstu3() {
|
||||||
|
super(FhirContext.forDstu3());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<Patient> getResourceType() {
|
||||||
|
return Patient.class;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package ca.uhn.fhir.jaxrs.server.test;
|
||||||
|
|
||||||
|
import javax.ejb.Stateless;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.jaxrs.server.AbstractJaxRsPageProvider;
|
||||||
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
|
import ca.uhn.fhir.rest.server.IPagingProvider;
|
||||||
|
|
||||||
|
@Path("/")
|
||||||
|
@Stateless
|
||||||
|
@Produces({ MediaType.APPLICATION_JSON, Constants.CT_FHIR_JSON, Constants.CT_FHIR_XML })
|
||||||
|
public class TestJaxRsMockPageProviderDstu3 extends AbstractJaxRsPageProvider {
|
||||||
|
|
||||||
|
public TestJaxRsMockPageProviderDstu3() {
|
||||||
|
super(FhirContext.forDstu3());
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public IPagingProvider getPagingProvider() {
|
||||||
|
return TestJaxRsMockPatientRestProviderDstu3.PAGING_PROVIDER;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,141 @@
|
||||||
|
package ca.uhn.fhir.jaxrs.server.test;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
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 org.hl7.fhir.dstu3.model.IdType;
|
||||||
|
import org.hl7.fhir.dstu3.model.Parameters;
|
||||||
|
import org.hl7.fhir.dstu3.model.Patient;
|
||||||
|
import org.hl7.fhir.dstu3.model.StringType;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
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.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.StringAndListParam;
|
||||||
|
import ca.uhn.fhir.rest.param.StringParam;
|
||||||
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
|
import ca.uhn.fhir.rest.server.FifoMemoryPagingProvider;
|
||||||
|
import ca.uhn.fhir.rest.server.IPagingProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A test server delegating each call to a mock
|
||||||
|
*/
|
||||||
|
@Path(TestJaxRsMockPatientRestProviderDstu3.PATH)
|
||||||
|
@Stateless
|
||||||
|
@Produces({ MediaType.APPLICATION_JSON, Constants.CT_FHIR_JSON, Constants.CT_FHIR_XML })
|
||||||
|
@Interceptors(JaxRsExceptionInterceptor.class)
|
||||||
|
public class TestJaxRsMockPatientRestProviderDstu3 extends AbstractJaxRsResourceProvider<Patient> {
|
||||||
|
|
||||||
|
static final String PATH = "/Patient";
|
||||||
|
|
||||||
|
public static final TestJaxRsMockPatientRestProviderDstu3 mock = Mockito.mock(TestJaxRsMockPatientRestProviderDstu3.class);
|
||||||
|
|
||||||
|
public static final FifoMemoryPagingProvider PAGING_PROVIDER;
|
||||||
|
|
||||||
|
static
|
||||||
|
{
|
||||||
|
PAGING_PROVIDER = new FifoMemoryPagingProvider(10);
|
||||||
|
PAGING_PROVIDER.setDefaultPageSize(10);
|
||||||
|
PAGING_PROVIDER.setMaximumPageSize(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
public TestJaxRsMockPatientRestProviderDstu3() {
|
||||||
|
super(FhirContext.forDstu3());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Search
|
||||||
|
public List<Patient> search(@RequiredParam(name = Patient.SP_NAME) final StringParam name, @RequiredParam(name=Patient.SP_ADDRESS) StringAndListParam theAddressParts) {
|
||||||
|
return mock.search(name, theAddressParts);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Update
|
||||||
|
public MethodOutcome update(@IdParam final IdType theId, @ResourceParam final Patient patient) throws Exception {
|
||||||
|
return mock.update(theId, patient);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Read
|
||||||
|
public Patient find(@IdParam final IdType theId) {
|
||||||
|
return mock.find(theId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Read(version = true)
|
||||||
|
public Patient findHistory(@IdParam final IdType theId) {
|
||||||
|
return mock.findHistory(theId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Create
|
||||||
|
public MethodOutcome create(@ResourceParam final Patient patient, @ConditionalUrlParam String theConditional)
|
||||||
|
throws Exception {
|
||||||
|
return mock.create(patient, theConditional);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
public MethodOutcome delete(@IdParam final IdType theId) {
|
||||||
|
return mock.delete(theId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Search(compartmentName = "Condition")
|
||||||
|
public List<IBaseResource> searchCompartment(@IdParam IdType thePatientId) {
|
||||||
|
return mock.searchCompartment(thePatientId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/{id}/$someCustomOperation")
|
||||||
|
public Response someCustomOperationUsingGet(@PathParam("id") String id, String resource) throws Exception {
|
||||||
|
return customOperation(resource, RequestTypeEnum.GET, id, "$someCustomOperation",
|
||||||
|
RestOperationTypeEnum.EXTENDED_OPERATION_INSTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("/{id}/$someCustomOperation")
|
||||||
|
public Response someCustomOperationUsingPost(@PathParam("id") String id, String resource) throws Exception {
|
||||||
|
return customOperation(resource, RequestTypeEnum.POST, id, "$someCustomOperation",
|
||||||
|
RestOperationTypeEnum.EXTENDED_OPERATION_INSTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(name = "someCustomOperation", idempotent = true, returnParameters = {
|
||||||
|
@OperationParam(name = "return", type = StringType.class) })
|
||||||
|
public Parameters someCustomOperation(@IdParam IdType myId, @OperationParam(name = "dummy") StringType dummyInput) {
|
||||||
|
return mock.someCustomOperation(myId, dummyInput);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<Patient> getResourceType() {
|
||||||
|
return Patient.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IPagingProvider getPagingProvider() {
|
||||||
|
return PAGING_PROVIDER;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,129 @@
|
||||||
|
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.hl7.fhir.dstu3.model.IdType;
|
||||||
|
import org.hl7.fhir.dstu3.model.Parameters;
|
||||||
|
import org.hl7.fhir.dstu3.model.Patient;
|
||||||
|
import org.hl7.fhir.dstu3.model.StringType;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.FixMethodOrder;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runners.MethodSorters;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.jaxrs.server.test.TestJaxRsDummyPatientProviderDstu3;
|
||||||
|
import ca.uhn.fhir.jaxrs.server.util.JaxRsMethodBindings;
|
||||||
|
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;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.NotImplementedOperationException;
|
||||||
|
|
||||||
|
@FixMethodOrder(MethodSorters.DEFAULT)
|
||||||
|
public class JaxRsMethodBindingsDstu3Test {
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
JaxRsMethodBindings.getClassBindings().clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = NotImplementedOperationException.class)
|
||||||
|
public void testFindMethodsForProviderNotDefinedMappingMethods() {
|
||||||
|
new TestJaxRsDummyPatientProviderDstu3().getBindings().getBinding(RestOperationTypeEnum.UPDATE, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFindMethodsForProviderWithMethods() {
|
||||||
|
class TestFindPatientProvider extends TestJaxRsDummyPatientProviderDstu3 {
|
||||||
|
@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 TestJaxRsDummyPatientProviderDstu3 {
|
||||||
|
@Search
|
||||||
|
public List<Patient> search(@RequiredParam(name = Patient.SP_NAME) final StringParam name) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class TestUpdatePatientProvider extends TestJaxRsDummyPatientProviderDstu3 {
|
||||||
|
@Update
|
||||||
|
public MethodOutcome update(@IdParam final IdType 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 TestJaxRsDummyPatientProviderDstu3 {
|
||||||
|
@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 TestJaxRsDummyPatientProviderDstu3 {
|
||||||
|
@Search
|
||||||
|
public List<Patient> search(@RequiredParam(name = Patient.SP_NAME) final StringParam name) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
@Update
|
||||||
|
public MethodOutcome update(@IdParam final IdType theId, @ResourceParam final Patient patient) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
@Operation(name = "firstMethod", idempotent = true, returnParameters = { @OperationParam(name = "return", type = StringType.class) })
|
||||||
|
public Parameters firstMethod(@OperationParam(name = "dummy") StringType dummyInput) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
@Operation(name = "secondMethod", returnParameters = { @OperationParam(name = "return", type = StringType.class) })
|
||||||
|
public Parameters secondMethod(@OperationParam(name = "dummy") StringType dummyInput) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
JaxRsMethodBindings 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(NotImplementedOperationException e){
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,119 @@
|
||||||
|
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.glassfish.jersey.internal.MapPropertiesDelegate;
|
||||||
|
import org.glassfish.jersey.server.ContainerRequest;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.jaxrs.server.test.TestJaxRsDummyPatientProvider;
|
||||||
|
import ca.uhn.fhir.jaxrs.server.test.TestJaxRsDummyPatientProviderDstu3;
|
||||||
|
import ca.uhn.fhir.jaxrs.server.util.JaxRsRequest;
|
||||||
|
import ca.uhn.fhir.jaxrs.server.util.JaxRsResponse;
|
||||||
|
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||||
|
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||||
|
|
||||||
|
public class JaxRsRequestDstu3Test {
|
||||||
|
|
||||||
|
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 TestJaxRsDummyPatientProviderDstu3 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(JaxRsRequestDstu3Test.BASEURI, details.getFhirServerBase());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetServer() {
|
||||||
|
assertEquals(this.provider, details.getServer());
|
||||||
|
}
|
||||||
|
|
||||||
|
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(TestJaxRsDummyPatientProviderDstu3.class);
|
||||||
|
doReturn(uriInfo).when(provider).getUriInfo();
|
||||||
|
doReturn(BASEURI).when(provider).getBaseForRequest();
|
||||||
|
doReturn(BASEURI).when(provider).getBaseForServer();
|
||||||
|
doReturn(headers).when(provider).getHeaders();
|
||||||
|
|
||||||
|
return new JaxRsRequest(provider, RESOURCE_STRING, RequestTypeEnum.GET, RestOperationTypeEnum.HISTORY_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,159 @@
|
||||||
|
package ca.uhn.fhir.jaxrs.server.util;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
|
import org.hl7.fhir.dstu3.model.Binary;
|
||||||
|
import org.hl7.fhir.dstu3.model.Bundle;
|
||||||
|
import org.hl7.fhir.dstu3.model.IdType;
|
||||||
|
import org.hl7.fhir.dstu3.model.Patient;
|
||||||
|
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.jaxrs.server.util.JaxRsRequest;
|
||||||
|
import ca.uhn.fhir.jaxrs.server.util.JaxRsResponse;
|
||||||
|
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 JaxRsResponseDstu3Test {
|
||||||
|
|
||||||
|
private JaxRsResponse response;
|
||||||
|
private JaxRsRequest request;
|
||||||
|
private Bundle bundle;
|
||||||
|
private Set<SummaryEnum> theSummaryMode;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws URISyntaxException {
|
||||||
|
request = new JaxRsRequestDstu3Test().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();
|
||||||
|
boolean theAddContentLocationHeader = false;
|
||||||
|
Response result = (Response) RestfulServerUtils.streamResponseAsResource(request.getServer(), bundle, theSummaryMode, 200, theAddContentLocationHeader, respondGzip, request);
|
||||||
|
assertEquals(200, result.getStatus());
|
||||||
|
assertEquals(Constants.CT_FHIR_JSON+Constants.CHARSET_UTF8_CTSUFFIX, result.getHeaderString(Constants.HEADER_CONTENT_TYPE));
|
||||||
|
assertTrue(result.getEntity().toString().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, theSummaryMode, 200, 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, theSummaryMode, 200, 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, theSummaryMode, 200, 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 {
|
||||||
|
IdType theId = new IdType(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+Constants.CHARSET_UTF8_CTSUFFIX, 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 {
|
||||||
|
IdType theId = new IdType(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+Constants.CHARSET_UTF8_CTSUFFIX, 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+Constants.CHARSET_UTF8_CTSUFFIX, result.getHeaderString(Constants.HEADER_CONTENT_TYPE));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Bundle getSinglePatientResource() {
|
||||||
|
Patient theResource = createPatient();
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
bundle.addEntry().setResource(theResource);
|
||||||
|
return bundle;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Patient createPatient() {
|
||||||
|
Patient theResource = new Patient();
|
||||||
|
theResource.setId(new IdType(15L));
|
||||||
|
return theResource;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
package ca.uhn.fhir.jaxrs.server.example;
|
||||||
|
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import javax.ejb.Stateless;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.jaxrs.server.AbstractJaxRsConformanceProvider;
|
||||||
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
|
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Conformance Rest Service
|
||||||
|
*
|
||||||
|
* @author Peter Van Houte | peter.vanhoute@agfa.com | Agfa Healthcare
|
||||||
|
*/
|
||||||
|
@Path("")
|
||||||
|
@Stateless
|
||||||
|
@Produces({ MediaType.APPLICATION_JSON, Constants.CT_FHIR_JSON, Constants.CT_FHIR_XML })
|
||||||
|
public class JaxRsConformanceProviderDstu3 extends AbstractJaxRsConformanceProvider {
|
||||||
|
private static final String SERVER_VERSION = "1.0.0";
|
||||||
|
private static final String SERVER_DESCRIPTION = "Jax-Rs Test Example Description";
|
||||||
|
private static final String SERVER_NAME = "Jax-Rs Test Example";
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private JaxRsPatientRestProvider patientProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Standard Constructor
|
||||||
|
*/
|
||||||
|
public JaxRsConformanceProviderDstu3() {
|
||||||
|
super(FhirContext.forDstu3(), SERVER_VERSION, SERVER_DESCRIPTION, SERVER_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider> getProviders() {
|
||||||
|
ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider> map = new ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider>();
|
||||||
|
map.put(JaxRsConformanceProviderDstu3.class, this);
|
||||||
|
map.put(JaxRsPatientRestProvider.class, patientProvider);
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package ca.uhn.fhir.jaxrs.server.example;
|
||||||
|
|
||||||
|
import javax.ejb.Stateless;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.jaxrs.server.AbstractJaxRsPageProvider;
|
||||||
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
|
import ca.uhn.fhir.rest.server.IPagingProvider;
|
||||||
|
|
||||||
|
@Path("/")
|
||||||
|
@Stateless
|
||||||
|
@Produces({ MediaType.APPLICATION_JSON, Constants.CT_FHIR_JSON, Constants.CT_FHIR_XML })
|
||||||
|
public class JaxRsPageProviderDstu3 extends AbstractJaxRsPageProvider {
|
||||||
|
|
||||||
|
public JaxRsPageProviderDstu3() {
|
||||||
|
super(FhirContext.forDstu3());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IPagingProvider getPagingProvider() {
|
||||||
|
return JaxRsPatientRestProviderDstu3.PAGE_PROVIDER;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,258 @@
|
||||||
|
package ca.uhn.fhir.jaxrs.server.example;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import javax.ejb.Local;
|
||||||
|
import javax.ejb.Stateless;
|
||||||
|
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 org.hl7.fhir.dstu3.model.Condition;
|
||||||
|
import org.hl7.fhir.dstu3.model.HumanName;
|
||||||
|
import org.hl7.fhir.dstu3.model.IdType;
|
||||||
|
import org.hl7.fhir.dstu3.model.Parameters;
|
||||||
|
import org.hl7.fhir.dstu3.model.Patient;
|
||||||
|
import org.hl7.fhir.dstu3.model.StringType;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.jaxrs.server.AbstractJaxRsResourceProvider;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A demo JaxRs Patient Rest Provider
|
||||||
|
*
|
||||||
|
* @author Peter Van Houte | peter.vanhoute@agfa.com | Agfa Healthcare
|
||||||
|
*/
|
||||||
|
@Local
|
||||||
|
@Path(JaxRsPatientRestProviderDstu3.PATH)
|
||||||
|
@Stateless
|
||||||
|
@Produces({ MediaType.APPLICATION_JSON, Constants.CT_FHIR_JSON, Constants.CT_FHIR_XML })
|
||||||
|
public class JaxRsPatientRestProviderDstu3 extends AbstractJaxRsResourceProvider<Patient> {
|
||||||
|
|
||||||
|
private static Long counter = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The HAPI paging provider for this server
|
||||||
|
*/
|
||||||
|
public static final IPagingProvider PAGE_PROVIDER;
|
||||||
|
|
||||||
|
static final String PATH = "/Patient";
|
||||||
|
private static final ConcurrentHashMap<String, List<Patient>> patients = new ConcurrentHashMap<String, List<Patient>>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
PAGE_PROVIDER = new FifoMemoryPagingProvider(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
patients.put(String.valueOf(counter), createPatient("Van Houte"));
|
||||||
|
patients.put(String.valueOf(counter), createPatient("Agnew"));
|
||||||
|
for (int i = 0; i < 20; i++) {
|
||||||
|
patients.put(String.valueOf(counter), createPatient("Random Patient " + counter));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public JaxRsPatientRestProviderDstu3() {
|
||||||
|
super(FhirContext.forDstu3(), JaxRsPatientRestProviderDstu3.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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(new IdType(patient.getId()));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
public MethodOutcome delete(@IdParam final IdType theId) {
|
||||||
|
final Patient deletedPatient = find(theId);
|
||||||
|
patients.remove(deletedPatient.getIdElement().getIdPart());
|
||||||
|
final MethodOutcome result = new MethodOutcome().setCreated(true);
|
||||||
|
result.setResource(deletedPatient);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Read
|
||||||
|
public Patient find(@IdParam final IdType theId) {
|
||||||
|
if (patients.containsKey(theId.getIdPart())) {
|
||||||
|
return getLast(patients.get(theId.getIdPart()));
|
||||||
|
} else {
|
||||||
|
throw new ResourceNotFoundException(theId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Read(version = true)
|
||||||
|
public Patient findHistory(@IdParam final IdType theId) {
|
||||||
|
if (patients.containsKey(theId.getIdPart())) {
|
||||||
|
final List<Patient> list = patients.get(theId.getIdPart());
|
||||||
|
for (final Patient patient : list) {
|
||||||
|
if (patient.getIdElement().getVersionIdPartAsLong().equals(theId.getVersionIdPartAsLong())) {
|
||||||
|
return patient;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new ResourceNotFoundException(theId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(name = "firstVersion", idempotent = true, returnParameters = { @OperationParam(name = "return", type = StringType.class) })
|
||||||
|
public Parameters firstVersion(@IdParam final IdType theId, @OperationParam(name = "dummy") StringType dummyInput) {
|
||||||
|
Parameters parameters = new Parameters();
|
||||||
|
Patient patient = find(new IdType(theId.getResourceType(), theId.getIdPart(), "0"));
|
||||||
|
parameters.addParameter().setName("return").setResource(patient).setValue(new StringType((counter - 1) + "" + "inputVariable [ " + dummyInput.getValue() + "]"));
|
||||||
|
return parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AddProfileTagEnum getAddProfileTag() {
|
||||||
|
return AddProfileTagEnum.NEVER;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BundleInclusionRule getBundleInclusionRule() {
|
||||||
|
return BundleInclusionRule.BASED_ON_INCLUDES;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ETagSupportEnum getETagSupport() {
|
||||||
|
return ETagSupportEnum.DISABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** THE DEFAULTS */
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<IServerInterceptor> getInterceptors() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Patient getLast(final List<Patient> list) {
|
||||||
|
return list.get(list.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IPagingProvider getPagingProvider() {
|
||||||
|
return PAGE_PROVIDER;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<Patient> getResourceType() {
|
||||||
|
return Patient.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDefaultPrettyPrint() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isUseBrowserFriendlyContentTypes() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/{id}/$firstVersion")
|
||||||
|
public Response operationFirstVersionUsingGet(@PathParam("id") String id) throws IOException {
|
||||||
|
return customOperation(null, RequestTypeEnum.GET, id, "$firstVersion", RestOperationTypeEnum.EXTENDED_OPERATION_INSTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("/{id}/$firstVersion")
|
||||||
|
public Response operationFirstVersionUsingGet(@PathParam("id") String id, final String resource) throws Exception {
|
||||||
|
return customOperation(resource, RequestTypeEnum.POST, id, "$firstVersion", RestOperationTypeEnum.EXTENDED_OPERATION_INSTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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.getName().get(0).getFamily().get(0).getValueNotNull().equals(name.getValueNotNull())) {
|
||||||
|
single = patient;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (single != null) {
|
||||||
|
result.add(single);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Search(compartmentName = "Condition")
|
||||||
|
public List<IBaseResource> searchCompartment(@IdParam IdType thePatientId) {
|
||||||
|
List<IBaseResource> retVal = new ArrayList<IBaseResource>();
|
||||||
|
Condition condition = new Condition();
|
||||||
|
condition.setId(new IdType("665577"));
|
||||||
|
retVal.add(condition);
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Update
|
||||||
|
public MethodOutcome update(@IdParam final IdType theId, @ResourceParam final Patient patient) {
|
||||||
|
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.getIdElement().getVersionIdPartAsLong() + 1));
|
||||||
|
patientList.add(patient);
|
||||||
|
final MethodOutcome result = new MethodOutcome().setCreated(false);
|
||||||
|
result.setResource(patient);
|
||||||
|
result.setId(new IdType(patient.getId()));
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
throw new ResourceNotFoundException(theId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IdType createId(final Long id, final Long theVersionId) {
|
||||||
|
return new IdType("Patient", "" + id, "" + theVersionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 List<Patient> createPatient(final String name) {
|
||||||
|
final Patient patient = new Patient();
|
||||||
|
patient.getName().add(new HumanName().addFamily(name));
|
||||||
|
return createPatient(patient);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,315 @@
|
||||||
|
package ca.uhn.fhir.jaxrs.server.example;
|
||||||
|
|
||||||
|
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.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.eclipse.jetty.server.Server;
|
||||||
|
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||||
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
|
import org.hl7.fhir.dstu3.model.Bundle;
|
||||||
|
import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
|
||||||
|
import org.hl7.fhir.dstu3.model.Conformance;
|
||||||
|
import org.hl7.fhir.dstu3.model.DateType;
|
||||||
|
import org.hl7.fhir.dstu3.model.HumanName;
|
||||||
|
import org.hl7.fhir.dstu3.model.IdType;
|
||||||
|
import org.hl7.fhir.dstu3.model.Parameters;
|
||||||
|
import org.hl7.fhir.dstu3.model.Patient;
|
||||||
|
import org.hl7.fhir.dstu3.model.StringType;
|
||||||
|
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.client.JaxRsRestfulClientFactory;
|
||||||
|
import ca.uhn.fhir.model.api.BundleEntry;
|
||||||
|
import ca.uhn.fhir.model.primitive.BoundCodeDt;
|
||||||
|
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 JaxRsPatientProviderDstu3Test {
|
||||||
|
|
||||||
|
private static IGenericClient client;
|
||||||
|
private static final FhirContext ourCtx = FhirContext.forDstu3();
|
||||||
|
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);
|
||||||
|
//@formatter:off
|
||||||
|
jerseyServlet.setInitParameter("jersey.config.server.provider.classnames",
|
||||||
|
StringUtils.join(Arrays.asList(
|
||||||
|
JaxRsConformanceProviderDstu3.class.getCanonicalName(),
|
||||||
|
JaxRsPatientRestProviderDstu3.class.getCanonicalName(),
|
||||||
|
JaxRsPageProviderDstu3.class.getCanonicalName()
|
||||||
|
), ";"));
|
||||||
|
//@formatter:on
|
||||||
|
jettyServer.start();
|
||||||
|
|
||||||
|
ourCtx.setRestfulClientFactory(new JaxRsRestfulClientFactory(ourCtx));
|
||||||
|
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 Bundle results = client.search().forResource(Patient.class)
|
||||||
|
.where(Patient.NAME.matchesExactly().value(PATIENT_NAME)).returnBundle(Bundle.class).execute();
|
||||||
|
System.out.println(results.getEntry().get(0));
|
||||||
|
assertEquals(results.getEntry().size(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Search - Multi-valued Parameters (ANY/OR) */
|
||||||
|
@Test
|
||||||
|
public void findUsingGenericClientBySearchWithMultiValues() {
|
||||||
|
final 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")).returnBundle(Bundle.class).execute();
|
||||||
|
System.out.println(response.getEntry().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(Bundle.class)
|
||||||
|
.execute();
|
||||||
|
assertTrue(response.getEntry().size() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Search - Subsetting (_summary and _elements) */
|
||||||
|
@Test
|
||||||
|
@Ignore
|
||||||
|
public void testSummary() {
|
||||||
|
client.search()
|
||||||
|
.forResource(Patient.class)
|
||||||
|
.returnBundle(Bundle.class)
|
||||||
|
.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreatePatient() {
|
||||||
|
final Patient existing = new Patient();
|
||||||
|
existing.setId((IdType) null);
|
||||||
|
existing.getName().add(new HumanName().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.class, patient.getId()));
|
||||||
|
client.setEncoding(EncodingEnum.JSON);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Conditional Creates */
|
||||||
|
@Test
|
||||||
|
public void testConditionalCreate() {
|
||||||
|
final Patient existing = new Patient();
|
||||||
|
existing.setId((IdType) null);
|
||||||
|
existing.getName().add(new HumanName().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.getId()))
|
||||||
|
.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Find By Id */
|
||||||
|
@Test
|
||||||
|
public void findUsingGenericClientById() {
|
||||||
|
final Patient results = client.read(Patient.class, "1");
|
||||||
|
assertEquals(results.getIdElement().getIdPartAsLong().longValue(), 1L);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUpdateById() {
|
||||||
|
final Patient existing = client.read(Patient.class, "1");
|
||||||
|
final List<HumanName> name = existing.getName();
|
||||||
|
name.get(0).addSuffix("The Second");
|
||||||
|
existing.getName().addAll(name);
|
||||||
|
client.setEncoding(EncodingEnum.XML);
|
||||||
|
final MethodOutcome results = client.update("1", existing);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDeletePatient() {
|
||||||
|
final Patient existing = new Patient();
|
||||||
|
existing.getName().add(new HumanName().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.class, patient.getId());
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
catch (final Exception e) {
|
||||||
|
//assertEquals(e.getStatusCode(), Constants.STATUS_HTTP_404_NOT_FOUND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Transaction - Server */
|
||||||
|
@Ignore
|
||||||
|
@Test
|
||||||
|
public void testTransaction() {
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
BundleEntryComponent entry = bundle.addEntry();
|
||||||
|
final Patient existing = new Patient();
|
||||||
|
existing.getName().get(0).addFamily("Created with bundle");
|
||||||
|
entry.setResource(existing);
|
||||||
|
|
||||||
|
// FIXME ?
|
||||||
|
// BoundCodeDt<BundleEntryTransactionMethodEnum> theTransactionOperation =
|
||||||
|
// new BoundCodeDt(
|
||||||
|
// BundleEntryTransactionMethodEnum.VALUESET_BINDER,
|
||||||
|
// BundleEntryTransactionMethodEnum.POST);
|
||||||
|
// entry.setTransactionMethod(theTransactionOperation);
|
||||||
|
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 DateType("2001-01-01"));
|
||||||
|
inParams.addParameter().setName("end").setValue(new DateType("2015-03-01"));
|
||||||
|
inParams.addParameter().setName("dummy").setValue(new StringType("myAwesomeDummyValue"));
|
||||||
|
|
||||||
|
// Invoke $everything on "Patient/1"
|
||||||
|
Parameters outParams = client
|
||||||
|
.operation()
|
||||||
|
.onInstance(new IdType("Patient", "1"))
|
||||||
|
.named("$firstVersion")
|
||||||
|
.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() {
|
||||||
|
// Create the input parameters to pass to the server
|
||||||
|
Parameters inParams = new Parameters();
|
||||||
|
inParams.addParameter().setName("start").setValue(new DateType("2001-01-01"));
|
||||||
|
inParams.addParameter().setName("end").setValue(new DateType("2015-03-01"));
|
||||||
|
inParams.addParameter().setName("dummy").setValue(new StringType("myAwesomeDummyValue"));
|
||||||
|
|
||||||
|
// Invoke $everything on "Patient/1"
|
||||||
|
Parameters outParams = client
|
||||||
|
.operation()
|
||||||
|
.onInstance(new IdType("Patient", "1"))
|
||||||
|
.named("$firstVersion")
|
||||||
|
.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 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue