Client security working
This commit is contained in:
parent
0b93dcc491
commit
018e780343
|
@ -0,0 +1,44 @@
|
|||
package ca.uhn.fhir.rest.client;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.http.HttpException;
|
||||
import org.apache.http.HttpRequest;
|
||||
import org.apache.http.HttpRequestInterceptor;
|
||||
import org.apache.http.auth.AuthState;
|
||||
import org.apache.http.auth.Credentials;
|
||||
import org.apache.http.auth.UsernamePasswordCredentials;
|
||||
import org.apache.http.client.protocol.HttpClientContext;
|
||||
import org.apache.http.impl.auth.BasicScheme;
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
|
||||
/**
|
||||
* HTTP interceptor to be used for adding HTTP basic auth username/password tokens
|
||||
* to requests
|
||||
* <p>
|
||||
* See the
|
||||
* </p>
|
||||
*/
|
||||
public class HttpBasicAuthInterceptor implements HttpRequestInterceptor {
|
||||
|
||||
private String myUsername;
|
||||
private String myPassword;
|
||||
|
||||
public HttpBasicAuthInterceptor(String theUsername, String thePassword) {
|
||||
super();
|
||||
myUsername = theUsername;
|
||||
myPassword = thePassword;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException {
|
||||
AuthState authState = (AuthState) context.getAttribute(HttpClientContext.TARGET_AUTH_STATE);
|
||||
|
||||
if (authState.getAuthScheme() == null) {
|
||||
Credentials creds = new UsernamePasswordCredentials(myUsername, myPassword);
|
||||
authState.update(new BasicScheme(), creds);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -69,7 +69,7 @@ public abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends
|
|||
if (param == null) {
|
||||
continue;
|
||||
}
|
||||
params[i] = param.translateQueryParametersIntoServerArgument(theRequest.getParameters(), resource);
|
||||
params[i] = param.translateQueryParametersIntoServerArgument(theRequest, resource);
|
||||
}
|
||||
|
||||
addParametersForServerRequest(theRequest, params);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package ca.uhn.fhir.rest.method;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
|
@ -130,7 +130,7 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
|
|||
throw new IllegalStateException("Should not get here!");
|
||||
}
|
||||
|
||||
public abstract List<IResource> invokeServer(Object theResourceProvider, IdDt theId, IdDt theVersionId, Map<String, String[]> theParameterValues) throws InvalidRequestException, InternalErrorException;
|
||||
public abstract List<IResource> invokeServer(Object theResourceProvider, Request theRequest) throws InvalidRequestException, InternalErrorException;
|
||||
|
||||
@Override
|
||||
public void invokeServer(RestfulServer theServer, Request theRequest, HttpServletResponse theResponse) throws BaseServerResponseException, IOException {
|
||||
|
@ -165,7 +165,7 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
|
|||
requestIsBrowser = true;
|
||||
}
|
||||
|
||||
List<IResource> result = invokeServer(getProvider(), theRequest.getId(), theRequest.getVersion(), theRequest.getParameters());
|
||||
List<IResource> result = invokeServer(getProvider(), theRequest);
|
||||
switch (getReturnType()) {
|
||||
case BUNDLE:
|
||||
streamResponseAsBundle(theServer, theResponse, result, responseEncoding, theRequest.getFhirServerBase(), theRequest.getCompleteUrl(), prettyPrint, requestIsBrowser, narrativeMode);
|
||||
|
|
|
@ -3,7 +3,6 @@ package ca.uhn.fhir.rest.method;
|
|||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
|
@ -11,7 +10,6 @@ import ca.uhn.fhir.model.api.IResource;
|
|||
import ca.uhn.fhir.model.dstu.resource.Conformance;
|
||||
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationSystemEnum;
|
||||
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationTypeEnum;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.client.GetClientInvocation;
|
||||
import ca.uhn.fhir.rest.method.SearchMethodBinding.RequestType;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
|
@ -39,7 +37,7 @@ public class ConformanceMethodBinding extends BaseResourceReturningMethodBinding
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<IResource> invokeServer(Object theResourceProvider, IdDt theId, IdDt theVersionId, Map<String, String[]> theParameterValues) throws InvalidRequestException,
|
||||
public List<IResource> invokeServer(Object theResourceProvider, Request theRequest) throws InvalidRequestException,
|
||||
InternalErrorException {
|
||||
IResource conf;
|
||||
try {
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
package ca.uhn.fhir.rest.method;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
@ -151,10 +150,10 @@ public class HistoryMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<IResource> invokeServer(Object theResourceProvider, IdDt theId, IdDt theVersionId, Map<String, String[]> theParameterValues) throws InvalidRequestException, InternalErrorException {
|
||||
public List<IResource> invokeServer(Object theResourceProvider, Request theRequest) throws InvalidRequestException, InternalErrorException {
|
||||
Object[] args = new Object[getMethod().getParameterTypes().length];
|
||||
if (myCountParamIndex != null) {
|
||||
String[] countValues = theParameterValues.remove(Constants.PARAM_COUNT);
|
||||
String[] countValues = theRequest.getParameters().remove(Constants.PARAM_COUNT);
|
||||
if (countValues.length > 0 && StringUtils.isNotBlank(countValues[0])) {
|
||||
try {
|
||||
args[myCountParamIndex] = new IntegerDt(countValues[0]);
|
||||
|
@ -164,7 +163,7 @@ public class HistoryMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
}
|
||||
}
|
||||
if (mySinceParamIndex != null) {
|
||||
String[] sinceValues = theParameterValues.remove(Constants.PARAM_SINCE);
|
||||
String[] sinceValues = theRequest.getParameters().remove(Constants.PARAM_SINCE);
|
||||
if (sinceValues.length > 0 && StringUtils.isNotBlank(sinceValues[0])) {
|
||||
try {
|
||||
args[mySinceParamIndex] = new InstantDt(sinceValues[0]);
|
||||
|
@ -175,7 +174,7 @@ public class HistoryMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
}
|
||||
|
||||
if (myIdParamIndex!=null) {
|
||||
args[myIdParamIndex] = theId;
|
||||
args[myIdParamIndex] = theRequest.getId();
|
||||
}
|
||||
|
||||
Object response;
|
||||
|
|
|
@ -2,7 +2,6 @@ package ca.uhn.fhir.rest.method;
|
|||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
@ -88,11 +87,11 @@ public class ReadMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<IResource> invokeServer(Object theResourceProvider, IdDt theId, IdDt theVersionId, Map<String, String[]> theParameterValues) throws InvalidRequestException, InternalErrorException {
|
||||
public List<IResource> invokeServer(Object theResourceProvider,Request theRequest) throws InvalidRequestException, InternalErrorException {
|
||||
Object[] params = new Object[myParameterCount];
|
||||
params[myIdIndex] = theId;
|
||||
params[myIdIndex] = theRequest.getId();
|
||||
if (myVersionIdIndex != null) {
|
||||
params[myVersionIdIndex] = theVersionId;
|
||||
params[myVersionIdIndex] = theRequest.getId();
|
||||
}
|
||||
|
||||
Object response;
|
||||
|
|
|
@ -15,10 +15,9 @@ import ca.uhn.fhir.context.FhirContext;
|
|||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationSystemEnum;
|
||||
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationTypeEnum;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.client.GetClientInvocation;
|
||||
import ca.uhn.fhir.rest.param.IParameter;
|
||||
import ca.uhn.fhir.rest.param.IQueryParameter;
|
||||
import ca.uhn.fhir.rest.param.BaseQueryParameter;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
|
@ -85,20 +84,21 @@ public class SearchMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<IResource> invokeServer(Object theResourceProvider, IdDt theId, IdDt theVersionId, Map<String, String[]> parameterValues) throws InvalidRequestException,
|
||||
public List<IResource> invokeServer(Object theResourceProvider, Request theRequest) throws InvalidRequestException,
|
||||
InternalErrorException {
|
||||
assert theId == null;
|
||||
assert theVersionId == null;
|
||||
assert theRequest.getId() == null;
|
||||
assert theRequest.getVersion() == null;
|
||||
|
||||
Object[] params = new Object[myParameters.size()];
|
||||
for (int i = 0; i < myParameters.size(); i++) {
|
||||
IParameter param = myParameters.get(i);
|
||||
params[i] = param.translateQueryParametersIntoServerArgument(parameterValues, null);
|
||||
params[i] = param.translateQueryParametersIntoServerArgument(theRequest, null);
|
||||
}
|
||||
|
||||
Object response;
|
||||
try {
|
||||
response = this.getMethod().invoke(theResourceProvider, params);
|
||||
Method method = this.getMethod();
|
||||
response = method.invoke(theResourceProvider, params);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new InternalErrorException(e);
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
@ -140,10 +140,10 @@ public class SearchMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
|
||||
Set<String> methodParamsTemp = new HashSet<String>();
|
||||
for (int i = 0; i < this.myParameters.size(); i++) {
|
||||
if (!(myParameters.get(i) instanceof IQueryParameter)) {
|
||||
if (!(myParameters.get(i) instanceof BaseQueryParameter)) {
|
||||
continue;
|
||||
}
|
||||
IQueryParameter temp = (IQueryParameter) myParameters.get(i);
|
||||
BaseQueryParameter temp = (BaseQueryParameter) myParameters.get(i);
|
||||
methodParamsTemp.add(temp.getName());
|
||||
if (temp.isRequired() && !theRequest.getParameters().containsKey(temp.getName())) {
|
||||
ourLog.trace("Method {} doesn't match param '{}' is not present", getMethod().getName(), temp.getName());
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
package ca.uhn.fhir.rest.method;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import ca.uhn.fhir.rest.param.IParameter;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
class ServletRequestParameter implements IParameter {
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ServletRequestParameter.class);
|
||||
|
||||
@Override
|
||||
public void translateClientArgumentIntoQueryArgument(Object theSourceClientArgument, Map<String, List<String>> theTargetQueryArguments) throws InternalErrorException {
|
||||
/*
|
||||
* Does nothing, since we just ignore HttpServletRequest arguments
|
||||
*/
|
||||
ourLog.trace("Ignoring HttpServletRequest argument: {}", theSourceClientArgument);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, Object theRequestContents) throws InternalErrorException, InvalidRequestException {
|
||||
return theRequest.getServletRequest();
|
||||
}
|
||||
|
||||
}
|
|
@ -24,7 +24,7 @@ import ca.uhn.fhir.rest.server.Constants;
|
|||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
public class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithResourceParam {
|
||||
class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithResourceParam {
|
||||
|
||||
private Integer myIdParameterIndex;
|
||||
|
||||
|
|
|
@ -10,6 +10,9 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.PathSpecification;
|
||||
|
@ -88,66 +91,73 @@ class Util {
|
|||
int paramIndex = 0;
|
||||
for (Annotation[] annotations : method.getParameterAnnotations()) {
|
||||
boolean haveHandledMethod = false;
|
||||
for (int i = 0; i < annotations.length; i++) {
|
||||
Annotation nextAnnotation = annotations[i];
|
||||
Class<?> parameterType = parameterTypes[paramIndex];
|
||||
|
||||
Class<? extends java.util.Collection<?>> outerCollectionType = null;
|
||||
Class<? extends java.util.Collection<?>> innerCollectionType = null;
|
||||
|
||||
if (Collection.class.isAssignableFrom(parameterType)) {
|
||||
innerCollectionType = (Class<? extends java.util.Collection<?>>) parameterType;
|
||||
parameterType = ReflectionUtil.getGenericCollectionTypeOfMethodParameter(method, paramIndex);
|
||||
}
|
||||
|
||||
if (Collection.class.isAssignableFrom(parameterType)) {
|
||||
outerCollectionType = innerCollectionType;
|
||||
innerCollectionType = (Class<? extends java.util.Collection<?>>) parameterType;
|
||||
parameterType = ReflectionUtil.getGenericCollectionTypeOfMethodParameter(method, paramIndex);
|
||||
}
|
||||
|
||||
IParameter param;
|
||||
if (nextAnnotation instanceof RequiredParam) {
|
||||
SearchParameter parameter = new SearchParameter();
|
||||
parameter.setName(((RequiredParam) nextAnnotation).name());
|
||||
parameter.setRequired(true);
|
||||
parameter.setType(parameterType, innerCollectionType, outerCollectionType);
|
||||
param = parameter;
|
||||
} else if (nextAnnotation instanceof OptionalParam) {
|
||||
SearchParameter parameter = new SearchParameter();
|
||||
parameter.setName(((OptionalParam) nextAnnotation).name());
|
||||
parameter.setRequired(false);
|
||||
parameter.setType(parameterType, innerCollectionType, innerCollectionType);
|
||||
param = parameter;
|
||||
} else if (nextAnnotation instanceof IncludeParam) {
|
||||
if (parameterType != PathSpecification.class || innerCollectionType == null || outerCollectionType != null) {
|
||||
throw new ConfigurationException("Method '" + method.getName() + "' is annotated with @" + IncludeParam.class.getSimpleName() + " but has a type other than Collection<"
|
||||
+ PathSpecification.class.getSimpleName() + ">");
|
||||
}
|
||||
Class<? extends Collection<PathSpecification>> instantiableCollectionType = (Class<? extends Collection<PathSpecification>>) CollectionBinder.getInstantiableCollectionType(
|
||||
innerCollectionType, "Method '" + method.getName() + "'");
|
||||
|
||||
param = new IncludeParameter((IncludeParam) nextAnnotation, instantiableCollectionType);
|
||||
} else if (nextAnnotation instanceof ResourceParam) {
|
||||
if (!IResource.class.isAssignableFrom(parameterType)) {
|
||||
throw new ConfigurationException("Method '" + method.getName() + "' is annotated with @" + ResourceParam.class.getSimpleName()
|
||||
+ " but has a type that is not an implemtation of " + IResource.class.getCanonicalName());
|
||||
}
|
||||
param = new ResourceParameter((Class<? extends IResource>) parameterType);
|
||||
} else if (nextAnnotation instanceof IdParam || nextAnnotation instanceof VersionIdParam) {
|
||||
param = null;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
haveHandledMethod = true;
|
||||
Class<?> parameterType = parameterTypes[paramIndex];
|
||||
if (parameterType.equals(HttpServletRequest.class) || parameterType.equals(ServletRequest.class)) {
|
||||
ServletRequestParameter param = new ServletRequestParameter();
|
||||
parameters.add(param);
|
||||
} else {
|
||||
for (int i = 0; i < annotations.length; i++) {
|
||||
Annotation nextAnnotation = annotations[i];
|
||||
|
||||
}
|
||||
Class<? extends java.util.Collection<?>> outerCollectionType = null;
|
||||
Class<? extends java.util.Collection<?>> innerCollectionType = null;
|
||||
|
||||
if (!haveHandledMethod) {
|
||||
throw new ConfigurationException("Parameter #" + paramIndex + " of method '" + method.getName() + "' on type '" + method.getDeclaringClass().getCanonicalName()
|
||||
+ "' has no recognized FHIR interface parameter annotations. Don't know how to handle this parameter");
|
||||
if (Collection.class.isAssignableFrom(parameterType)) {
|
||||
innerCollectionType = (Class<? extends java.util.Collection<?>>) parameterType;
|
||||
parameterType = ReflectionUtil.getGenericCollectionTypeOfMethodParameter(method, paramIndex);
|
||||
}
|
||||
|
||||
if (Collection.class.isAssignableFrom(parameterType)) {
|
||||
outerCollectionType = innerCollectionType;
|
||||
innerCollectionType = (Class<? extends java.util.Collection<?>>) parameterType;
|
||||
parameterType = ReflectionUtil.getGenericCollectionTypeOfMethodParameter(method, paramIndex);
|
||||
}
|
||||
|
||||
IParameter param;
|
||||
if (nextAnnotation instanceof RequiredParam) {
|
||||
SearchParameter parameter = new SearchParameter();
|
||||
parameter.setName(((RequiredParam) nextAnnotation).name());
|
||||
parameter.setRequired(true);
|
||||
parameter.setType(parameterType, innerCollectionType, outerCollectionType);
|
||||
param = parameter;
|
||||
} else if (nextAnnotation instanceof OptionalParam) {
|
||||
SearchParameter parameter = new SearchParameter();
|
||||
parameter.setName(((OptionalParam) nextAnnotation).name());
|
||||
parameter.setRequired(false);
|
||||
parameter.setType(parameterType, innerCollectionType, outerCollectionType);
|
||||
param = parameter;
|
||||
} else if (nextAnnotation instanceof IncludeParam) {
|
||||
if (parameterType != PathSpecification.class || innerCollectionType == null || outerCollectionType != null) {
|
||||
throw new ConfigurationException("Method '" + method.getName() + "' is annotated with @" + IncludeParam.class.getSimpleName() + " but has a type other than Collection<"
|
||||
+ PathSpecification.class.getSimpleName() + ">");
|
||||
}
|
||||
Class<? extends Collection<PathSpecification>> instantiableCollectionType = (Class<? extends Collection<PathSpecification>>) CollectionBinder.getInstantiableCollectionType(
|
||||
innerCollectionType, "Method '" + method.getName() + "'");
|
||||
|
||||
param = new IncludeParameter((IncludeParam) nextAnnotation, instantiableCollectionType);
|
||||
} else if (nextAnnotation instanceof ResourceParam) {
|
||||
if (!IResource.class.isAssignableFrom(parameterType)) {
|
||||
throw new ConfigurationException("Method '" + method.getName() + "' is annotated with @" + ResourceParam.class.getSimpleName()
|
||||
+ " but has a type that is not an implemtation of " + IResource.class.getCanonicalName());
|
||||
}
|
||||
param = new ResourceParameter((Class<? extends IResource>) parameterType);
|
||||
} else if (nextAnnotation instanceof IdParam || nextAnnotation instanceof VersionIdParam) {
|
||||
param = null;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
haveHandledMethod = true;
|
||||
parameters.add(param);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if (!haveHandledMethod) {
|
||||
throw new ConfigurationException("Parameter #" + paramIndex + " of method '" + method.getName() + "' on type '" + method.getDeclaringClass().getCanonicalName()
|
||||
+ "' has no recognized FHIR interface parameter annotations. Don't know how to handle this parameter");
|
||||
}
|
||||
}
|
||||
|
||||
paramIndex++;
|
||||
|
|
|
@ -6,11 +6,12 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
import ca.uhn.fhir.model.dstu.valueset.SearchParamTypeEnum;
|
||||
import ca.uhn.fhir.rest.method.Request;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.util.QueryUtil;
|
||||
|
||||
public abstract class IQueryParameter implements IParameter {
|
||||
public abstract class BaseQueryParameter implements IParameter {
|
||||
|
||||
public abstract List<List<String>> encode(Object theObject) throws InternalErrorException;
|
||||
|
||||
|
@ -54,8 +55,8 @@ public abstract class IQueryParameter implements IParameter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object translateQueryParametersIntoServerArgument(Map<String, String[]> theQueryParameters, Object theRequestContents) throws InternalErrorException, InvalidRequestException {
|
||||
String[] value = theQueryParameters.get(getName());
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, Object theRequestContents) throws InternalErrorException, InvalidRequestException {
|
||||
String[] value = theRequest.getParameters().get(getName());
|
||||
if (value == null || value.length == 0) {
|
||||
if (handlesMissing()) {
|
||||
return parse(new ArrayList<List<String>>(0));
|
|
@ -4,6 +4,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.rest.method.Request;
|
||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
@ -16,12 +17,12 @@ public interface IParameter {
|
|||
* This <b>server method</b> method takes the data received by the server in an incoming request, and translates that data into a single argument for a server method invocation. Note that all
|
||||
* received data is passed to this method, but the expectation is that not necessarily that all data is used by every parameter.
|
||||
*
|
||||
* @param theQueryParameters
|
||||
* The query params, e.g. ?family=smith&given=john
|
||||
* @param theRequest
|
||||
* The incoming request object
|
||||
* @param theRequestContents
|
||||
* The parsed contents of the incoming request. E.g. if the request was an HTTP POST with a resource in the body, this argument would contain the parsed {@link IResource} instance.
|
||||
* @return Returns the argument object as it will be passed to the {@link IResourceProvider} method.
|
||||
*/
|
||||
Object translateQueryParametersIntoServerArgument(Map<String, String[]> theQueryParameters, Object theRequestContents) throws InternalErrorException, InvalidRequestException;
|
||||
Object translateQueryParametersIntoServerArgument(Request theRequest, Object theRequestContents) throws InternalErrorException, InvalidRequestException;
|
||||
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ import ca.uhn.fhir.rest.annotation.IncludeParam;
|
|||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
public class IncludeParameter extends IQueryParameter {
|
||||
public class IncludeParameter extends BaseQueryParameter {
|
||||
|
||||
private Class<? extends Collection<PathSpecification>> myInstantiableCollectionType;
|
||||
private HashSet<String> myAllow;
|
||||
|
|
|
@ -4,6 +4,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.rest.method.Request;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
|
@ -22,7 +23,7 @@ public class ResourceParameter implements IParameter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object translateQueryParametersIntoServerArgument(Map<String, String[]> theQueryParameters, Object theRequestContents) throws InternalErrorException, InvalidRequestException {
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, Object theRequestContents) throws InternalErrorException, InvalidRequestException {
|
||||
IResource resource = (IResource) theRequestContents;
|
||||
return resource;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
|||
/**
|
||||
* Created by dsotnikov on 2/25/2014.
|
||||
*/
|
||||
public class SearchParameter extends IQueryParameter {
|
||||
public class SearchParameter extends BaseQueryParameter {
|
||||
|
||||
private String name;
|
||||
private IParamBinder myParamBinder;
|
||||
|
|
|
@ -162,6 +162,7 @@ public class RestfulServer extends HttpServlet {
|
|||
}
|
||||
ourLog.info("Got {} resource providers", typeToProvider.size());
|
||||
for (IResourceProvider provider : typeToProvider.values()) {
|
||||
assertProviderIsValid(provider);
|
||||
findResourceMethods(provider);
|
||||
}
|
||||
}
|
||||
|
@ -169,6 +170,7 @@ public class RestfulServer extends HttpServlet {
|
|||
Collection<Object> providers = getProviders();
|
||||
if (providers != null) {
|
||||
for (Object next : providers) {
|
||||
assertProviderIsValid(next);
|
||||
findResourceMethods(next);
|
||||
}
|
||||
}
|
||||
|
@ -184,6 +186,12 @@ public class RestfulServer extends HttpServlet {
|
|||
ourLog.info("A FHIR has been lit on this server");
|
||||
}
|
||||
|
||||
private void assertProviderIsValid(Object theNext) throws ConfigurationException {
|
||||
if (Modifier.isPublic(theNext.getClass().getModifiers()) == false) {
|
||||
throw new ConfigurationException("Can not use provider '" + theNext.getClass() + "' - Must be public");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isUseBrowserFriendlyContentTypes() {
|
||||
return myUseBrowserFriendlyContentTypes;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ import ca.uhn.fhir.rest.annotation.Metadata;
|
|||
import ca.uhn.fhir.rest.method.BaseMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.SearchMethodBinding;
|
||||
import ca.uhn.fhir.rest.param.IParameter;
|
||||
import ca.uhn.fhir.rest.param.IQueryParameter;
|
||||
import ca.uhn.fhir.rest.param.BaseQueryParameter;
|
||||
import ca.uhn.fhir.rest.server.ResourceBinding;
|
||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
import ca.uhn.fhir.util.ExtensionConstants;
|
||||
|
@ -86,11 +86,11 @@ public class ServerConformanceProvider {
|
|||
RestResourceSearchParam searchParam = null;
|
||||
StringDt searchParamChain = null;
|
||||
for (IParameter nextParameterObj : params) {
|
||||
if (!(nextParameterObj instanceof IQueryParameter)) {
|
||||
if (!(nextParameterObj instanceof BaseQueryParameter)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
IQueryParameter nextParameter = (IQueryParameter)nextParameterObj;
|
||||
BaseQueryParameter nextParameter = (BaseQueryParameter)nextParameterObj;
|
||||
if (nextParameter.getName().startsWith("_")) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ DIV.hapiHeaderText {
|
|||
TABLE.hapiTableOfValues THEAD TR TD {
|
||||
background: #A0A0F0;
|
||||
color: #000080;
|
||||
font-size: 1.em;
|
||||
font-size: 1.2em;
|
||||
font-weight: bold;
|
||||
padding: 5px;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
package example;
|
||||
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.client.HttpBasicAuthInterceptor;
|
||||
import ca.uhn.fhir.rest.client.IRestfulClientFactory;
|
||||
import ca.uhn.fhir.rest.client.api.IBasicClient;
|
||||
|
||||
public class ClientExamples {
|
||||
|
||||
public interface PatientClient extends IBasicClient {
|
||||
// nothing yet
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void createSecurity() {
|
||||
//START SNIPPET: security
|
||||
// Create a context and get the client factory so it can be configured
|
||||
FhirContext ctx = new FhirContext();
|
||||
IRestfulClientFactory clientFactory = ctx.getRestfulClientFactory();
|
||||
|
||||
// Create an HTTP Client Builder
|
||||
HttpClientBuilder builder = HttpClientBuilder.create();
|
||||
|
||||
// This interceptor adds HTTP username/password to every request
|
||||
String username = "foobar";
|
||||
String password = "boobear";
|
||||
builder.addInterceptorFirst(new HttpBasicAuthInterceptor(username, password));
|
||||
|
||||
// Use the new HTTP client builder
|
||||
clientFactory.setHttpClient(builder.build());
|
||||
|
||||
// Actually create a client instance
|
||||
PatientClient client = ctx.newRestfulClient(PatientClient.class, "http://localhost:9999/");
|
||||
//END SNIPPET: security
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
|
||||
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
|
||||
|
||||
<properties>
|
||||
<title>RESTful Client - HAPI FHIR</title>
|
||||
|
@ -15,16 +16,22 @@
|
|||
</macro>
|
||||
|
||||
<p>
|
||||
HAPI provides a built-in mechanism for connecting to FHIR RESTful servers.
|
||||
The HAPI RESTful client is designed to be easy to set up and to allow strong
|
||||
HAPI provides a built-in mechanism for connecting to FHIR RESTful
|
||||
servers.
|
||||
The HAPI RESTful client is designed to be easy to set up and
|
||||
to allow strong
|
||||
compile-time type checking wherever possible.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Setup is mostly done using simple annotations, which means that it should
|
||||
be possible to create a FHIR compliant server quickly and easily. Once again,
|
||||
this design is intended to be similar to that of JAX-WS, so users of that
|
||||
specification should be comfortable with this one.
|
||||
Setup is mostly done using simple annotations, which means that it
|
||||
should
|
||||
be possible to create a FHIR compliant server quickly and
|
||||
easily. Once again,
|
||||
this design is intended to be similar to that of
|
||||
JAX-WS, so users of that
|
||||
specification should be comfortable with
|
||||
this one.
|
||||
</p>
|
||||
|
||||
<subsection name="Defining A Restful Client Interface">
|
||||
|
@ -36,35 +43,45 @@
|
|||
|
||||
<p>
|
||||
A restful client interface class must extend the
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/client/api/IRestfulClient.html">IRestfulClient</a> interface,
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/client/api/IRestfulClient.html">IRestfulClient</a>
|
||||
interface,
|
||||
and will contain one or more methods which have been
|
||||
annotated with special annotations indicating which RESTful operation
|
||||
that method supports. Below is a simple example of a resource provider
|
||||
annotated with special annotations indicating which RESTful
|
||||
operation
|
||||
that method supports. Below is a simple example of a
|
||||
resource provider
|
||||
which supports the
|
||||
<a href="http://hl7.org/implement/standards/fhir/http.html#read">read</a>
|
||||
operation (i.e. retrieve a single resource by ID) as well as the
|
||||
<a href="http://hl7.org/implement/standards/fhir/http.html#search">search</a>
|
||||
operation (i.e. find any resources matching a given criteria) for a specific
|
||||
operation (i.e. find any resources matching a given criteria) for a
|
||||
specific
|
||||
search criteria.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
You may notice that this interface looks a lot like the Resource Provider
|
||||
which is defined for use by the RESTful server. In fact, it supports all
|
||||
of the same annotations and is essentially identical, other than the
|
||||
You may notice that this interface looks a lot like the Resource
|
||||
Provider
|
||||
which is defined for use by the RESTful server. In fact, it
|
||||
supports all
|
||||
of the same annotations and is essentially identical,
|
||||
other than the
|
||||
fact that for a client you must use an interface but for a server you
|
||||
must use a concrete class with method implementations.
|
||||
</p>
|
||||
|
||||
<macro name="snippet">
|
||||
<param name="id" value="provider" />
|
||||
<param name="file" value="src/site/example/java/example/RestfulClientImpl.java" />
|
||||
<param name="file"
|
||||
value="src/site/example/java/example/RestfulClientImpl.java" />
|
||||
</macro>
|
||||
|
||||
<p>
|
||||
You will probably want to add more methods
|
||||
to your client interface. See
|
||||
<a href="./doc_rest_operations.html">RESTful Operations</a> for
|
||||
to your client interface.
|
||||
See
|
||||
<a href="./doc_rest_operations.html">RESTful Operations</a>
|
||||
for
|
||||
lots more examples of how to add methods for various operations.
|
||||
</p>
|
||||
|
||||
|
@ -75,12 +92,14 @@
|
|||
<p>
|
||||
Once your client interface is created, all that is left is to
|
||||
create a FhirContext and instantiate the client and you are
|
||||
ready to start using it.
|
||||
ready to
|
||||
start using it.
|
||||
</p>
|
||||
|
||||
<macro name="snippet">
|
||||
<param name="id" value="client" />
|
||||
<param name="file" value="src/site/example/java/example/ExampleRestfulClient.java" />
|
||||
<param name="file"
|
||||
value="src/site/example/java/example/ExampleRestfulClient.java" />
|
||||
</macro>
|
||||
|
||||
</subsection>
|
||||
|
@ -91,16 +110,53 @@
|
|||
|
||||
<p>
|
||||
The following is a complete example showing a RESTful client
|
||||
using HAPI FHIR.
|
||||
using
|
||||
HAPI FHIR.
|
||||
</p>
|
||||
|
||||
<macro name="snippet">
|
||||
<param name="id" value="client" />
|
||||
<param name="file" value="src/site/example/java/example/CompleteExampleClient.java" />
|
||||
<param name="file"
|
||||
value="src/site/example/java/example/CompleteExampleClient.java" />
|
||||
</macro>
|
||||
|
||||
</section>
|
||||
|
||||
<section name="Configuring the HTTP Client">
|
||||
|
||||
<p>
|
||||
The client uses <a href="http://hc.apache.org/httpcomponents-client-ga/">Apache HTTP Client</a>
|
||||
as a provider. The HTTP Client is very powerful, but can be a bit tricky to configure.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In many cases, the default configuration should suffice. However, if you require anything
|
||||
more sophisticated (username/password, HTTP proxy settings, etc.) you will need
|
||||
to configure the underlying client.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The underlying client configuration is provided by setting an
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/client/IRestfulClientFactory.html#setHttpClient(org.apache.http.client.HttpClient)">HttpClient</a>
|
||||
on the RestfulClientFactory.
|
||||
</p>
|
||||
|
||||
<subsection name="HTTP Basic Authorization">
|
||||
|
||||
<p>
|
||||
The following example shows how to configure your client to
|
||||
use a specific username and password in every request.
|
||||
</p>
|
||||
|
||||
<macro name="snippet">
|
||||
<param name="id" value="security" />
|
||||
<param name="file" value="src/site/example/java/example/ClientExamples.java" />
|
||||
</macro>
|
||||
|
||||
</subsection>
|
||||
|
||||
</section>
|
||||
|
||||
</body>
|
||||
|
||||
</document>
|
||||
|
|
|
@ -0,0 +1,134 @@
|
|||
package ca.uhn.fhir.rest.client;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.http.auth.AuthScope;
|
||||
import org.apache.http.auth.UsernamePasswordCredentials;
|
||||
import org.apache.http.client.CredentialsProvider;
|
||||
import org.apache.http.impl.client.BasicCredentialsProvider;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.servlet.ServletHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.rest.annotation.RequiredParam;
|
||||
import ca.uhn.fhir.rest.annotation.Search;
|
||||
import ca.uhn.fhir.rest.client.api.IBasicClient;
|
||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||
import ca.uhn.fhir.rest.server.ResfulServerMethodTest.DummyDiagnosticReportResourceProvider;
|
||||
import ca.uhn.fhir.rest.server.ResfulServerMethodTest.DummyPatientResourceProvider;
|
||||
import ca.uhn.fhir.rest.server.ResfulServerMethodTest.DummyRestfulServer;
|
||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
import ca.uhn.fhir.rest.server.provider.ServerProfileProvider;
|
||||
import ca.uhn.fhir.testutil.RandomServerPortProvider;
|
||||
|
||||
public class ClientIntegrationTest {
|
||||
|
||||
private int myPort;
|
||||
private Server myServer;
|
||||
private FhirContext myCtx;
|
||||
private MyPatientResourceProvider myPatientProvider;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
myPort = RandomServerPortProvider.findFreePort();
|
||||
myServer = new Server(myPort);
|
||||
myCtx = new FhirContext(Patient.class);
|
||||
|
||||
myPatientProvider = new MyPatientResourceProvider();
|
||||
|
||||
ServletHandler proxyHandler = new ServletHandler();
|
||||
RestfulServer servlet = new RestfulServer();
|
||||
servlet.setResourceProviders(myPatientProvider);
|
||||
ServletHolder servletHolder = new ServletHolder(servlet);
|
||||
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
||||
myServer.setHandler(proxyHandler);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClientSecurity() throws Exception {
|
||||
// BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
|
||||
// UsernamePasswordCredentials credentials = new UsernamePasswordCredentials("foobar", "boobear");
|
||||
// AuthScope scope = new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT);
|
||||
// credentialsProvider.setCredentials(scope, credentials);
|
||||
// builder.setDefaultCredentialsProvider(credentialsProvider);
|
||||
//
|
||||
|
||||
myServer.start();
|
||||
|
||||
FhirContext ctx = new FhirContext();
|
||||
|
||||
HttpClientBuilder builder = HttpClientBuilder.create();
|
||||
// PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
||||
// builder.setConnectionManager(connectionManager);
|
||||
builder.addInterceptorFirst(new HttpBasicAuthInterceptor("foobar", "boobear"));
|
||||
|
||||
CloseableHttpClient httpClient = builder.build();
|
||||
ctx.getRestfulClientFactory().setHttpClient(httpClient);
|
||||
|
||||
PatientClient client = ctx.newRestfulClient(PatientClient.class, "http://localhost:" + myPort + "/");
|
||||
|
||||
List<Patient> actualPatients = client.searchForPatients(new StringDt("AAAABBBB"));
|
||||
assertEquals(1, actualPatients.size());
|
||||
assertEquals("AAAABBBB", actualPatients.get(0).getNameFirstRep().getFamilyAsSingleString());
|
||||
|
||||
assertEquals("Basic Zm9vYmFyOmJvb2JlYXI=", myPatientProvider.getAuthorizationHeader());
|
||||
}
|
||||
|
||||
|
||||
@After
|
||||
public void after() throws Exception {
|
||||
myServer.stop();
|
||||
}
|
||||
|
||||
|
||||
public static class MyPatientResourceProvider implements IResourceProvider {
|
||||
private String myAuthorizationHeader;
|
||||
|
||||
public String getAuthorizationHeader() {
|
||||
return myAuthorizationHeader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends IResource> getResourceType() {
|
||||
return Patient.class;
|
||||
}
|
||||
|
||||
@Search
|
||||
public List<Patient> searchForPatients(@RequiredParam(name="fooParam") StringDt theFooParam, HttpServletRequest theRequest) {
|
||||
|
||||
myAuthorizationHeader = theRequest.getHeader("authorization");
|
||||
|
||||
Patient retVal = new Patient();
|
||||
retVal.addName().addFamily(theFooParam.getValue());
|
||||
return Collections.singletonList(retVal);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static interface PatientClient extends IBasicClient {
|
||||
|
||||
@Search
|
||||
public List<Patient> searchForPatients(@RequiredParam(name="fooParam") StringDt theFooParam);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -52,9 +52,9 @@ import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
|
|||
|
||||
public class ClientTest {
|
||||
|
||||
private FhirContext ctx;
|
||||
private HttpClient httpClient;
|
||||
private HttpResponse httpResponse;
|
||||
private FhirContext ctx;
|
||||
|
||||
// atom-document-large.xml
|
||||
|
||||
|
@ -68,173 +68,19 @@ public class ClientTest {
|
|||
httpResponse = mock(HttpResponse.class, new ReturnsDeepStubs());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHistoryResourceInstance() throws Exception {
|
||||
|
||||
private String getPatientFeedWithOneResult() {
|
||||
//@formatter:off
|
||||
String msg = "<feed xmlns=\"http://www.w3.org/2005/Atom\"><title/><id>6c1d93be-027f-468d-9d47-f826cd15cf42</id><link rel=\"self\" href=\"http://localhost:51698/Patient/222/_history\"/><link rel=\"fhir-base\" href=\"http://localhost:51698\"/><os:totalResults xmlns:os=\"http://a9.com/-/spec/opensearch/1.1/\">2</os:totalResults><published>2014-04-13T18:24:50-04:00</published><author><name>ca.uhn.fhir.rest.method.HistoryMethodBinding</name></author><entry><title>Patient 222</title><id>222</id><updated>1969-12-31T19:00:20.000-05:00</updated><published>1969-12-31T19:00:10.000-05:00</published><link rel=\"self\" href=\"http://localhost:51698/Patient/222/_history/1\"/><content type=\"text/xml\"><Patient xmlns=\"http://hl7.org/fhir\"><identifier><use value=\"official\"/><system value=\"urn:hapitest:mrns\"/><value value=\"00001\"/></identifier><name><family value=\"OlderFamily\"/><given value=\"PatientOne\"/></name><gender><text value=\"M\"/></gender></Patient></content></entry><entry><title>Patient 222</title><id>222</id><updated>1969-12-31T19:00:30.000-05:00</updated><published>1969-12-31T19:00:10.000-05:00</published><link rel=\"self\" href=\"http://localhost:51698/Patient/222/_history/2\"/><content type=\"text/xml\"><Patient xmlns=\"http://hl7.org/fhir\"><identifier><use value=\"official\"/><system value=\"urn:hapitest:mrns\"/><value value=\"00001\"/></identifier><name><family value=\"NewerFamily\"/><given value=\"PatientOne\"/></name><gender><text value=\"M\"/></gender></Patient></content></entry></feed>";
|
||||
//@formatter:on
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_ATOM_XML + "; charset=UTF-8"));
|
||||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
|
||||
ITestClient client = ctx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
Bundle response = client.getHistoryPatientInstance(new IdDt("111"));
|
||||
|
||||
assertEquals("http://foo/Patient/111/_history", capt.getValue().getURI().toString());
|
||||
|
||||
assertEquals(2, response.getEntries().size());
|
||||
|
||||
// Older resource
|
||||
{
|
||||
BundleEntry olderEntry = response.getEntries().get(0);
|
||||
assertEquals("222", olderEntry.getId().getValue());
|
||||
assertThat(olderEntry.getLinkSelf().getValue(), StringEndsWith.endsWith("/Patient/222/_history/1"));
|
||||
InstantDt pubExpected = new InstantDt(new Date(10000L));
|
||||
InstantDt pubActualRes = (InstantDt) olderEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.PUBLISHED);
|
||||
InstantDt pubActualBundle = olderEntry.getPublished();
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualRes.getValueAsString());
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualBundle.getValueAsString());
|
||||
InstantDt updExpected = new InstantDt(new Date(20000L));
|
||||
InstantDt updActualRes = (InstantDt) olderEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
|
||||
InstantDt updActualBundle = olderEntry.getUpdated();
|
||||
assertEquals(updExpected.getValueAsString(), updActualRes.getValueAsString());
|
||||
assertEquals(updExpected.getValueAsString(), updActualBundle.getValueAsString());
|
||||
}
|
||||
// Newer resource
|
||||
{
|
||||
BundleEntry newerEntry = response.getEntries().get(1);
|
||||
assertEquals("222", newerEntry.getId().getValue());
|
||||
assertThat(newerEntry.getLinkSelf().getValue(), StringEndsWith.endsWith("/Patient/222/_history/2"));
|
||||
InstantDt pubExpected = new InstantDt(new Date(10000L));
|
||||
InstantDt pubActualRes = (InstantDt) newerEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.PUBLISHED);
|
||||
InstantDt pubActualBundle = newerEntry.getPublished();
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualRes.getValueAsString());
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualBundle.getValueAsString());
|
||||
InstantDt updExpected = new InstantDt(new Date(30000L));
|
||||
InstantDt updActualRes = (InstantDt) newerEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
|
||||
InstantDt updActualBundle = newerEntry.getUpdated();
|
||||
assertEquals(updExpected.getValueAsString(), updActualRes.getValueAsString());
|
||||
assertEquals(updExpected.getValueAsString(), updActualBundle.getValueAsString());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHistoryResourceType() throws Exception {
|
||||
|
||||
//@formatter:off
|
||||
String msg = "<feed xmlns=\"http://www.w3.org/2005/Atom\"><title/><id>6c1d93be-027f-468d-9d47-f826cd15cf42</id><link rel=\"self\" href=\"http://localhost:51698/Patient/222/_history\"/><link rel=\"fhir-base\" href=\"http://localhost:51698\"/><os:totalResults xmlns:os=\"http://a9.com/-/spec/opensearch/1.1/\">2</os:totalResults><published>2014-04-13T18:24:50-04:00</published><author><name>ca.uhn.fhir.rest.method.HistoryMethodBinding</name></author><entry><title>Patient 222</title><id>222</id><updated>1969-12-31T19:00:20.000-05:00</updated><published>1969-12-31T19:00:10.000-05:00</published><link rel=\"self\" href=\"http://localhost:51698/Patient/222/_history/1\"/><content type=\"text/xml\"><Patient xmlns=\"http://hl7.org/fhir\"><identifier><use value=\"official\"/><system value=\"urn:hapitest:mrns\"/><value value=\"00001\"/></identifier><name><family value=\"OlderFamily\"/><given value=\"PatientOne\"/></name><gender><text value=\"M\"/></gender></Patient></content></entry><entry><title>Patient 222</title><id>222</id><updated>1969-12-31T19:00:30.000-05:00</updated><published>1969-12-31T19:00:10.000-05:00</published><link rel=\"self\" href=\"http://localhost:51698/Patient/222/_history/2\"/><content type=\"text/xml\"><Patient xmlns=\"http://hl7.org/fhir\"><identifier><use value=\"official\"/><system value=\"urn:hapitest:mrns\"/><value value=\"00001\"/></identifier><name><family value=\"NewerFamily\"/><given value=\"PatientOne\"/></name><gender><text value=\"M\"/></gender></Patient></content></entry></feed>";
|
||||
//@formatter:on
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_ATOM_XML + "; charset=UTF-8"));
|
||||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
|
||||
ITestClient client = ctx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
Bundle response = client.getHistoryPatientType();
|
||||
|
||||
assertEquals("http://foo/Patient/_history", capt.getValue().getURI().toString());
|
||||
|
||||
assertEquals(2, response.getEntries().size());
|
||||
|
||||
// Older resource
|
||||
{
|
||||
BundleEntry olderEntry = response.getEntries().get(0);
|
||||
assertEquals("222", olderEntry.getId().getValue());
|
||||
assertThat(olderEntry.getLinkSelf().getValue(), StringEndsWith.endsWith("/Patient/222/_history/1"));
|
||||
InstantDt pubExpected = new InstantDt(new Date(10000L));
|
||||
InstantDt pubActualRes = (InstantDt) olderEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.PUBLISHED);
|
||||
InstantDt pubActualBundle = olderEntry.getPublished();
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualRes.getValueAsString());
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualBundle.getValueAsString());
|
||||
InstantDt updExpected = new InstantDt(new Date(20000L));
|
||||
InstantDt updActualRes = (InstantDt) olderEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
|
||||
InstantDt updActualBundle = olderEntry.getUpdated();
|
||||
assertEquals(updExpected.getValueAsString(), updActualRes.getValueAsString());
|
||||
assertEquals(updExpected.getValueAsString(), updActualBundle.getValueAsString());
|
||||
}
|
||||
// Newer resource
|
||||
{
|
||||
BundleEntry newerEntry = response.getEntries().get(1);
|
||||
assertEquals("222", newerEntry.getId().getValue());
|
||||
assertThat(newerEntry.getLinkSelf().getValue(), StringEndsWith.endsWith("/Patient/222/_history/2"));
|
||||
InstantDt pubExpected = new InstantDt(new Date(10000L));
|
||||
InstantDt pubActualRes = (InstantDt) newerEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.PUBLISHED);
|
||||
InstantDt pubActualBundle = newerEntry.getPublished();
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualRes.getValueAsString());
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualBundle.getValueAsString());
|
||||
InstantDt updExpected = new InstantDt(new Date(30000L));
|
||||
InstantDt updActualRes = (InstantDt) newerEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
|
||||
InstantDt updActualBundle = newerEntry.getUpdated();
|
||||
assertEquals(updExpected.getValueAsString(), updActualRes.getValueAsString());
|
||||
assertEquals(updExpected.getValueAsString(), updActualBundle.getValueAsString());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHistoryServer() throws Exception {
|
||||
|
||||
//@formatter:off
|
||||
String msg = "<feed xmlns=\"http://www.w3.org/2005/Atom\"><title/><id>6c1d93be-027f-468d-9d47-f826cd15cf42</id><link rel=\"self\" href=\"http://localhost:51698/Patient/222/_history\"/><link rel=\"fhir-base\" href=\"http://localhost:51698\"/><os:totalResults xmlns:os=\"http://a9.com/-/spec/opensearch/1.1/\">2</os:totalResults><published>2014-04-13T18:24:50-04:00</published><author><name>ca.uhn.fhir.rest.method.HistoryMethodBinding</name></author><entry><title>Patient 222</title><id>222</id><updated>1969-12-31T19:00:20.000-05:00</updated><published>1969-12-31T19:00:10.000-05:00</published><link rel=\"self\" href=\"http://localhost:51698/Patient/222/_history/1\"/><content type=\"text/xml\"><Patient xmlns=\"http://hl7.org/fhir\"><identifier><use value=\"official\"/><system value=\"urn:hapitest:mrns\"/><value value=\"00001\"/></identifier><name><family value=\"OlderFamily\"/><given value=\"PatientOne\"/></name><gender><text value=\"M\"/></gender></Patient></content></entry><entry><title>Patient 222</title><id>222</id><updated>1969-12-31T19:00:30.000-05:00</updated><published>1969-12-31T19:00:10.000-05:00</published><link rel=\"self\" href=\"http://localhost:51698/Patient/222/_history/2\"/><content type=\"text/xml\"><Patient xmlns=\"http://hl7.org/fhir\"><identifier><use value=\"official\"/><system value=\"urn:hapitest:mrns\"/><value value=\"00001\"/></identifier><name><family value=\"NewerFamily\"/><given value=\"PatientOne\"/></name><gender><text value=\"M\"/></gender></Patient></content></entry></feed>";
|
||||
//@formatter:on
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_ATOM_XML + "; charset=UTF-8"));
|
||||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
|
||||
ITestClient client = ctx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
Bundle response = client.getHistoryServer();
|
||||
|
||||
assertEquals("http://foo/_history", capt.getValue().getURI().toString());
|
||||
|
||||
assertEquals(2, response.getEntries().size());
|
||||
|
||||
// Older resource
|
||||
{
|
||||
BundleEntry olderEntry = response.getEntries().get(0);
|
||||
assertEquals("222", olderEntry.getId().getValue());
|
||||
assertThat(olderEntry.getLinkSelf().getValue(), StringEndsWith.endsWith("/Patient/222/_history/1"));
|
||||
InstantDt pubExpected = new InstantDt(new Date(10000L));
|
||||
InstantDt pubActualRes = (InstantDt) olderEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.PUBLISHED);
|
||||
InstantDt pubActualBundle = olderEntry.getPublished();
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualRes.getValueAsString());
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualBundle.getValueAsString());
|
||||
InstantDt updExpected = new InstantDt(new Date(20000L));
|
||||
InstantDt updActualRes = (InstantDt) olderEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
|
||||
InstantDt updActualBundle = olderEntry.getUpdated();
|
||||
assertEquals(updExpected.getValueAsString(), updActualRes.getValueAsString());
|
||||
assertEquals(updExpected.getValueAsString(), updActualBundle.getValueAsString());
|
||||
}
|
||||
// Newer resource
|
||||
{
|
||||
BundleEntry newerEntry = response.getEntries().get(1);
|
||||
assertEquals("222", newerEntry.getId().getValue());
|
||||
assertThat(newerEntry.getLinkSelf().getValue(), StringEndsWith.endsWith("/Patient/222/_history/2"));
|
||||
InstantDt pubExpected = new InstantDt(new Date(10000L));
|
||||
InstantDt pubActualRes = (InstantDt) newerEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.PUBLISHED);
|
||||
InstantDt pubActualBundle = newerEntry.getPublished();
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualRes.getValueAsString());
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualBundle.getValueAsString());
|
||||
InstantDt updExpected = new InstantDt(new Date(30000L));
|
||||
InstantDt updActualRes = (InstantDt) newerEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
|
||||
InstantDt updActualBundle = newerEntry.getUpdated();
|
||||
assertEquals(updExpected.getValueAsString(), updActualRes.getValueAsString());
|
||||
assertEquals(updExpected.getValueAsString(), updActualBundle.getValueAsString());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRead() throws Exception {
|
||||
|
||||
//@formatter:off
|
||||
String msg = "<Patient xmlns=\"http://hl7.org/fhir\">"
|
||||
String msg = "<feed xmlns=\"http://www.w3.org/2005/Atom\">\n" +
|
||||
"<title/>\n" +
|
||||
"<id>d039f91a-cc3c-4013-988e-af4d8d0614bd</id>\n" +
|
||||
"<os:totalResults xmlns:os=\"http://a9.com/-/spec/opensearch/1.1/\">1</os:totalResults>\n" +
|
||||
"<published>2014-03-11T16:35:07-04:00</published>\n" +
|
||||
"<author>\n" +
|
||||
"<name>ca.uhn.fhir.rest.server.DummyRestfulServer</name>\n" +
|
||||
"</author>\n" +
|
||||
"<entry>\n" +
|
||||
"<content type=\"text/xml\">"
|
||||
+ "<Patient xmlns=\"http://hl7.org/fhir\">"
|
||||
+ "<text><status value=\"generated\" /><div xmlns=\"http://www.w3.org/1999/xhtml\">John Cardinal: 444333333 </div></text>"
|
||||
+ "<identifier><label value=\"SSN\" /><system value=\"http://orionhealth.com/mrn\" /><value value=\"PRP1660\" /></identifier>"
|
||||
+ "<name><use value=\"official\" /><family value=\"Cardinal\" /><given value=\"John\" /></name>"
|
||||
|
@ -242,25 +88,14 @@ public class ClientTest {
|
|||
+ "<telecom><system value=\"phone\" /><value value=\"555-555-2004\" /><use value=\"work\" /></telecom>"
|
||||
+ "<gender><coding><system value=\"http://hl7.org/fhir/v3/AdministrativeGender\" /><code value=\"M\" /></coding></gender>"
|
||||
+ "<address><use value=\"home\" /><line value=\"2222 Home Street\" /></address><active value=\"true\" />"
|
||||
+ "</Patient>";
|
||||
+ "</Patient>"
|
||||
+ "</content>\n"
|
||||
+ " </entry>\n"
|
||||
+ "</feed>";
|
||||
//@formatter:on
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
|
||||
ITestClient client = ctx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
// Patient response = client.findPatientByMrn(new IdentifierDt("urn:foo", "123"));
|
||||
Patient response = client.getPatientById(new IdDt("111"));
|
||||
|
||||
assertEquals("http://foo/Patient/111", capt.getValue().getURI().toString());
|
||||
assertEquals("PRP1660", response.getIdentifier().get(0).getValue().getValue());
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCreate() throws Exception {
|
||||
|
||||
|
@ -272,7 +107,7 @@ public class ClientTest {
|
|||
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
||||
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_TEXT + "; charset=UTF-8"));
|
||||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
||||
when(httpResponse.getAllHeaders()).thenReturn(toHeaderArray("Location" , "http://example.com/fhir/Patient/100/_history/200"));
|
||||
when(httpResponse.getAllHeaders()).thenReturn(toHeaderArray("Location", "http://example.com/fhir/Patient/100/_history/200"));
|
||||
|
||||
ITestClient client = ctx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
MethodOutcome response = client.createPatient(patient);
|
||||
|
@ -284,6 +119,25 @@ public class ClientTest {
|
|||
assertEquals("200", response.getVersionId().getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateBad() throws Exception {
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier("urn:foo", "123");
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 400, "OK"));
|
||||
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_TEXT + "; charset=UTF-8"));
|
||||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader("foobar"), Charset.forName("UTF-8")));
|
||||
|
||||
try {
|
||||
ctx.newRestfulClient(ITestClient.class, "http://foo").createPatient(patient);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertThat(e.getMessage(), StringContains.containsString("foobar"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDelete() throws Exception {
|
||||
|
@ -322,120 +176,189 @@ public class ClientTest {
|
|||
assertEquals("http://foo/DiagnosticReport/1234", capt.getValue().getURI().toString());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testUpdate() throws Exception {
|
||||
public void testGetConformance() throws Exception {
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier("urn:foo", "123");
|
||||
String msg = IOUtils.toString(ClientTest.class.getResourceAsStream("/example-metadata.xml"));
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
||||
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_TEXT + "; charset=UTF-8"));
|
||||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
||||
when(httpResponse.getAllHeaders()).thenReturn(toHeaderArray("Location" , "http://example.com/fhir/Patient/100/_history/200"));
|
||||
|
||||
ITestClient client = ctx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
MethodOutcome response = client.updatePatient(new IdDt("100"), patient);
|
||||
|
||||
assertEquals(HttpPut.class, capt.getValue().getClass());
|
||||
HttpPut post = (HttpPut) capt.getValue();
|
||||
assertThat(post.getURI().toASCIIString(), StringEndsWith.endsWith("/Patient/100"));
|
||||
assertThat(IOUtils.toString(post.getEntity().getContent()), StringContains.containsString("<Patient"));
|
||||
assertEquals("100", response.getId().getValue());
|
||||
assertEquals("200", response.getVersionId().getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a FHIR content type, but no content and make sure we handle this without crashing
|
||||
*/
|
||||
@Test
|
||||
public void testUpdateWithEmptyResponse() throws Exception {
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier("urn:foo", "123");
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
||||
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
||||
when(httpResponse.getAllHeaders()).thenReturn(toHeaderArray("Location" , "http://example.com/fhir/Patient/100/_history/200"));
|
||||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
|
||||
ITestClient client = ctx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
client.updatePatient(new IdDt("100"), new IdDt("200"), patient);
|
||||
Conformance response = client.getServerConformanceStatement();
|
||||
|
||||
assertEquals("http://foo/metadata", capt.getValue().getURI().toString());
|
||||
assertEquals("Health Intersections", response.getPublisher().getValue());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateWithVersion() throws Exception {
|
||||
public void testHistoryResourceInstance() throws Exception {
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier("urn:foo", "123");
|
||||
//@formatter:off
|
||||
String msg = "<feed xmlns=\"http://www.w3.org/2005/Atom\"><title/><id>6c1d93be-027f-468d-9d47-f826cd15cf42</id><link rel=\"self\" href=\"http://localhost:51698/Patient/222/_history\"/><link rel=\"fhir-base\" href=\"http://localhost:51698\"/><os:totalResults xmlns:os=\"http://a9.com/-/spec/opensearch/1.1/\">2</os:totalResults><published>2014-04-13T18:24:50-04:00</published><author><name>ca.uhn.fhir.rest.method.HistoryMethodBinding</name></author><entry><title>Patient 222</title><id>222</id><updated>1969-12-31T19:00:20.000-05:00</updated><published>1969-12-31T19:00:10.000-05:00</published><link rel=\"self\" href=\"http://localhost:51698/Patient/222/_history/1\"/><content type=\"text/xml\"><Patient xmlns=\"http://hl7.org/fhir\"><identifier><use value=\"official\"/><system value=\"urn:hapitest:mrns\"/><value value=\"00001\"/></identifier><name><family value=\"OlderFamily\"/><given value=\"PatientOne\"/></name><gender><text value=\"M\"/></gender></Patient></content></entry><entry><title>Patient 222</title><id>222</id><updated>1969-12-31T19:00:30.000-05:00</updated><published>1969-12-31T19:00:10.000-05:00</published><link rel=\"self\" href=\"http://localhost:51698/Patient/222/_history/2\"/><content type=\"text/xml\"><Patient xmlns=\"http://hl7.org/fhir\"><identifier><use value=\"official\"/><system value=\"urn:hapitest:mrns\"/><value value=\"00001\"/></identifier><name><family value=\"NewerFamily\"/><given value=\"PatientOne\"/></name><gender><text value=\"M\"/></gender></Patient></content></entry></feed>";
|
||||
//@formatter:on
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
||||
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_TEXT + "; charset=UTF-8"));
|
||||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
||||
when(httpResponse.getAllHeaders()).thenReturn(toHeaderArray("Location" , "http://example.com/fhir/Patient/100/_history/200"));
|
||||
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_ATOM_XML + "; charset=UTF-8"));
|
||||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
|
||||
ITestClient client = ctx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
MethodOutcome response = client.updatePatient(new IdDt("100"), new IdDt("200"), patient);
|
||||
Bundle response = client.getHistoryPatientInstance(new IdDt("111"));
|
||||
|
||||
assertEquals(HttpPut.class, capt.getValue().getClass());
|
||||
HttpPut post = (HttpPut) capt.getValue();
|
||||
assertThat(post.getURI().toASCIIString(), StringEndsWith.endsWith("/Patient/100"));
|
||||
assertThat(IOUtils.toString(post.getEntity().getContent()), StringContains.containsString("<Patient"));
|
||||
assertThat(post.getFirstHeader("Content-Location").getValue(), StringEndsWith.endsWith("/Patient/100/_history/200"));
|
||||
assertEquals("100", response.getId().getValue());
|
||||
assertEquals("200", response.getVersionId().getValue());
|
||||
}
|
||||
assertEquals("http://foo/Patient/111/_history", capt.getValue().getURI().toString());
|
||||
|
||||
assertEquals(2, response.getEntries().size());
|
||||
|
||||
@Test(expected=ResourceVersionConflictException.class)
|
||||
public void testUpdateWithResourceConflict() throws Exception {
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier("urn:foo", "123");
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
||||
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), Constants.STATUS_HTTP_409_CONFLICT, "Conflict"));
|
||||
|
||||
ITestClient client = ctx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
client.updatePatient(new IdDt("100"), new IdDt("200"), patient);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCreateBad() throws Exception {
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier("urn:foo", "123");
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 400, "OK"));
|
||||
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_TEXT + "; charset=UTF-8"));
|
||||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader("foobar"), Charset.forName("UTF-8")));
|
||||
|
||||
try {
|
||||
ctx.newRestfulClient(ITestClient.class, "http://foo").createPatient(patient);
|
||||
fail();
|
||||
}catch (InvalidRequestException e) {
|
||||
assertThat(e.getMessage(), StringContains.containsString("foobar"));
|
||||
// Older resource
|
||||
{
|
||||
BundleEntry olderEntry = response.getEntries().get(0);
|
||||
assertEquals("222", olderEntry.getId().getValue());
|
||||
assertThat(olderEntry.getLinkSelf().getValue(), StringEndsWith.endsWith("/Patient/222/_history/1"));
|
||||
InstantDt pubExpected = new InstantDt(new Date(10000L));
|
||||
InstantDt pubActualRes = (InstantDt) olderEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.PUBLISHED);
|
||||
InstantDt pubActualBundle = olderEntry.getPublished();
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualRes.getValueAsString());
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualBundle.getValueAsString());
|
||||
InstantDt updExpected = new InstantDt(new Date(20000L));
|
||||
InstantDt updActualRes = (InstantDt) olderEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
|
||||
InstantDt updActualBundle = olderEntry.getUpdated();
|
||||
assertEquals(updExpected.getValueAsString(), updActualRes.getValueAsString());
|
||||
assertEquals(updExpected.getValueAsString(), updActualBundle.getValueAsString());
|
||||
}
|
||||
// Newer resource
|
||||
{
|
||||
BundleEntry newerEntry = response.getEntries().get(1);
|
||||
assertEquals("222", newerEntry.getId().getValue());
|
||||
assertThat(newerEntry.getLinkSelf().getValue(), StringEndsWith.endsWith("/Patient/222/_history/2"));
|
||||
InstantDt pubExpected = new InstantDt(new Date(10000L));
|
||||
InstantDt pubActualRes = (InstantDt) newerEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.PUBLISHED);
|
||||
InstantDt pubActualBundle = newerEntry.getPublished();
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualRes.getValueAsString());
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualBundle.getValueAsString());
|
||||
InstantDt updExpected = new InstantDt(new Date(30000L));
|
||||
InstantDt updActualRes = (InstantDt) newerEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
|
||||
InstantDt updActualBundle = newerEntry.getUpdated();
|
||||
assertEquals(updExpected.getValueAsString(), updActualRes.getValueAsString());
|
||||
assertEquals(updExpected.getValueAsString(), updActualBundle.getValueAsString());
|
||||
}
|
||||
}
|
||||
|
||||
private Header[] toHeaderArray(String theName, String theValue) {
|
||||
return new Header[] {new BasicHeader(theName, theValue)};
|
||||
@Test
|
||||
public void testHistoryResourceType() throws Exception {
|
||||
|
||||
//@formatter:off
|
||||
String msg = "<feed xmlns=\"http://www.w3.org/2005/Atom\"><title/><id>6c1d93be-027f-468d-9d47-f826cd15cf42</id><link rel=\"self\" href=\"http://localhost:51698/Patient/222/_history\"/><link rel=\"fhir-base\" href=\"http://localhost:51698\"/><os:totalResults xmlns:os=\"http://a9.com/-/spec/opensearch/1.1/\">2</os:totalResults><published>2014-04-13T18:24:50-04:00</published><author><name>ca.uhn.fhir.rest.method.HistoryMethodBinding</name></author><entry><title>Patient 222</title><id>222</id><updated>1969-12-31T19:00:20.000-05:00</updated><published>1969-12-31T19:00:10.000-05:00</published><link rel=\"self\" href=\"http://localhost:51698/Patient/222/_history/1\"/><content type=\"text/xml\"><Patient xmlns=\"http://hl7.org/fhir\"><identifier><use value=\"official\"/><system value=\"urn:hapitest:mrns\"/><value value=\"00001\"/></identifier><name><family value=\"OlderFamily\"/><given value=\"PatientOne\"/></name><gender><text value=\"M\"/></gender></Patient></content></entry><entry><title>Patient 222</title><id>222</id><updated>1969-12-31T19:00:30.000-05:00</updated><published>1969-12-31T19:00:10.000-05:00</published><link rel=\"self\" href=\"http://localhost:51698/Patient/222/_history/2\"/><content type=\"text/xml\"><Patient xmlns=\"http://hl7.org/fhir\"><identifier><use value=\"official\"/><system value=\"urn:hapitest:mrns\"/><value value=\"00001\"/></identifier><name><family value=\"NewerFamily\"/><given value=\"PatientOne\"/></name><gender><text value=\"M\"/></gender></Patient></content></entry></feed>";
|
||||
//@formatter:on
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_ATOM_XML + "; charset=UTF-8"));
|
||||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
|
||||
ITestClient client = ctx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
Bundle response = client.getHistoryPatientType();
|
||||
|
||||
assertEquals("http://foo/Patient/_history", capt.getValue().getURI().toString());
|
||||
|
||||
assertEquals(2, response.getEntries().size());
|
||||
|
||||
// Older resource
|
||||
{
|
||||
BundleEntry olderEntry = response.getEntries().get(0);
|
||||
assertEquals("222", olderEntry.getId().getValue());
|
||||
assertThat(olderEntry.getLinkSelf().getValue(), StringEndsWith.endsWith("/Patient/222/_history/1"));
|
||||
InstantDt pubExpected = new InstantDt(new Date(10000L));
|
||||
InstantDt pubActualRes = (InstantDt) olderEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.PUBLISHED);
|
||||
InstantDt pubActualBundle = olderEntry.getPublished();
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualRes.getValueAsString());
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualBundle.getValueAsString());
|
||||
InstantDt updExpected = new InstantDt(new Date(20000L));
|
||||
InstantDt updActualRes = (InstantDt) olderEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
|
||||
InstantDt updActualBundle = olderEntry.getUpdated();
|
||||
assertEquals(updExpected.getValueAsString(), updActualRes.getValueAsString());
|
||||
assertEquals(updExpected.getValueAsString(), updActualBundle.getValueAsString());
|
||||
}
|
||||
// Newer resource
|
||||
{
|
||||
BundleEntry newerEntry = response.getEntries().get(1);
|
||||
assertEquals("222", newerEntry.getId().getValue());
|
||||
assertThat(newerEntry.getLinkSelf().getValue(), StringEndsWith.endsWith("/Patient/222/_history/2"));
|
||||
InstantDt pubExpected = new InstantDt(new Date(10000L));
|
||||
InstantDt pubActualRes = (InstantDt) newerEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.PUBLISHED);
|
||||
InstantDt pubActualBundle = newerEntry.getPublished();
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualRes.getValueAsString());
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualBundle.getValueAsString());
|
||||
InstantDt updExpected = new InstantDt(new Date(30000L));
|
||||
InstantDt updActualRes = (InstantDt) newerEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
|
||||
InstantDt updActualBundle = newerEntry.getUpdated();
|
||||
assertEquals(updExpected.getValueAsString(), updActualRes.getValueAsString());
|
||||
assertEquals(updExpected.getValueAsString(), updActualBundle.getValueAsString());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVRead() throws Exception {
|
||||
public void testHistoryServer() throws Exception {
|
||||
|
||||
//@formatter:off
|
||||
String msg = "<feed xmlns=\"http://www.w3.org/2005/Atom\"><title/><id>6c1d93be-027f-468d-9d47-f826cd15cf42</id><link rel=\"self\" href=\"http://localhost:51698/Patient/222/_history\"/><link rel=\"fhir-base\" href=\"http://localhost:51698\"/><os:totalResults xmlns:os=\"http://a9.com/-/spec/opensearch/1.1/\">2</os:totalResults><published>2014-04-13T18:24:50-04:00</published><author><name>ca.uhn.fhir.rest.method.HistoryMethodBinding</name></author><entry><title>Patient 222</title><id>222</id><updated>1969-12-31T19:00:20.000-05:00</updated><published>1969-12-31T19:00:10.000-05:00</published><link rel=\"self\" href=\"http://localhost:51698/Patient/222/_history/1\"/><content type=\"text/xml\"><Patient xmlns=\"http://hl7.org/fhir\"><identifier><use value=\"official\"/><system value=\"urn:hapitest:mrns\"/><value value=\"00001\"/></identifier><name><family value=\"OlderFamily\"/><given value=\"PatientOne\"/></name><gender><text value=\"M\"/></gender></Patient></content></entry><entry><title>Patient 222</title><id>222</id><updated>1969-12-31T19:00:30.000-05:00</updated><published>1969-12-31T19:00:10.000-05:00</published><link rel=\"self\" href=\"http://localhost:51698/Patient/222/_history/2\"/><content type=\"text/xml\"><Patient xmlns=\"http://hl7.org/fhir\"><identifier><use value=\"official\"/><system value=\"urn:hapitest:mrns\"/><value value=\"00001\"/></identifier><name><family value=\"NewerFamily\"/><given value=\"PatientOne\"/></name><gender><text value=\"M\"/></gender></Patient></content></entry></feed>";
|
||||
//@formatter:on
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_ATOM_XML + "; charset=UTF-8"));
|
||||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
|
||||
ITestClient client = ctx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
Bundle response = client.getHistoryServer();
|
||||
|
||||
assertEquals("http://foo/_history", capt.getValue().getURI().toString());
|
||||
|
||||
assertEquals(2, response.getEntries().size());
|
||||
|
||||
// Older resource
|
||||
{
|
||||
BundleEntry olderEntry = response.getEntries().get(0);
|
||||
assertEquals("222", olderEntry.getId().getValue());
|
||||
assertThat(olderEntry.getLinkSelf().getValue(), StringEndsWith.endsWith("/Patient/222/_history/1"));
|
||||
InstantDt pubExpected = new InstantDt(new Date(10000L));
|
||||
InstantDt pubActualRes = (InstantDt) olderEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.PUBLISHED);
|
||||
InstantDt pubActualBundle = olderEntry.getPublished();
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualRes.getValueAsString());
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualBundle.getValueAsString());
|
||||
InstantDt updExpected = new InstantDt(new Date(20000L));
|
||||
InstantDt updActualRes = (InstantDt) olderEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
|
||||
InstantDt updActualBundle = olderEntry.getUpdated();
|
||||
assertEquals(updExpected.getValueAsString(), updActualRes.getValueAsString());
|
||||
assertEquals(updExpected.getValueAsString(), updActualBundle.getValueAsString());
|
||||
}
|
||||
// Newer resource
|
||||
{
|
||||
BundleEntry newerEntry = response.getEntries().get(1);
|
||||
assertEquals("222", newerEntry.getId().getValue());
|
||||
assertThat(newerEntry.getLinkSelf().getValue(), StringEndsWith.endsWith("/Patient/222/_history/2"));
|
||||
InstantDt pubExpected = new InstantDt(new Date(10000L));
|
||||
InstantDt pubActualRes = (InstantDt) newerEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.PUBLISHED);
|
||||
InstantDt pubActualBundle = newerEntry.getPublished();
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualRes.getValueAsString());
|
||||
assertEquals(pubExpected.getValueAsString(), pubActualBundle.getValueAsString());
|
||||
InstantDt updExpected = new InstantDt(new Date(30000L));
|
||||
InstantDt updActualRes = (InstantDt) newerEntry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
|
||||
InstantDt updActualBundle = newerEntry.getUpdated();
|
||||
assertEquals(updExpected.getValueAsString(), updActualRes.getValueAsString());
|
||||
assertEquals(updExpected.getValueAsString(), updActualBundle.getValueAsString());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRead() throws Exception {
|
||||
|
||||
//@formatter:off
|
||||
String msg = "<Patient xmlns=\"http://hl7.org/fhir\">"
|
||||
|
@ -457,33 +380,13 @@ public class ClientTest {
|
|||
|
||||
ITestClient client = ctx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
// Patient response = client.findPatientByMrn(new IdentifierDt("urn:foo", "123"));
|
||||
Patient response = client.getPatientByVersionId(new IdDt("111"), new IdDt("999"));
|
||||
Patient response = client.getPatientById(new IdDt("111"));
|
||||
|
||||
assertEquals("http://foo/Patient/111/_history/999", capt.getValue().getURI().toString());
|
||||
assertEquals("http://foo/Patient/111", capt.getValue().getURI().toString());
|
||||
assertEquals("PRP1660", response.getIdentifier().get(0).getValue().getValue());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchByToken() throws Exception {
|
||||
|
||||
String msg = getPatientFeedWithOneResult();
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
|
||||
ITestClient client = ctx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
Patient response = client.findPatientByMrn(new IdentifierDt("urn:foo", "123"));
|
||||
|
||||
assertEquals("http://foo/Patient?identifier=urn%3Afoo%7C123", capt.getValue().getURI().toString());
|
||||
assertEquals("PRP1660", response.getIdentifier().get(0).getValue().getValue());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSearchByDateRange() throws Exception {
|
||||
|
||||
|
@ -505,10 +408,6 @@ public class ClientTest {
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testSearchByDob() throws Exception {
|
||||
|
||||
|
@ -529,7 +428,7 @@ public class ClientTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithIncludes() throws Exception {
|
||||
public void testSearchByToken() throws Exception {
|
||||
|
||||
String msg = getPatientFeedWithOneResult();
|
||||
|
||||
|
@ -540,9 +439,10 @@ public class ClientTest {
|
|||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
|
||||
ITestClient client = ctx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
client.getPatientWithIncludes(new StringDt("aaa"), Arrays.asList(new PathSpecification[] {new PathSpecification("inc1"), new PathSpecification("inc2")}));
|
||||
Patient response = client.findPatientByMrn(new IdentifierDt("urn:foo", "123"));
|
||||
|
||||
assertEquals("http://foo/Patient?withIncludes=aaa&_include=inc1&_include=inc2", capt.getValue().getURI().toString());
|
||||
assertEquals("http://foo/Patient?identifier=urn%3Afoo%7C123", capt.getValue().getURI().toString());
|
||||
assertEquals("PRP1660", response.getIdentifier().get(0).getValue().getValue());
|
||||
|
||||
}
|
||||
|
||||
|
@ -568,9 +468,9 @@ public class ClientTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testGetConformance() throws Exception {
|
||||
public void testSearchNamedQueryNoParams() throws Exception {
|
||||
|
||||
String msg = IOUtils.toString(ClientTest.class.getResourceAsStream("/example-metadata.xml"));
|
||||
String msg = getPatientFeedWithOneResult();
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||
|
@ -579,10 +479,45 @@ public class ClientTest {
|
|||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
|
||||
ITestClient client = ctx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
Conformance response = client.getServerConformanceStatement();
|
||||
client.getPatientNoParams();
|
||||
|
||||
assertEquals("http://foo/metadata", capt.getValue().getURI().toString());
|
||||
assertEquals("Health Intersections", response.getPublisher().getValue());
|
||||
assertEquals("http://foo/Patient?_query=someQueryNoParams", capt.getValue().getURI().toString());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchNamedQueryOneParam() throws Exception {
|
||||
|
||||
String msg = getPatientFeedWithOneResult();
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
|
||||
ITestClient client = ctx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
client.getPatientOneParam(new StringDt("BB"));
|
||||
|
||||
assertEquals("http://foo/Patient?_query=someQueryOneParam¶m1=BB", capt.getValue().getURI().toString());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithIncludes() throws Exception {
|
||||
|
||||
String msg = getPatientFeedWithOneResult();
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
|
||||
ITestClient client = ctx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
client.getPatientWithIncludes(new StringDt("aaa"), Arrays.asList(new PathSpecification[] { new PathSpecification("inc1"), new PathSpecification("inc2") }));
|
||||
|
||||
assertEquals("http://foo/Patient?withIncludes=aaa&_include=inc1&_include=inc2", capt.getValue().getURI().toString());
|
||||
|
||||
}
|
||||
|
||||
|
@ -619,54 +554,95 @@ public class ClientTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testSearchNamedQueryOneParam() throws Exception {
|
||||
public void testUpdate() throws Exception {
|
||||
|
||||
String msg = getPatientFeedWithOneResult();
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier("urn:foo", "123");
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
||||
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_TEXT + "; charset=UTF-8"));
|
||||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
||||
when(httpResponse.getAllHeaders()).thenReturn(toHeaderArray("Location", "http://example.com/fhir/Patient/100/_history/200"));
|
||||
|
||||
ITestClient client = ctx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
client.getPatientOneParam(new StringDt("BB"));
|
||||
MethodOutcome response = client.updatePatient(new IdDt("100"), patient);
|
||||
|
||||
assertEquals("http://foo/Patient?_query=someQueryOneParam¶m1=BB", capt.getValue().getURI().toString());
|
||||
assertEquals(HttpPut.class, capt.getValue().getClass());
|
||||
HttpPut post = (HttpPut) capt.getValue();
|
||||
assertThat(post.getURI().toASCIIString(), StringEndsWith.endsWith("/Patient/100"));
|
||||
assertThat(IOUtils.toString(post.getEntity().getContent()), StringContains.containsString("<Patient"));
|
||||
assertEquals("100", response.getId().getValue());
|
||||
assertEquals("200", response.getVersionId().getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a FHIR content type, but no content and make sure we handle this without crashing
|
||||
*/
|
||||
@Test
|
||||
public void testUpdateWithEmptyResponse() throws Exception {
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier("urn:foo", "123");
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
||||
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
||||
when(httpResponse.getAllHeaders()).thenReturn(toHeaderArray("Location", "http://example.com/fhir/Patient/100/_history/200"));
|
||||
|
||||
ITestClient client = ctx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
client.updatePatient(new IdDt("100"), new IdDt("200"), patient);
|
||||
}
|
||||
|
||||
@Test(expected = ResourceVersionConflictException.class)
|
||||
public void testUpdateWithResourceConflict() throws Exception {
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier("urn:foo", "123");
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
||||
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), Constants.STATUS_HTTP_409_CONFLICT, "Conflict"));
|
||||
|
||||
ITestClient client = ctx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
client.updatePatient(new IdDt("100"), new IdDt("200"), patient);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchNamedQueryNoParams() throws Exception {
|
||||
public void testUpdateWithVersion() throws Exception {
|
||||
|
||||
String msg = getPatientFeedWithOneResult();
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier("urn:foo", "123");
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
||||
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_TEXT + "; charset=UTF-8"));
|
||||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
||||
when(httpResponse.getAllHeaders()).thenReturn(toHeaderArray("Location", "http://example.com/fhir/Patient/100/_history/200"));
|
||||
|
||||
ITestClient client = ctx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
client.getPatientNoParams();
|
||||
|
||||
assertEquals("http://foo/Patient?_query=someQueryNoParams", capt.getValue().getURI().toString());
|
||||
MethodOutcome response = client.updatePatient(new IdDt("100"), new IdDt("200"), patient);
|
||||
|
||||
assertEquals(HttpPut.class, capt.getValue().getClass());
|
||||
HttpPut post = (HttpPut) capt.getValue();
|
||||
assertThat(post.getURI().toASCIIString(), StringEndsWith.endsWith("/Patient/100"));
|
||||
assertThat(IOUtils.toString(post.getEntity().getContent()), StringContains.containsString("<Patient"));
|
||||
assertThat(post.getFirstHeader("Content-Location").getValue(), StringEndsWith.endsWith("/Patient/100/_history/200"));
|
||||
assertEquals("100", response.getId().getValue());
|
||||
assertEquals("200", response.getVersionId().getValue());
|
||||
}
|
||||
|
||||
private String getPatientFeedWithOneResult() {
|
||||
@Test
|
||||
public void testVRead() throws Exception {
|
||||
|
||||
//@formatter:off
|
||||
String msg = "<feed xmlns=\"http://www.w3.org/2005/Atom\">\n" +
|
||||
"<title/>\n" +
|
||||
"<id>d039f91a-cc3c-4013-988e-af4d8d0614bd</id>\n" +
|
||||
"<os:totalResults xmlns:os=\"http://a9.com/-/spec/opensearch/1.1/\">1</os:totalResults>\n" +
|
||||
"<published>2014-03-11T16:35:07-04:00</published>\n" +
|
||||
"<author>\n" +
|
||||
"<name>ca.uhn.fhir.rest.server.DummyRestfulServer</name>\n" +
|
||||
"</author>\n" +
|
||||
"<entry>\n" +
|
||||
"<content type=\"text/xml\">"
|
||||
+ "<Patient xmlns=\"http://hl7.org/fhir\">"
|
||||
String msg = "<Patient xmlns=\"http://hl7.org/fhir\">"
|
||||
+ "<text><status value=\"generated\" /><div xmlns=\"http://www.w3.org/1999/xhtml\">John Cardinal: 444333333 </div></text>"
|
||||
+ "<identifier><label value=\"SSN\" /><system value=\"http://orionhealth.com/mrn\" /><value value=\"PRP1660\" /></identifier>"
|
||||
+ "<name><use value=\"official\" /><family value=\"Cardinal\" /><given value=\"John\" /></name>"
|
||||
|
@ -674,11 +650,25 @@ public class ClientTest {
|
|||
+ "<telecom><system value=\"phone\" /><value value=\"555-555-2004\" /><use value=\"work\" /></telecom>"
|
||||
+ "<gender><coding><system value=\"http://hl7.org/fhir/v3/AdministrativeGender\" /><code value=\"M\" /></coding></gender>"
|
||||
+ "<address><use value=\"home\" /><line value=\"2222 Home Street\" /></address><active value=\"true\" />"
|
||||
+ "</Patient>"
|
||||
+ "</content>\n"
|
||||
+ " </entry>\n"
|
||||
+ "</feed>";
|
||||
+ "</Patient>";
|
||||
//@formatter:on
|
||||
return msg;
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
|
||||
ITestClient client = ctx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
// Patient response = client.findPatientByMrn(new IdentifierDt("urn:foo", "123"));
|
||||
Patient response = client.getPatientByVersionId(new IdDt("111"), new IdDt("999"));
|
||||
|
||||
assertEquals("http://foo/Patient/111/_history/999", capt.getValue().getURI().toString());
|
||||
assertEquals("PRP1660", response.getIdentifier().get(0).getValue().getValue());
|
||||
|
||||
}
|
||||
|
||||
private Header[] toHeaderArray(String theName, String theValue) {
|
||||
return new Header[] { new BasicHeader(theName, theValue) };
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,20 @@ public class ServerInvalidDefinitionTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrivateResourceProvider() {
|
||||
RestfulServer srv = new RestfulServer();
|
||||
srv.setResourceProviders(new PrivateResourceProvider());
|
||||
|
||||
try {
|
||||
srv.init();
|
||||
fail();
|
||||
} catch (ServletException e) {
|
||||
assertThat(e.getCause().toString(), StringContains.containsString("ConfigurationException"));
|
||||
assertThat(e.getCause().toString(), StringContains.containsString("public"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Normal, should initialize properly
|
||||
*/
|
||||
|
@ -40,8 +54,23 @@ public class ServerInvalidDefinitionTest {
|
|||
srv.init();
|
||||
}
|
||||
|
||||
private static class PrivateResourceProvider implements IResourceProvider
|
||||
{
|
||||
|
||||
private static class NonInstantiableTypeForResourceProvider implements IResourceProvider
|
||||
@Override
|
||||
public Class<? extends IResource> getResourceType() {
|
||||
return Patient.class;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Read
|
||||
public Patient read(@IdParam IdDt theId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class NonInstantiableTypeForResourceProvider implements IResourceProvider
|
||||
{
|
||||
|
||||
@Override
|
||||
|
@ -57,7 +86,7 @@ public class ServerInvalidDefinitionTest {
|
|||
|
||||
}
|
||||
|
||||
private static class InstantiableTypeForResourceProvider implements IResourceProvider
|
||||
public static class InstantiableTypeForResourceProvider implements IResourceProvider
|
||||
{
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Reference in New Issue