Continue refactor for HAPI 3

This commit is contained in:
James Agnew 2017-07-03 22:10:59 -04:00
parent 9281ccafc3
commit f1d2ee9092
42 changed files with 773 additions and 1164 deletions

View File

@ -1,5 +1,7 @@
package ca.uhn.fhir.rest.client.api;
import java.util.List;
/*
* #%L
* HAPI FHIR - Core Library
@ -20,7 +22,6 @@ package ca.uhn.fhir.rest.client.api;
* #L%
*/
import org.hl7.fhir.instance.model.api.IBaseResource;
import ca.uhn.fhir.context.FhirContext;
@ -34,12 +35,20 @@ public interface IRestfulClient {
* method could be used as a low level implementation of a read/vread/search
* operation.
*
* @param theResourceType The resource type to parse
* @param theUrl The URL to load
* @param theResourceType
* The resource type to parse
* @param theUrl
* The URL to load
* @return The parsed resource
*/
<T extends IBaseResource> T fetchResourceFromUrl(Class<T> theResourceType, String theUrl);
/**
* Returns the encoding that will be used on requests. Default is <code>null</code>, which means the client will not
* explicitly request an encoding. (This is standard behaviour according to the FHIR specification)
*/
EncodingEnum getEncoding();
/**
* Returns the FHIR context associated with this client
*/
@ -51,6 +60,11 @@ public interface IRestfulClient {
*/
IHttpClient getHttpClient();
/**
* Returns the client interceptors that have been registered with this client
*/
List<IClientInterceptor> getInterceptors();
/**
* Base URL for the server, with no trailing "/"
*/
@ -68,7 +82,8 @@ public interface IRestfulClient {
* to GET methods (read/search/etc), and will add an appropriate header for
* write methods.
*
* @param theEncoding The encoding to use in the request, or <code>null</code> not specify
* @param theEncoding
* The encoding to use in the request, or <code>null</code> not specify
* an encoding (which generally implies the use of XML). The default is <code>null</code>.
*/
void setEncoding(EncodingEnum theEncoding);
@ -78,7 +93,8 @@ public interface IRestfulClient {
* enabled. Note that this is a non-standard parameter, not all servers will
* support it.
*
* @param thePrettyPrint The pretty print flag to use in the request (default is <code>false</code>)
* @param thePrettyPrint
* The pretty print flag to use in the request (default is <code>false</code>)
*/
void setPrettyPrint(Boolean thePrettyPrint);

View File

@ -25,7 +25,6 @@ import java.util.Map;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.rest.api.RequestTypeEnum;
import ca.uhn.fhir.rest.client.api.*;
public interface IRestfulClientFactory {

View File

@ -1,5 +1,7 @@
package ca.uhn.fhir.rest.param;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
/*
* #%L
* HAPI FHIR - Core Library
@ -19,14 +21,15 @@ package ca.uhn.fhir.rest.param;
* limitations under the License.
* #L%
*/
import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.hl7.fhir.instance.model.api.IIdType;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.IntegerDt;
import ca.uhn.fhir.rest.annotation.*;
import ca.uhn.fhir.util.UrlUtil;
public class ParameterUtil {
@ -45,17 +48,96 @@ public class ParameterUtil {
// return findParamIndex(theMethod, Since.class);
// }
public static int nonEscapedIndexOf(String theString, char theCharacter) {
for (int i = 0; i < theString.length(); i++) {
if (theString.charAt(i) == theCharacter) {
if (i == 0 || theString.charAt(i - 1) != '\\') {
return i;
/**
* Escapes a string according to the rules for parameter escaping specified in the <a href="http://www.hl7.org/implement/standards/fhir/search.html#escaping">FHIR Specification Escaping
* Section</a>
*/
public static String escape(String theValue) {
if (theValue == null) {
return null;
}
StringBuilder b = new StringBuilder();
for (int i = 0; i < theValue.length(); i++) {
char next = theValue.charAt(i);
switch (next) {
case '$':
case ',':
case '|':
case '\\':
b.append('\\');
break;
default:
break;
}
}
return -1;
b.append(next);
}
return b.toString();
}
/**
* Escapes a string according to the rules for parameter escaping specified in the <a href="http://www.hl7.org/implement/standards/fhir/search.html#escaping">FHIR Specification Escaping
* Section</a>
*/
public static String escapeAndUrlEncode(String theValue) {
if (theValue == null) {
return null;
}
String escaped = escape(theValue);
return UrlUtil.escape(escaped);
}
/**
* Escapes a string according to the rules for parameter escaping specified in the <a href="http://www.hl7.org/implement/standards/fhir/search.html#escaping">FHIR Specification Escaping
* Section</a>
*/
public static String escapeWithDefault(Object theValue) {
if (theValue == null) {
return "";
}
return escape(theValue.toString());
}
public static Integer findIdParameterIndex(Method theMethod, FhirContext theContext) {
Integer index = findParamAnnotationIndex(theMethod, IdParam.class);
if (index != null) {
Class<?> paramType = theMethod.getParameterTypes()[index];
if (IIdType.class.equals(paramType)) {
return index;
}
boolean isRi = theContext.getVersion().getVersion().isRi();
boolean usesHapiId = IdDt.class.equals(paramType);
if (isRi == usesHapiId) {
throw new ConfigurationException("Method uses the wrong Id datatype (IdDt / IdType) for the given context FHIR version: " + theMethod.toString());
}
}
return index;
}
public static Integer findParamAnnotationIndex(Method theMethod, Class<?> toFind) {
int paramIndex = 0;
for (Annotation[] annotations : theMethod.getParameterAnnotations()) {
for (int annotationIndex = 0; annotationIndex < annotations.length; annotationIndex++) {
Annotation nextAnnotation = annotations[annotationIndex];
Class<? extends Annotation> class1 = nextAnnotation.getClass();
if (toFind.isAssignableFrom(class1)) {
return paramIndex;
}
}
paramIndex++;
}
return null;
}
public static Integer findTagListParameterIndex(Method theMethod) {
return findParamAnnotationIndex(theMethod, TagListParam.class);
}
public static Integer findVersionIdParameterIndex(Method theMethod) {
return findParamAnnotationIndex(theMethod, VersionIdParam.class);
}
public static Object fromInteger(Class<?> theType, IntegerDt theArgument) {
if (theType.equals(IntegerDt.class)) {
@ -77,15 +159,15 @@ public class ParameterUtil {
return BINDABLE_INTEGER_TYPES;
}
public static IntegerDt toInteger(Object theArgument) {
if (theArgument instanceof IntegerDt) {
return (IntegerDt) theArgument;
public static int nonEscapedIndexOf(String theString, char theCharacter) {
for (int i = 0; i < theString.length(); i++) {
if (theString.charAt(i) == theCharacter) {
if (i == 0 || theString.charAt(i - 1) != '\\') {
return i;
}
if (theArgument instanceof Integer) {
return new IntegerDt((Integer) theArgument);
}
return null;
}
return -1;
}
static List<String> splitParameterString(String theInput, boolean theUnescapeComponents) {
@ -132,57 +214,15 @@ public class ParameterUtil {
return retVal;
}
/**
* Escapes a string according to the rules for parameter escaping specified in the <a href="http://www.hl7.org/implement/standards/fhir/search.html#escaping">FHIR Specification Escaping
* Section</a>
*/
public static String escapeWithDefault(Object theValue) {
if (theValue == null) {
return "";
public static IntegerDt toInteger(Object theArgument) {
if (theArgument instanceof IntegerDt) {
return (IntegerDt) theArgument;
}
return escape(theValue.toString());
if (theArgument instanceof Integer) {
return new IntegerDt((Integer) theArgument);
}
/**
* Escapes a string according to the rules for parameter escaping specified in the <a href="http://www.hl7.org/implement/standards/fhir/search.html#escaping">FHIR Specification Escaping
* Section</a>
*/
public static String escape(String theValue) {
if (theValue == null) {
return null;
}
StringBuilder b = new StringBuilder();
for (int i = 0; i < theValue.length(); i++) {
char next = theValue.charAt(i);
switch (next) {
case '$':
case ',':
case '|':
case '\\':
b.append('\\');
break;
default:
break;
}
b.append(next);
}
return b.toString();
}
/**
* Escapes a string according to the rules for parameter escaping specified in the <a href="http://www.hl7.org/implement/standards/fhir/search.html#escaping">FHIR Specification Escaping
* Section</a>
*/
public static String escapeAndUrlEncode(String theValue) {
if (theValue == null) {
return null;
}
String escaped = escape(theValue);
return UrlUtil.escape(escaped);
}
/**
* Unescapes a string according to the rules for parameter escaping specified in the <a href="http://www.hl7.org/implement/standards/fhir/search.html#escaping">FHIR Specification Escaping

View File

@ -21,29 +21,20 @@ package ca.uhn.fhir.rest.client.apache;
*/
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.Map.Entry;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpOptions;
import org.apache.http.client.methods.HttpPatch;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.methods.*;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.message.BasicNameValuePair;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.RequestTypeEnum;
import ca.uhn.fhir.rest.client.api.Header;
import ca.uhn.fhir.rest.client.api.IHttpClient;
import ca.uhn.fhir.rest.client.api.IHttpRequest;
import ca.uhn.fhir.rest.client.api.*;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
/**

View File

@ -19,26 +19,16 @@ package ca.uhn.fhir.rest.client.apache;
* limitations under the License.
* #L%
*/
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.io.*;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import org.apache.commons.io.IOUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.*;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.entity.ContentType;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.client.api.IHttpResponse;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;

View File

@ -26,13 +26,13 @@ import java.util.Map;
import org.hl7.fhir.instance.model.api.IBaseBinary;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.api.EncodingEnum;
import ca.uhn.fhir.rest.api.RequestTypeEnum;
import ca.uhn.fhir.rest.api.*;
import ca.uhn.fhir.rest.client.api.Header;
import ca.uhn.fhir.rest.client.api.HttpClientUtil;
import ca.uhn.fhir.rest.client.api.IHttpClient;
import ca.uhn.fhir.rest.client.api.IHttpRequest;
import ca.uhn.fhir.rest.client.impl.BaseHttpClientInvocation;
import ca.uhn.fhir.rest.client.method.MethodUtil;
public abstract class BaseHttpClient implements IHttpClient {
@ -81,7 +81,7 @@ public abstract class BaseHttpClient implements IHttpClient {
addHeaderIfNoneExist(theHttpRequest);
RestfulServerUtils.addAcceptHeaderToRequest(theEncoding, theHttpRequest, theContext);
MethodUtil.addAcceptHeaderToRequest(theEncoding, theHttpRequest, theContext);
}
@Override

View File

@ -29,9 +29,8 @@ import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.ByteArrayEntity;
import ca.uhn.fhir.rest.client.api.IClientInterceptor;
import ca.uhn.fhir.rest.client.api.IHttpRequest;
import ca.uhn.fhir.rest.client.api.IHttpResponse;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.client.api.*;
/**
* Client interceptor which GZip compresses outgoing (POST/PUT) contents being uploaded

View File

@ -142,10 +142,7 @@ public abstract class BaseClient implements IRestfulClient {
myFactory.validateServerBase(myUrlBase, myClient, this);
}
/**
* Returns the encoding that will be used on requests. Default is <code>null</code>, which means the client will not
* explicitly request an encoding. (This is standard behaviour according to the FHIR specification)
*/
@Override
public EncodingEnum getEncoding() {
return myEncoding;
}
@ -158,6 +155,10 @@ public abstract class BaseClient implements IRestfulClient {
return myClient;
}
/**
* {@inheritDoc}
*/
@Override
public List<IClientInterceptor> getInterceptors() {
return Collections.unmodifiableList(myInterceptors);
}
@ -352,12 +353,7 @@ public abstract class BaseClient implements IRestfulClient {
throw new FhirClientConnectionException(e);
} catch (IOException e) {
String msg;
if ( httpRequest != null ) {
msg = getFhirContext().getLocalizer().getMessage(BaseClient.class, "failedToParseResponse", httpRequest.getHttpVerbName(), httpRequest.getUri(), e.toString());
}
else {
msg = getFhirContext().getLocalizer().getMessage(BaseClient.class, "failedToParseResponse", "UNKNOWN", "UNKNOWN", e.toString());
}
throw new FhirClientConnectionException(msg, e);
} catch (RuntimeException e) {
throw e;

View File

@ -19,29 +19,30 @@ package ca.uhn.fhir.rest.client.impl;
* limitations under the License.
* #L%
*/
import java.lang.reflect.*;
import java.util.*;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.client.api.IGenericClient;
import ca.uhn.fhir.rest.client.api.IHttpClient;
import ca.uhn.fhir.rest.client.api.IRestfulClient;
import ca.uhn.fhir.rest.client.api.IRestfulClientFactory;
import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum;
import ca.uhn.fhir.context.*;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.client.api.*;
import ca.uhn.fhir.rest.client.exceptions.FhirClientConnectionException;
import ca.uhn.fhir.rest.client.exceptions.FhirClientInappropriateForServerException;
import ca.uhn.fhir.rest.client.method.BaseMethodBinding;
import ca.uhn.fhir.util.FhirTerser;
/**
* Base class for a REST client factory implementation
*/
public abstract class RestfulClientFactory implements IRestfulClientFactory {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RestfulClientFactory.class);
private Set<String> myValidatedServerBaseUrls = Collections.synchronizedSet(new HashSet<String>());
private int myConnectionRequestTimeout = DEFAULT_CONNECTION_REQUEST_TIMEOUT;
private int myConnectTimeout = DEFAULT_CONNECT_TIMEOUT;
private FhirContext myContext;
@ -257,6 +258,102 @@ public abstract class RestfulClientFactory implements IRestfulClientFactory {
setServerValidationMode(theServerValidationMode);
}
@Override
public void validateServerBaseIfConfiguredToDoSo(String theServerBase, IHttpClient theHttpClient, IRestfulClient theClient) {
String serverBase = normalizeBaseUrlForMap(theServerBase);
switch (getServerValidationMode()) {
case NEVER:
break;
case ONCE:
if (!myValidatedServerBaseUrls.contains(serverBase)) {
validateServerBase(serverBase, theHttpClient, theClient);
}
break;
}
}
@SuppressWarnings("unchecked")
@Override
public void validateServerBase(String theServerBase, IHttpClient theHttpClient, IRestfulClient theClient) {
GenericClient client = new GenericClient(myContext, theHttpClient, theServerBase, this);
client.setEncoding(theClient.getEncoding());
for (IClientInterceptor interceptor : theClient.getInterceptors()) {
client.registerInterceptor(interceptor);
}
client.setDontValidateConformance(true);
IBaseResource conformance;
try {
String capabilityStatementResourceName = "CapabilityStatement";
if (myContext.getVersion().getVersion().isOlderThan(FhirVersionEnum.DSTU3)) {
capabilityStatementResourceName = "Conformance";
}
@SuppressWarnings("rawtypes")
Class implementingClass;
try {
implementingClass = myContext.getResourceDefinition(capabilityStatementResourceName).getImplementingClass();
} catch (DataFormatException e) {
if (!myContext.getVersion().getVersion().isOlderThan(FhirVersionEnum.DSTU3)) {
capabilityStatementResourceName = "Conformance";
implementingClass = myContext.getResourceDefinition(capabilityStatementResourceName).getImplementingClass();
} else {
throw e;
}
}
try {
conformance = (IBaseResource) client.fetchConformance().ofType(implementingClass).execute();
} catch (FhirClientConnectionException e) {
if (!myContext.getVersion().getVersion().isOlderThan(FhirVersionEnum.DSTU3) && e.getCause() instanceof DataFormatException) {
capabilityStatementResourceName = "Conformance";
implementingClass = myContext.getResourceDefinition(capabilityStatementResourceName).getImplementingClass();
conformance = (IBaseResource) client.fetchConformance().ofType(implementingClass).execute();
} else {
throw e;
}
}
} catch (FhirClientConnectionException e) {
String msg = myContext.getLocalizer().getMessage(RestfulClientFactory.class, "failedToRetrieveConformance", theServerBase + Constants.URL_TOKEN_METADATA);
throw new FhirClientConnectionException(msg, e);
}
FhirTerser t = myContext.newTerser();
String serverFhirVersionString = null;
Object value = t.getSingleValueOrNull(conformance, "fhirVersion");
if (value instanceof IPrimitiveType) {
serverFhirVersionString = IPrimitiveType.class.cast(value).getValueAsString();
}
FhirVersionEnum serverFhirVersionEnum = null;
if (StringUtils.isBlank(serverFhirVersionString)) {
// we'll be lenient and accept this
} else {
//FIXME null access on serverFhirVersionString
if (serverFhirVersionString.startsWith("0.80") || serverFhirVersionString.startsWith("0.0.8")) {
serverFhirVersionEnum = FhirVersionEnum.DSTU1;
} else if (serverFhirVersionString.startsWith("0.4")) {
serverFhirVersionEnum = FhirVersionEnum.DSTU2;
} else if (serverFhirVersionString.startsWith("0.5")) {
serverFhirVersionEnum = FhirVersionEnum.DSTU2;
} else {
// we'll be lenient and accept this
ourLog.debug("Server conformance statement indicates unknown FHIR version: {}", serverFhirVersionString);
}
}
if (serverFhirVersionEnum != null) {
FhirVersionEnum contextFhirVersion = myContext.getVersion().getVersion();
if (!contextFhirVersion.isEquivalentTo(serverFhirVersionEnum)) {
throw new FhirClientInappropriateForServerException(myContext.getLocalizer().getMessage(RestfulClientFactory.class, "wrongVersionInConformance", theServerBase + Constants.URL_TOKEN_METADATA, serverFhirVersionString, serverFhirVersionEnum, contextFhirVersion));
}
}
myValidatedServerBaseUrls.add(normalizeBaseUrlForMap(theServerBase));
}
/**
* Get the http client for the given server base
* @param theServerBase the server base

View File

@ -26,9 +26,8 @@ import java.io.UnsupportedEncodingException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import ca.uhn.fhir.rest.client.api.IClientInterceptor;
import ca.uhn.fhir.rest.client.api.IHttpRequest;
import ca.uhn.fhir.rest.client.api.IHttpResponse;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.client.api.*;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
/**

View File

@ -22,9 +22,8 @@ package ca.uhn.fhir.rest.client.interceptor;
import org.apache.commons.lang3.Validate;
import ca.uhn.fhir.rest.client.api.IClientInterceptor;
import ca.uhn.fhir.rest.client.api.IHttpRequest;
import ca.uhn.fhir.rest.client.api.IHttpResponse;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.client.api.*;
import ca.uhn.fhir.util.CoverageIgnore;
/**

View File

@ -1,8 +1,7 @@
package ca.uhn.fhir.rest.client.interceptor;
import ca.uhn.fhir.rest.client.api.IClientInterceptor;
import ca.uhn.fhir.rest.client.api.IHttpRequest;
import ca.uhn.fhir.rest.client.api.IHttpResponse;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.client.api.*;
/**
* HTTP interceptor to be used for adding Cookie to requests.

View File

@ -17,10 +17,7 @@ import ca.uhn.fhir.rest.annotation.TagListParam;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.client.impl.BaseHttpClientInvocation;
import ca.uhn.fhir.rest.param.IParameter;
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.*;
abstract class BaseAddOrDeleteTagsMethodBinding extends BaseMethodBinding<Void> {

View File

@ -3,54 +3,21 @@ package ca.uhn.fhir.rest.client.method;
import java.io.IOException;
import java.io.Reader;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.*;
import org.apache.commons.io.IOUtils;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IBaseResource;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.context.*;
import ca.uhn.fhir.model.api.*;
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.annotation.AddTags;
import ca.uhn.fhir.rest.annotation.Create;
import ca.uhn.fhir.rest.annotation.Delete;
import ca.uhn.fhir.rest.annotation.DeleteTags;
import ca.uhn.fhir.rest.annotation.GetPage;
import ca.uhn.fhir.rest.annotation.GetTags;
import ca.uhn.fhir.rest.annotation.History;
import ca.uhn.fhir.rest.annotation.Metadata;
import ca.uhn.fhir.rest.annotation.Operation;
import ca.uhn.fhir.rest.annotation.Patch;
import ca.uhn.fhir.rest.annotation.Read;
import ca.uhn.fhir.rest.annotation.Search;
import ca.uhn.fhir.rest.annotation.Transaction;
import ca.uhn.fhir.rest.annotation.Update;
import ca.uhn.fhir.rest.annotation.Validate;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.EncodingEnum;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.annotation.*;
import ca.uhn.fhir.rest.api.*;
import ca.uhn.fhir.rest.client.exceptions.NonFhirResponseException;
import ca.uhn.fhir.rest.client.impl.BaseHttpClientInvocation;
import ca.uhn.fhir.rest.param.IParameter;
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
import ca.uhn.fhir.rest.server.exceptions.UnclassifiedServerFailureException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.rest.server.exceptions.*;
import ca.uhn.fhir.util.ReflectionUtil;
public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T> {

View File

@ -24,14 +24,9 @@ import java.lang.reflect.Method;
import org.hl7.fhir.instance.model.api.IBaseResource;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.rest.annotation.Delete;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.context.*;
//TODO Use of a deprecated method should be resolved
import ca.uhn.fhir.rest.annotation.VersionIdParam;
import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.annotation.*;
public abstract class BaseOutcomeReturningMethodBindingWithResourceIdButNoResourceBody extends BaseOutcomeReturningMethodBinding {
@ -45,15 +40,10 @@ public abstract class BaseOutcomeReturningMethodBindingWithResourceIdButNoResour
if (resourceType != IBaseResource.class) {
RuntimeResourceDefinition def = theContext.getResourceDefinition(resourceType);
myResourceName = def.getName();
} else {
if (theProvider != null && theProvider instanceof IResourceProvider) {
RuntimeResourceDefinition def = theContext.getResourceDefinition(((IResourceProvider) theProvider).getResourceType());
myResourceName = def.getName();
} else {
throw new ConfigurationException(
"Can not determine resource type for method '" + theMethod.getName() + "' on type " + theMethod.getDeclaringClass().getCanonicalName() + " - Did you forget to include the resourceType() value on the @" + Delete.class.getSimpleName() + " method annotation?");
}
}
myIdParameterIndex = MethodUtil.findIdParameterIndex(theMethod, getContext());
if (myIdParameterIndex == null) {

View File

@ -1,7 +1,5 @@
package ca.uhn.fhir.rest.client.method;
import static org.apache.commons.lang3.StringUtils.defaultIfBlank;
/*
* #%L
* HAPI FHIR - Core Library
@ -23,32 +21,21 @@ import static org.apache.commons.lang3.StringUtils.defaultIfBlank;
*/
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.rest.annotation.ResourceParam;
import ca.uhn.fhir.rest.client.impl.BaseHttpClientInvocation;
import ca.uhn.fhir.rest.param.IParameter;
import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
import ca.uhn.fhir.rest.server.method.ResourceParameter;
abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends BaseOutcomeReturningMethodBinding {
private Integer myIdParamIndex;
private String myResourceName;
private int myResourceParameterIndex = -1;
private Class<? extends IBaseResource> myResourceType;
private Class<? extends IIdType> myIdParamType;
private int myConditionalUrlIndex = -1;
@SuppressWarnings("unchecked")
public BaseOutcomeReturningMethodBindingWithResourceParam(Method theMethod, FhirContext theContext, Class<?> theMethodAnnotation, Object theProvider) {
super(theMethod, theContext, theMethodAnnotation, theProvider);
@ -58,9 +45,6 @@ abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends BaseOu
for (IParameter next : getParameters()) {
if (next instanceof ResourceParameter) {
resourceParameter = (ResourceParameter) next;
if (resourceParameter.getMode() != ResourceParameter.Mode.RESOURCE) {
continue;
}
if (myResourceType != null) {
throw new ConfigurationException("Method " + theMethod.getName() + " on type " + theMethod.getDeclaringClass() + " has more than one @ResourceParam. Only one is allowed.");
}
@ -68,24 +52,15 @@ abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends BaseOu
myResourceType = resourceParameter.getResourceType();
myResourceParameterIndex = index;
} else if (next instanceof ConditionalParamBinder) {
myConditionalUrlIndex = index;
}
index++;
}
if ((myResourceType == null || Modifier.isAbstract(myResourceType.getModifiers())) && (theProvider instanceof IResourceProvider)) {
myResourceType = ((IResourceProvider) theProvider).getResourceType();
}
if (myResourceType == null) {
throw new ConfigurationException("Unable to determine resource type for method: " + theMethod);
}
myResourceName = theContext.getResourceDefinition(myResourceType).getName();
myIdParamIndex = MethodUtil.findIdParameterIndex(theMethod, getContext());
if (myIdParamIndex != null) {
myIdParamType = (Class<? extends IIdType>) theMethod.getParameterTypes()[myIdParamIndex];
}
if (resourceParameter == null) {
throw new ConfigurationException("Method " + theMethod.getName() + " in type " + theMethod.getDeclaringClass().getCanonicalName() + " does not have a resource parameter annotated with @" + ResourceParam.class.getSimpleName());
@ -93,31 +68,6 @@ abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends BaseOu
}
@Override
protected void addParametersForServerRequest(RequestDetails theRequest, Object[] theParams) {
if (myIdParamIndex != null) {
theParams[myIdParamIndex] = MethodUtil.convertIdToType(theRequest.getId(), myIdParamType);
}
if (myResourceParameterIndex != -1) {
IBaseResource resource = ((IBaseResource) theParams[myResourceParameterIndex]);
String resourceId = resource.getIdElement().getIdPart();
String urlId = theRequest.getId() != null ? theRequest.getId().getIdPart() : null;
if (getContext().getVersion().getVersion() == FhirVersionEnum.DSTU1) {
resource.setId(urlId);
} else {
if (getContext().getVersion().getVersion().isOlderThan(FhirVersionEnum.DSTU3) == false) {
resource.setId(theRequest.getId());
}
String matchUrl = null;
if (myConditionalUrlIndex != -1) {
matchUrl = (String) theParams[myConditionalUrlIndex];
matchUrl = defaultIfBlank(matchUrl, null);
}
validateResourceIdAndUrlIdForNonConditionalOperation(resource, resourceId, urlId, matchUrl);
}
}
}
@Override
public String getResourceName() {
@ -135,21 +85,6 @@ abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends BaseOu
return retVal;
}
@Override
protected void populateActionRequestDetailsForInterceptor(RequestDetails theRequestDetails, ActionRequestDetails theDetails, Object[] theMethodParams) {
super.populateActionRequestDetailsForInterceptor(theRequestDetails, theDetails, theMethodParams);
/*
* If the method has no parsed resource parameter, we parse here in order to have something for the interceptor.
*/
if (myResourceParameterIndex != -1) {
theDetails.setResource((IBaseResource) theMethodParams[myResourceParameterIndex]);
} else {
theDetails.setResource(ResourceParameter.parseResourceFromRequest(theRequestDetails, this, myResourceType));
}
}
/**
* Subclasses may override
*/

View File

@ -21,9 +21,7 @@ package ca.uhn.fhir.rest.client.method;
*/
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.*;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.IBaseResource;
@ -32,18 +30,14 @@ import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.annotation.ConditionalUrlParam;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.param.IParameter;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
class ConditionalParamBinder implements IParameter {
private RestOperationTypeEnum myOperationType;
private boolean mySupportsMultiple;
ConditionalParamBinder(RestOperationTypeEnum theOperationType, boolean theSupportsMultiple) {
Validate.notNull(theOperationType, "theOperationType can not be null");
myOperationType = theOperationType;
mySupportsMultiple = theSupportsMultiple;
}
@ -63,9 +57,4 @@ class ConditionalParamBinder implements IParameter {
throw new UnsupportedOperationException("Can not use @" + getClass().getName() + " annotated parameters in client");
}
@Override
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
return theRequest.getConditionalUrl(myOperationType);
}
}

View File

@ -36,7 +36,6 @@ import ca.uhn.fhir.rest.annotation.Create;
import ca.uhn.fhir.rest.api.RequestTypeEnum;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.client.impl.BaseHttpClientInvocation;
import ca.uhn.fhir.rest.param.IParameter;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
public class CreateMethodBinding extends BaseOutcomeReturningMethodBindingWithResourceParam {

View File

@ -19,7 +19,6 @@ import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.client.impl.BaseHttpClientInvocation;
import ca.uhn.fhir.rest.param.IParameter;
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;

View File

@ -37,7 +37,6 @@ import ca.uhn.fhir.rest.annotation.History;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.client.impl.BaseHttpClientInvocation;
import ca.uhn.fhir.rest.param.IParameter;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
public class HistoryMethodBinding extends BaseResourceReturningMethodBinding {

View File

@ -19,23 +19,13 @@ package ca.uhn.fhir.rest.client.method;
* limitations under the License.
* #L%
*/
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.*;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.rest.annotation.IncludeParam;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.QualifiedParamList;
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
import ca.uhn.fhir.rest.param.BaseQueryParameter;
import ca.uhn.fhir.rest.api.*;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;

View File

@ -3,88 +3,28 @@ package ca.uhn.fhir.rest.client.method;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.io.IOException;
import java.io.PushbackReader;
import java.io.Reader;
import java.io.*;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.Map.Entry;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IBaseMetaType;
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.*;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.model.api.IQueryParameterAnd;
import ca.uhn.fhir.model.api.IQueryParameterOr;
import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.api.Tag;
import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.context.*;
import ca.uhn.fhir.model.api.*;
import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.annotation.At;
import ca.uhn.fhir.rest.annotation.ConditionalUrlParam;
import ca.uhn.fhir.rest.annotation.Count;
import ca.uhn.fhir.rest.annotation.Elements;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.IncludeParam;
import ca.uhn.fhir.rest.annotation.Operation;
import ca.uhn.fhir.rest.annotation.OperationParam;
import ca.uhn.fhir.rest.annotation.OptionalParam;
import ca.uhn.fhir.rest.annotation.RawParam;
import ca.uhn.fhir.rest.annotation.RequiredParam;
import ca.uhn.fhir.rest.annotation.ResourceParam;
import ca.uhn.fhir.rest.annotation.ServerBase;
import ca.uhn.fhir.rest.annotation.Since;
import ca.uhn.fhir.rest.annotation.Sort;
import ca.uhn.fhir.rest.annotation.TagListParam;
import ca.uhn.fhir.rest.annotation.TransactionParam;
import ca.uhn.fhir.rest.annotation.Validate;
import ca.uhn.fhir.rest.annotation.VersionIdParam;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.EncodingEnum;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.PatchTypeEnum;
import ca.uhn.fhir.rest.api.QualifiedParamList;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
import ca.uhn.fhir.rest.api.SummaryEnum;
import ca.uhn.fhir.rest.api.ValidationModeEnum;
import ca.uhn.fhir.rest.annotation.*;
import ca.uhn.fhir.rest.api.*;
import ca.uhn.fhir.rest.client.api.IHttpRequest;
import ca.uhn.fhir.rest.client.impl.BaseHttpClientInvocation;
import ca.uhn.fhir.rest.client.method.OperationParameter.IOperationParamConverter;
import ca.uhn.fhir.rest.param.CollectionBinder;
import ca.uhn.fhir.rest.param.DateAndListParam;
import ca.uhn.fhir.rest.param.HasAndListParam;
import ca.uhn.fhir.rest.param.NumberAndListParam;
import ca.uhn.fhir.rest.param.QuantityAndListParam;
import ca.uhn.fhir.rest.param.ReferenceAndListParam;
import ca.uhn.fhir.rest.param.StringAndListParam;
import ca.uhn.fhir.rest.param.TokenAndListParam;
import ca.uhn.fhir.rest.param.UriAndListParam;
import ca.uhn.fhir.util.DateUtils;
import ca.uhn.fhir.util.ParametersUtil;
import ca.uhn.fhir.util.ReflectionUtil;
import ca.uhn.fhir.util.UrlUtil;
import ca.uhn.fhir.rest.param.*;
import ca.uhn.fhir.util.*;
/*
* #%L
@ -127,7 +67,6 @@ public class MethodUtil {
// nothing
}
static void addTagsToPostOrPut(FhirContext theContext, IBaseResource resource, BaseHttpClientInvocation retVal) {
if (theContext.getVersion().getVersion().equals(FhirVersionEnum.DSTU1)) {
TagList list = (TagList) ((IResource) resource).getResourceMetadata().get(ResourceMetadataKeyEnum.TAG_LIST);
@ -141,7 +80,6 @@ public class MethodUtil {
}
}
@SuppressWarnings("unchecked")
public static <T extends IIdType> T convertIdToType(IIdType value, Class<T> theIdParamType) {
if (value != null && !theIdParamType.isAssignableFrom(value.getClass())) {
@ -194,7 +132,8 @@ public class MethodUtil {
return retVal;
}
public static HttpPostClientInvocation createCreateInvocation(IBaseResource theResource, String theResourceBody, String theId, FhirContext theContext, Map<String, List<String>> theIfNoneExistParams) {
public static HttpPostClientInvocation createCreateInvocation(IBaseResource theResource, String theResourceBody, String theId, FhirContext theContext,
Map<String, List<String>> theIfNoneExistParams) {
HttpPostClientInvocation retVal = createCreateInvocation(theResource, theResourceBody, theId, theContext);
retVal.setIfNoneExistParams(theIfNoneExistParams);
return retVal;
@ -235,7 +174,6 @@ public class MethodUtil {
return retVal;
}
public static StringBuilder createUrl(String theResourceType, Map<String, List<String>> theMatchParams) {
StringBuilder b = new StringBuilder();
@ -254,7 +192,6 @@ public class MethodUtil {
return b;
}
public static HttpPutClientInvocation createUpdateInvocation(FhirContext theContext, IBaseResource theResource, String theResourceBody, String theMatchUrl) {
HttpPutClientInvocation retVal;
if (StringUtils.isBlank(theResourceBody)) {
@ -319,46 +256,6 @@ public class MethodUtil {
}
}
public static Integer findIdParameterIndex(Method theMethod, FhirContext theContext) {
Integer index = MethodUtil.findParamAnnotationIndex(theMethod, IdParam.class);
if (index != null) {
Class<?> paramType = theMethod.getParameterTypes()[index];
if (IIdType.class.equals(paramType)) {
return index;
}
boolean isRi = theContext.getVersion().getVersion().isRi();
boolean usesHapiId = IdDt.class.equals(paramType);
if (isRi == usesHapiId) {
throw new ConfigurationException("Method uses the wrong Id datatype (IdDt / IdType) for the given context FHIR version: " + theMethod.toString());
}
}
return index;
}
@SuppressWarnings("GetClassOnAnnotation")
public static Integer findParamAnnotationIndex(Method theMethod, Class<?> toFind) {
int paramIndex = 0;
for (Annotation[] annotations : theMethod.getParameterAnnotations()) {
for (int annotationIndex = 0; annotationIndex < annotations.length; annotationIndex++) {
Annotation nextAnnotation = annotations[annotationIndex];
Class<? extends Annotation> class1 = nextAnnotation.getClass();
if (toFind.isAssignableFrom(class1)) {
return paramIndex;
}
}
paramIndex++;
}
return null;
}
public static Integer findTagListParameterIndex(Method theMethod) {
return MethodUtil.findParamAnnotationIndex(theMethod, TagListParam.class);
}
public static Integer findVersionIdParameterIndex(Method theMethod) {
return MethodUtil.findParamAnnotationIndex(theMethod, VersionIdParam.class);
}
@SuppressWarnings("unchecked")
public static List<IParameter> getResourceParameters(final FhirContext theContext, Method theMethod, Object theProvider, RestOperationTypeEnum theRestfulOperationTypeEnum) {
List<IParameter> parameters = new ArrayList<IParameter>();
@ -385,7 +282,8 @@ public class MethodUtil {
parameterType = ReflectionUtil.getGenericCollectionTypeOfMethodParameter(theMethod, paramIndex);
}
if (Collection.class.isAssignableFrom(parameterType)) {
throw new ConfigurationException("Argument #" + paramIndex + " of Method '" + theMethod.getName() + "' in type '" + theMethod.getDeclaringClass().getCanonicalName() + "' is of an invalid generic type (can not be a collection of a collection of a collection)");
throw new ConfigurationException("Argument #" + paramIndex + " of Method '" + theMethod.getName() + "' in type '" + theMethod.getDeclaringClass().getCanonicalName()
+ "' is of an invalid generic type (can not be a collection of a collection of a collection)");
}
}
@ -418,7 +316,7 @@ public class MethodUtil {
MethodUtil.extractDescription(parameter, annotations);
param = parameter;
} else if (nextAnnotation instanceof RawParam) {
param = new RawParamsParmeter(parameters);
param = new RawParamsParmeter();
} else if (nextAnnotation instanceof IncludeParam) {
Class<? extends Collection<Include>> instantiableCollectionType;
Class<?> specType;
@ -427,7 +325,8 @@ public class MethodUtil {
instantiableCollectionType = null;
specType = String.class;
} else if ((parameterType != Include.class) || innerCollectionType == null || outerCollectionType != null) {
throw new ConfigurationException("Method '" + theMethod.getName() + "' is annotated with @" + IncludeParam.class.getSimpleName() + " but has a type other than Collection<" + Include.class.getSimpleName() + ">");
throw new ConfigurationException("Method '" + theMethod.getName() + "' is annotated with @" + IncludeParam.class.getSimpleName() + " but has a type other than Collection<"
+ Include.class.getSimpleName() + ">");
} else {
instantiableCollectionType = (Class<? extends Collection<Include>>) CollectionBinder.getInstantiableCollectionType(innerCollectionType, "Method '" + theMethod.getName() + "'");
specType = parameterType;
@ -454,7 +353,7 @@ public class MethodUtil {
b.append(" or String or byte[]");
throw new ConfigurationException(b.toString());
}
param = new ResourceParameter();
param = new ResourceParameter(parameterType);
} else if (nextAnnotation instanceof IdParam || nextAnnotation instanceof VersionIdParam) {
param = new NullParameter();
} else if (nextAnnotation instanceof ServerBase) {
@ -480,7 +379,8 @@ public class MethodUtil {
param = new OperationParameter(theContext, op.name(), ((OperationParam) nextAnnotation));
} else if (nextAnnotation instanceof Validate.Mode) {
if (parameterType.equals(ValidationModeEnum.class) == false) {
throw new ConfigurationException("Parameter annotated with @" + Validate.class.getSimpleName() + "." + Validate.Mode.class.getSimpleName() + " must be of type " + ValidationModeEnum.class.getName());
throw new ConfigurationException(
"Parameter annotated with @" + Validate.class.getSimpleName() + "." + Validate.Mode.class.getSimpleName() + " must be of type " + ValidationModeEnum.class.getName());
}
param = new OperationParameter(theContext, Constants.EXTOP_VALIDATE, Constants.EXTOP_VALIDATE_MODE, 0, 1).setConverter(new IOperationParamConverter() {
@Override
@ -502,7 +402,8 @@ public class MethodUtil {
});
} else if (nextAnnotation instanceof Validate.Profile) {
if (parameterType.equals(String.class) == false) {
throw new ConfigurationException("Parameter annotated with @" + Validate.class.getSimpleName() + "." + Validate.Profile.class.getSimpleName() + " must be of type " + String.class.getName());
throw new ConfigurationException(
"Parameter annotated with @" + Validate.class.getSimpleName() + "." + Validate.Profile.class.getSimpleName() + " must be of type " + String.class.getName());
}
param = new OperationParameter(theContext, Constants.EXTOP_VALIDATE, Constants.EXTOP_VALIDATE_PROFILE, 0, 1).setConverter(new IOperationParamConverter() {
@Override
@ -524,7 +425,8 @@ public class MethodUtil {
}
if (param == null) {
throw new ConfigurationException("Parameter #" + ((paramIndex + 1)) + "/" + (parameterTypes.length) + " of method '" + theMethod.getName() + "' on type '" + theMethod.getDeclaringClass().getCanonicalName()
throw new ConfigurationException(
"Parameter #" + ((paramIndex + 1)) + "/" + (parameterTypes.length) + " of method '" + theMethod.getName() + "' on type '" + theMethod.getDeclaringClass().getCanonicalName()
+ "' has no recognized FHIR interface parameter annotations. Don't know how to handle this parameter");
}
@ -644,7 +546,6 @@ public class MethodUtil {
return parseQueryParams(theContext, paramType, theUnqualifiedParamName, theParameters);
}
/**
* This is a utility method intended provided to help the JPA module.
*/
@ -832,4 +733,27 @@ public class MethodUtil {
};
}
public static void addAcceptHeaderToRequest(EncodingEnum theEncoding, IHttpRequest theHttpRequest, FhirContext theContext) {
if (theEncoding == null) {
if (theContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU2_1) == false) {
theHttpRequest.addHeader(Constants.HEADER_ACCEPT, Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON_LEGACY);
} else {
theHttpRequest.addHeader(Constants.HEADER_ACCEPT, Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON_NON_LEGACY);
}
} else if (theEncoding == EncodingEnum.JSON) {
if (theContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU2_1) == false) {
theHttpRequest.addHeader(Constants.HEADER_ACCEPT, Constants.CT_FHIR_JSON);
} else {
theHttpRequest.addHeader(Constants.HEADER_ACCEPT, Constants.HEADER_ACCEPT_VALUE_JSON_NON_LEGACY);
}
} else if (theEncoding == EncodingEnum.XML) {
if (theContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU2_1) == false) {
theHttpRequest.addHeader(Constants.HEADER_ACCEPT, Constants.CT_FHIR_XML);
} else {
theHttpRequest.addHeader(Constants.HEADER_ACCEPT, Constants.HEADER_ACCEPT_VALUE_XML_NON_LEGACY);
}
}
}
}

View File

@ -21,16 +21,12 @@ package ca.uhn.fhir.rest.client.method;
*/
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.*;
import org.hl7.fhir.instance.model.api.IBaseResource;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.param.IParameter;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
class NullParameter implements IParameter {
@ -39,12 +35,6 @@ class NullParameter implements IParameter {
//nothing
}
@Override
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
// nothing
return null;
}
@Override
public void initializeTypes(Method theMethod, Class<? extends Collection<?>> theOuterCollectionType, Class<? extends Collection<?>> theInnerCollectionType, Class<?> theParameterType) {
// nothing

View File

@ -22,12 +22,7 @@ package ca.uhn.fhir.rest.client.method;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import java.util.*;
import org.hl7.fhir.instance.model.api.IIdType;
@ -36,11 +31,8 @@ import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.rest.annotation.Patch;
import ca.uhn.fhir.rest.annotation.ResourceParam;
import ca.uhn.fhir.rest.api.PatchTypeEnum;
import ca.uhn.fhir.rest.api.RequestTypeEnum;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.api.*;
import ca.uhn.fhir.rest.client.impl.BaseHttpClientInvocation;
import ca.uhn.fhir.rest.param.IParameter;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
@ -78,15 +70,6 @@ public class PatchMethodBinding extends BaseOutcomeReturningMethodBindingWithRes
}
}
@Override
public boolean incomingServerRequestMatchesMethod(RequestDetails theRequest) {
boolean retVal = super.incomingServerRequestMatchesMethod(theRequest);
if (retVal) {
PatchTypeParameter.getTypeForRequestOrThrowInvalidRequestException(theRequest);
}
return retVal;
}
@Override
public RestOperationTypeEnum getRestOperationType() {
return RestOperationTypeEnum.PATCH;
@ -146,13 +129,6 @@ public class PatchMethodBinding extends BaseOutcomeReturningMethodBindingWithRes
return retVal;
}
@Override
protected void addParametersForServerRequest(RequestDetails theRequest, Object[] theParams) {
IIdType id = theRequest.getId();
id = UpdateMethodBinding.applyETagAsVersion(theRequest, id);
theParams[getIdParameterIndex()] = id;
}
@Override
protected String getMatchingOperation() {
return null;

View File

@ -21,28 +21,19 @@ package ca.uhn.fhir.rest.client.method;
*/
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.IBaseResource;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.annotation.RawParam;
import ca.uhn.fhir.rest.param.IParameter;
import ca.uhn.fhir.rest.param.QualifierDetails;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
public class RawParamsParmeter implements IParameter {
private final List<IParameter> myAllMethodParameters;
public RawParamsParmeter(List<IParameter> theParameters) {
myAllMethodParameters = theParameters;
public RawParamsParmeter() {
super();
}
@Override
@ -51,42 +42,6 @@ public class RawParamsParmeter implements IParameter {
// not supported on client for now
}
@Override
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
HashMap<String, List<String>> retVal = null;
for (String nextName : theRequest.getParameters().keySet()) {
if (nextName.startsWith("_")) {
continue;
}
QualifierDetails qualifiers = SearchMethodBinding.extractQualifiersFromParameterName(nextName);
boolean alreadyCaptured = false;
for (IParameter nextParameter : myAllMethodParameters) {
if (nextParameter instanceof SearchParameter) {
SearchParameter nextSearchParam = (SearchParameter)nextParameter;
if (nextSearchParam.getName().equals(qualifiers.getParamName())) {
if (qualifiers.passes(nextSearchParam.getQualifierWhitelist(), nextSearchParam.getQualifierBlacklist())) {
alreadyCaptured = true;
break;
}
}
}
}
if (!alreadyCaptured) {
if (retVal == null) {
retVal = new HashMap<String, List<String>>();
}
retVal.put(nextName, Arrays.asList(theRequest.getParameters().get(nextName)));
}
}
return retVal;
}
@Override
public void initializeTypes(Method theMethod, Class<? extends Collection<?>> theOuterCollectionType, Class<? extends Collection<?>> theInnerCollectionType, Class<?> theParameterType) {
Validate.isTrue(theParameterType.equals(Map.class), "Parameter with @" + RawParam.class + " must be of type Map<String, List<String>>");

View File

@ -23,16 +23,11 @@ package ca.uhn.fhir.rest.client.method;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.*;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.IBaseBinary;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.*;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
@ -40,11 +35,8 @@ import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
import ca.uhn.fhir.rest.annotation.Elements;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.Read;
import ca.uhn.fhir.rest.annotation.*;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.param.IParameter;
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
public class ReadMethodBinding extends BaseResourceReturningMethodBinding implements IClientResponseHandlerHandlesBinary<Object> {

View File

@ -5,6 +5,7 @@ import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.IBaseResource;
import ca.uhn.fhir.context.FhirContext;
@ -12,11 +13,15 @@ import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
public class ResourceParameter implements IParameter {
private Class<? extends IBaseResource> myResourceType;
/**
* Constructor
*/
public ResourceParameter() {
super();
@SuppressWarnings("unchecked")
public ResourceParameter(Class<?> theParameterType) {
Validate.isTrue(IBaseResource.class.isAssignableFrom(theParameterType));
myResourceType = (Class<? extends IBaseResource>) theParameterType;
}
@Override
@ -37,4 +42,8 @@ public class ResourceParameter implements IParameter {
RESOURCE
}
public Class<? extends IBaseResource> getResourceType() {
return myResourceType;
}
}

View File

@ -23,10 +23,7 @@ import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.Map.Entry;
import org.apache.commons.lang3.StringUtils;
@ -38,11 +35,8 @@ import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
import ca.uhn.fhir.rest.annotation.Search;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.api.SearchStyleEnum;
import ca.uhn.fhir.rest.api.*;
import ca.uhn.fhir.rest.client.impl.BaseHttpClientInvocation;
import ca.uhn.fhir.rest.param.IParameter;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;

View File

@ -19,64 +19,20 @@ package ca.uhn.fhir.rest.client.method;
* limitations under the License.
* #L%
*/
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.*;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimePrimitiveDatatypeDefinition;
import ca.uhn.fhir.model.api.IQueryParameterAnd;
import ca.uhn.fhir.model.api.IQueryParameterOr;
import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.context.*;
import ca.uhn.fhir.model.api.*;
import ca.uhn.fhir.model.base.composite.BaseIdentifierDt;
import ca.uhn.fhir.model.base.composite.BaseQuantityDt;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.rest.annotation.OptionalParam;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.QualifiedParamList;
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
import ca.uhn.fhir.rest.param.BaseQueryParameter;
import ca.uhn.fhir.rest.param.CompositeAndListParam;
import ca.uhn.fhir.rest.param.CompositeOrListParam;
import ca.uhn.fhir.rest.param.CompositeParam;
import ca.uhn.fhir.rest.param.DateAndListParam;
import ca.uhn.fhir.rest.param.DateOrListParam;
import ca.uhn.fhir.rest.param.DateParam;
import ca.uhn.fhir.rest.param.DateRangeParam;
import ca.uhn.fhir.rest.param.HasAndListParam;
import ca.uhn.fhir.rest.param.HasOrListParam;
import ca.uhn.fhir.rest.param.HasParam;
import ca.uhn.fhir.rest.param.NumberAndListParam;
import ca.uhn.fhir.rest.param.NumberOrListParam;
import ca.uhn.fhir.rest.param.NumberParam;
import ca.uhn.fhir.rest.param.QuantityAndListParam;
import ca.uhn.fhir.rest.param.QuantityOrListParam;
import ca.uhn.fhir.rest.param.QuantityParam;
import ca.uhn.fhir.rest.param.ReferenceAndListParam;
import ca.uhn.fhir.rest.param.ReferenceOrListParam;
import ca.uhn.fhir.rest.param.ReferenceParam;
import ca.uhn.fhir.rest.param.StringAndListParam;
import ca.uhn.fhir.rest.param.StringOrListParam;
import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.rest.param.TokenAndListParam;
import ca.uhn.fhir.rest.param.TokenOrListParam;
import ca.uhn.fhir.rest.param.TokenParam;
import ca.uhn.fhir.rest.param.UriAndListParam;
import ca.uhn.fhir.rest.param.UriOrListParam;
import ca.uhn.fhir.rest.param.UriParam;
import ca.uhn.fhir.rest.api.*;
import ca.uhn.fhir.rest.param.*;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.util.CollectionUtil;
@ -205,16 +161,6 @@ public class SearchParameter extends BaseQueryParameter {
return myParamType;
}
@Override
public Set<String> getQualifierBlacklist() {
return myQualifierBlacklist;
}
@Override
public Set<String> getQualifierWhitelist() {
return myQualifierWhitelist;
}
public Class<?> getType() {
return myType;
}
@ -288,7 +234,6 @@ public class SearchParameter extends BaseQueryParameter {
@SuppressWarnings("unchecked")
public void setType(FhirContext theContext, final Class<?> type, Class<? extends Collection<?>> theInnerCollectionType, Class<? extends Collection<?>> theOuterCollectionType) {
this.myType = type;
if (IQueryParameterType.class.isAssignableFrom(type)) {
myParamBinder = new QueryParameterTypeBinder((Class<? extends IQueryParameterType>) type, myCompositeTypes);

View File

@ -21,16 +21,12 @@ package ca.uhn.fhir.rest.client.method;
*/
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.*;
import org.hl7.fhir.instance.model.api.IBaseResource;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.param.IParameter;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
class ServerBaseParamBinder implements IParameter {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ServerBaseParamBinder.class);
@ -43,11 +39,6 @@ class ServerBaseParamBinder implements IParameter {
ourLog.trace("Ignoring server base argument: {}", theSourceClientArgument);
}
@Override
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
return theRequest.getFhirServerBase();
}
@Override
public void initializeTypes(Method theMethod, Class<? extends Collection<?>> theOuterCollectionType, Class<? extends Collection<?>> theInnerCollectionType, Class<?> theParameterType) {
// ignore for now

View File

@ -1,27 +1,5 @@
package ca.uhn.fhir.rest.client.method;
/*
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 - 2017 University Health Network
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import java.util.Set;
class SinceOrAtParameter extends SearchParameter {
// private Class<?> myType;
@ -34,16 +12,6 @@ class SinceOrAtParameter extends SearchParameter {
// myAnnotationType = theAnnotationType;
}
@Override
public Set<String> getQualifierBlacklist() {
return null;
}
@Override
public Set<String> getQualifierWhitelist() {
return null;
}
// @Override
// public void translateClientArgumentIntoQueryArgument(FhirContext theContext, Object theSourceClientArgument, Map<String, List<String>> theTargetQueryArguments, IBaseResource theTargetResource) throws InternalErrorException {
// if (theSourceClientArgument != null) {

View File

@ -21,6 +21,7 @@ package ca.uhn.fhir.rest.client.method;
*/
import ca.uhn.fhir.rest.annotation.Since;
import ca.uhn.fhir.rest.api.Constants;
class SinceParameter extends SinceOrAtParameter {

View File

@ -1,26 +1,6 @@
package ca.uhn.fhir.rest.client.method;
import static org.apache.commons.lang3.StringUtils.isBlank;
/*
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 - 2017 University Health Network
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.lang.reflect.Method;
import java.util.Collections;
@ -33,11 +13,9 @@ import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.annotation.Update;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.RequestTypeEnum;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.client.impl.BaseHttpClientInvocation;
import ca.uhn.fhir.rest.param.IParameter;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
public class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithResourceParam {
@ -50,53 +28,6 @@ public class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithRe
myIdParameterIndex = MethodUtil.findIdParameterIndex(theMethod, getContext());
}
@Override
protected void addParametersForServerRequest(RequestDetails theRequest, Object[] theParams) {
/*
* We are being a bit lenient here, since technically the client is supposed to include the version in the
* Content-Location header, but we allow it in the PUT URL as well..
*/
String locationHeader = theRequest.getHeader(Constants.HEADER_CONTENT_LOCATION);
IIdType id = theRequest.getId();
if (isNotBlank(locationHeader)) {
id.setValue(locationHeader);
if (isNotBlank(id.getResourceType())) {
if (!getResourceName().equals(id.getResourceType())) {
throw new InvalidRequestException(
"Attempting to update '" + getResourceName() + "' but content-location header specifies different resource type '" + id.getResourceType() + "' - header value: " + locationHeader);
}
}
}
id = applyETagAsVersion(theRequest, id);
if (theRequest.getId() != null && theRequest.getId().hasVersionIdPart() == false) {
if (id != null && id.hasVersionIdPart()) {
theRequest.getId().setValue(id.getValue());
}
}
if (isNotBlank(locationHeader)) {
MethodOutcome mo = new MethodOutcome();
parseContentLocation(getContext(), mo, locationHeader);
if (mo.getId() == null || mo.getId().isEmpty()) {
throw new InvalidRequestException("Invalid Content-Location header for resource " + getResourceName() + ": " + locationHeader);
}
}
super.addParametersForServerRequest(theRequest, theParams);
}
public static IIdType applyETagAsVersion(RequestDetails theRequest, IIdType id) {
String ifMatchValue = theRequest.getHeader(Constants.HEADER_IF_MATCH);
if (isNotBlank(ifMatchValue)) {
ifMatchValue = MethodUtil.parseETagValue(ifMatchValue);
if (id != null && id.hasVersionIdPart() == false) {
id = id.withVersion(ifMatchValue);
}
}
return id;
}
@Override
protected BaseHttpClientInvocation createClientInvocation(Object[] theArgs, IResource theResource) {

View File

@ -30,10 +30,8 @@ import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.annotation.Validate;
import ca.uhn.fhir.rest.api.RequestTypeEnum;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.api.*;
import ca.uhn.fhir.rest.client.impl.BaseHttpClientInvocation;
import ca.uhn.fhir.rest.param.IParameter;
public class ValidateMethodBindingDstu1 extends BaseOutcomeReturningMethodBindingWithResourceParam {
@ -50,12 +48,6 @@ public class ValidateMethodBindingDstu1 extends BaseOutcomeReturningMethodBindin
return RestOperationTypeEnum.VALIDATE;
}
@Override
protected void addParametersForServerRequest(RequestDetails theRequest, Object[] theParams) {
if (myIdParameterIndex != null) {
theParams[myIdParameterIndex] = theRequest.getId();
}
}
@Override
protected BaseHttpClientInvocation createClientInvocation(Object[] theArgs, IResource theResource) {

View File

@ -31,10 +31,9 @@ import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
import ca.uhn.fhir.rest.annotation.OperationParam;
import ca.uhn.fhir.rest.annotation.Validate;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.EncodingEnum;
import ca.uhn.fhir.rest.client.impl.BaseHttpClientInvocation;
import ca.uhn.fhir.rest.param.IParameter;
import ca.uhn.fhir.rest.server.method.ResourceParameter;
import ca.uhn.fhir.util.ParametersUtil;
public class ValidateMethodBindingDstu2Plus extends OperationMethodBinding {

View File

@ -22,50 +22,30 @@ package ca.uhn.fhir.rest.server;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.io.*;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IBaseBinary;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import org.hl7.fhir.instance.model.api.*;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.api.Tag;
import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.model.api.*;
import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.api.*;
import ca.uhn.fhir.rest.api.server.IRestfulResponse;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.client.api.IHttpRequest;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.method.*;
import ca.uhn.fhir.rest.server.method.ElementsParameter;
import ca.uhn.fhir.rest.server.method.SummaryEnumParameter;
import ca.uhn.fhir.util.DateUtils;
public class RestfulServerUtils {
@ -788,27 +768,4 @@ public class RestfulServerUtils {
}
}
public static void addAcceptHeaderToRequest(EncodingEnum theEncoding, IHttpRequest theHttpRequest, FhirContext theContext) {
if (theEncoding == null) {
if (theContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU2_1) == false) {
theHttpRequest.addHeader(Constants.HEADER_ACCEPT, Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON_LEGACY);
} else {
theHttpRequest.addHeader(Constants.HEADER_ACCEPT, Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON_NON_LEGACY);
}
} else if (theEncoding == EncodingEnum.JSON) {
if (theContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU2_1) == false) {
theHttpRequest.addHeader(Constants.HEADER_ACCEPT, Constants.CT_FHIR_JSON);
} else {
theHttpRequest.addHeader(Constants.HEADER_ACCEPT, Constants.HEADER_ACCEPT_VALUE_JSON_NON_LEGACY);
}
} else if (theEncoding == EncodingEnum.XML) {
if (theContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU2_1) == false) {
theHttpRequest.addHeader(Constants.HEADER_ACCEPT, Constants.CT_FHIR_XML);
} else {
theHttpRequest.addHeader(Constants.HEADER_ACCEPT, Constants.HEADER_ACCEPT_VALUE_XML_NON_LEGACY);
}
}
}
}

View File

@ -1,29 +1,19 @@
package ca.uhn.fhir.rest.server.method;
import java.io.Reader;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Map;
import org.hl7.fhir.instance.model.api.IBaseResource;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.TagListParam;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.RequestTypeEnum;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.client.impl.BaseHttpClientInvocation;
import ca.uhn.fhir.rest.client.method.RequestDetails;
import ca.uhn.fhir.rest.param.IParameter;
import ca.uhn.fhir.rest.api.*;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.param.ParameterUtil;
import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
abstract class BaseAddOrDeleteTagsMethodBinding extends BaseMethodBinding<Void> {
@ -43,34 +33,23 @@ abstract class BaseAddOrDeleteTagsMethodBinding extends BaseMethodBinding<Void>
}
if (Modifier.isInterface(myType.getModifiers())) {
throw new ConfigurationException("Method '" + theMethod.getName() + "' does not specify a resource type, but has an @" + IdParam.class.getSimpleName() + " parameter. Please specity a resource type in the method annotation on this method");
throw new ConfigurationException("Method '" + theMethod.getName() + "' does not specify a resource type, but has an @" + IdParam.class.getSimpleName()
+ " parameter. Please specity a resource type in the method annotation on this method");
}
myResourceName = theContext.getResourceDefinition(myType).getName();
myIdParamIndex = MethodUtil.findIdParameterIndex(theMethod, getContext());
myVersionIdParamIndex = MethodUtil.findVersionIdParameterIndex(theMethod);
myTagListParamIndex = MethodUtil.findTagListParameterIndex(theMethod);
myIdParamIndex = ParameterUtil.findIdParameterIndex(theMethod, getContext());
myVersionIdParamIndex = ParameterUtil.findVersionIdParameterIndex(theMethod);
myTagListParamIndex = ParameterUtil.findTagListParameterIndex(theMethod);
if (myIdParamIndex == null) {
throw new ConfigurationException("Method '" + theMethod.getName() + "' does not have an @" + IdParam.class.getSimpleName() + " parameter.");
}
if (myTagListParamIndex == null) {
throw new ConfigurationException("Method '" + theMethod.getName() + "' does not have a parameter of type " + TagList.class.getSimpleName() + ", or paramater is not annotated with the @" + TagListParam.class.getSimpleName() + " annotation");
}
}
@Override
public Void invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws BaseServerResponseException {
switch (theResponseStatusCode) {
case Constants.STATUS_HTTP_200_OK:
case Constants.STATUS_HTTP_201_CREATED:
case Constants.STATUS_HTTP_204_NO_CONTENT:
return null;
default:
throw processNon2xxResponseAndReturnExceptionToThrow(theResponseStatusCode, theResponseMimeType, theResponseReader);
throw new ConfigurationException("Method '" + theMethod.getName() + "' does not have a parameter of type " + TagList.class.getSimpleName() + ", or paramater is not annotated with the @"
+ TagListParam.class.getSimpleName() + " annotation");
}
}
@ -87,46 +66,6 @@ abstract class BaseAddOrDeleteTagsMethodBinding extends BaseMethodBinding<Void>
protected abstract boolean isDelete();
@Override
public BaseHttpClientInvocation invokeClient(Object[] theArgs) throws InternalErrorException {
HttpPostClientInvocation retVal;
IdDt id = (IdDt) theArgs[myIdParamIndex];
if (id == null || id.isEmpty()) {
throw new InvalidRequestException("ID must not be null or empty for this operation");
}
IdDt versionId = null;
if (myVersionIdParamIndex != null) {
versionId = (IdDt) theArgs[myVersionIdParamIndex];
}
TagList tagList = (TagList) theArgs[myTagListParamIndex];
Class<? extends IBaseResource> type = myType;
assert type != null;
if (isDelete()) {
if (versionId != null) {
retVal = new HttpPostClientInvocation(getContext(), tagList, getResourceName(), id.getValue(), Constants.PARAM_HISTORY, versionId.getValue(), Constants.PARAM_TAGS, Constants.PARAM_DELETE);
} else {
retVal = new HttpPostClientInvocation(getContext(), tagList, getResourceName(), id.getValue(), Constants.PARAM_TAGS, Constants.PARAM_DELETE);
}
} else {
if (versionId != null) {
retVal = new HttpPostClientInvocation(getContext(), tagList, getResourceName(), id.getValue(), Constants.PARAM_HISTORY, versionId.getValue(), Constants.PARAM_TAGS);
} else {
retVal = new HttpPostClientInvocation(getContext(), tagList, getResourceName(), id.getValue(), Constants.PARAM_TAGS);
}
}
for (int idx = 0; idx < theArgs.length; idx++) {
IParameter nextParam = getParameters().get(idx);
nextParam.translateClientArgumentIntoQueryArgument(getContext(), theArgs[idx], null, null);
}
return retVal;
}
@Override
public boolean incomingServerRequestMatchesMethod(RequestDetails theRequest) {
if (theRequest.getRequestType() != RequestTypeEnum.POST) {

View File

@ -145,95 +145,6 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
public abstract ReturnTypeEnum getReturnType();
@Override
public Object invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) {
IParser parser = createAppropriateParserForParsingResponse(theResponseMimeType, theResponseReader, theResponseStatusCode, myPreferTypesList);
switch (getReturnType()) {
case BUNDLE: {
Bundle dstu1bundle = null;
IBaseBundle dstu2bundle = null;
List<? extends IBaseResource> listOfResources = null;
if (getMethodReturnType() == MethodReturnTypeEnum.BUNDLE || getContext().getVersion().getVersion() == FhirVersionEnum.DSTU1) {
if (myResourceType != null) {
dstu1bundle = parser.parseBundle(myResourceType, theResponseReader);
} else {
dstu1bundle = parser.parseBundle(theResponseReader);
}
listOfResources = dstu1bundle.toListOfResources();
} else {
Class<? extends IBaseResource> type = getContext().getResourceDefinition("Bundle").getImplementingClass();
dstu2bundle = (IBaseBundle) parser.parseResource(type, theResponseReader);
listOfResources = BundleUtil.toListOfResources(getContext(), dstu2bundle);
}
switch (getMethodReturnType()) {
case BUNDLE:
return dstu1bundle;
case BUNDLE_RESOURCE:
return dstu2bundle;
case LIST_OF_RESOURCES:
if (myResourceListCollectionType != null) {
for (Iterator<? extends IBaseResource> iter = listOfResources.iterator(); iter.hasNext();) {
IBaseResource next = iter.next();
if (!myResourceListCollectionType.isAssignableFrom(next.getClass())) {
ourLog.debug("Not returning resource of type {} because it is not a subclass or instance of {}", next.getClass(), myResourceListCollectionType);
iter.remove();
}
}
}
return listOfResources;
case RESOURCE:
//FIXME null access on dstu1bundle
List<IResource> list = dstu1bundle.toListOfResources();
if (list.size() == 0) {
return null;
} else if (list.size() == 1) {
return list.get(0);
} else {
throw new InvalidResponseException(theResponseStatusCode, "FHIR server call returned a bundle with multiple resources, but this method is only able to returns one.");
}
case BUNDLE_PROVIDER:
throw new IllegalStateException("Return type of " + IBundleProvider.class.getSimpleName() + " is not supported in clients");
default:
break;
}
break;
}
case RESOURCE: {
IBaseResource resource;
if (myResourceType != null) {
resource = parser.parseResource(myResourceType, theResponseReader);
} else {
resource = parser.parseResource(theResponseReader);
}
MethodUtil.parseClientRequestResourceHeaders(null, theHeaders, resource);
switch (getMethodReturnType()) {
case BUNDLE:
return Bundle.withSingleResource((IResource) resource);
case LIST_OF_RESOURCES:
return Collections.singletonList(resource);
case RESOURCE:
return resource;
case BUNDLE_PROVIDER:
throw new IllegalStateException("Return type of " + IBundleProvider.class.getSimpleName() + " is not supported in clients");
case BUNDLE_RESOURCE:
return resource;
case METHOD_OUTCOME:
MethodOutcome retVal = new MethodOutcome();
retVal.setOperationOutcome((IBaseOperationOutcome) resource);
return retVal;
}
break;
}
}
throw new IllegalStateException("Should not get here!");
}
@SuppressWarnings("unchecked")
private List<Class<? extends IBaseResource>> createPreferTypesList() {
List<Class<? extends IBaseResource>> preferTypes = null;

View File

@ -21,11 +21,8 @@ package ca.uhn.fhir.rest.server.method;
*/
import java.lang.reflect.Method;
import java.util.*;
import java.util.Collection;
import org.hl7.fhir.instance.model.api.IBaseResource;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.rest.api.server.IRequestDetails;
import ca.uhn.fhir.rest.api.server.IServerMethodBinding;
@ -49,7 +46,4 @@ public interface IParameter {
void initializeTypes(Method theMethod, Class<? extends Collection<?>> theOuterCollectionType, Class<? extends Collection<?>> theInnerCollectionType, Class<?> theParameterType);
void translateClientArgumentIntoQueryArgument(FhirContext theContext, Object theSourceClientArgument, Map<String, List<String>> theTargetQueryArguments, IBaseResource theTargetResource)
throws InternalErrorException;
}

View File

@ -0,0 +1,224 @@
package ca.uhn.fhir.rest.server.method;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.*;
import org.hl7.fhir.instance.model.api.IBaseResource;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.rest.annotation.*;
import ca.uhn.fhir.rest.api.*;
import ca.uhn.fhir.rest.param.CollectionBinder;
import ca.uhn.fhir.rest.server.method.OperationParameter.IOperationParamConverter;
import ca.uhn.fhir.rest.server.method.ResourceParameter.Mode;
import ca.uhn.fhir.util.ParametersUtil;
import ca.uhn.fhir.util.ReflectionUtil;
public class MethodUtil {
public static void extractDescription(SearchParameter theParameter, Annotation[] theAnnotations) {
for (Annotation annotation : theAnnotations) {
if (annotation instanceof Description) {
Description desc = (Description) annotation;
if (isNotBlank(desc.formalDefinition())) {
theParameter.setDescription(desc.formalDefinition());
} else {
theParameter.setDescription(desc.shortDefinition());
}
}
}
}
@SuppressWarnings("unchecked")
public static List<IParameter> getResourceParameters(final FhirContext theContext, Method theMethod, Object theProvider, RestOperationTypeEnum theRestfulOperationTypeEnum) {
List<IParameter> parameters = new ArrayList<IParameter>();
Class<?>[] parameterTypes = theMethod.getParameterTypes();
int paramIndex = 0;
for (Annotation[] annotations : theMethod.getParameterAnnotations()) {
IParameter param = null;
Class<?> parameterType = parameterTypes[paramIndex];
Class<? extends java.util.Collection<?>> outerCollectionType = null;
Class<? extends java.util.Collection<?>> innerCollectionType = null;
if (TagList.class.isAssignableFrom(parameterType)) {
// TagList is handled directly within the method bindings
param = new NullParameter();
} else {
if (Collection.class.isAssignableFrom(parameterType)) {
innerCollectionType = (Class<? extends java.util.Collection<?>>) parameterType;
parameterType = ReflectionUtil.getGenericCollectionTypeOfMethodParameter(theMethod, paramIndex);
}
if (Collection.class.isAssignableFrom(parameterType)) {
outerCollectionType = innerCollectionType;
innerCollectionType = (Class<? extends java.util.Collection<?>>) parameterType;
parameterType = ReflectionUtil.getGenericCollectionTypeOfMethodParameter(theMethod, paramIndex);
}
if (Collection.class.isAssignableFrom(parameterType)) {
throw new ConfigurationException("Argument #" + paramIndex + " of Method '" + theMethod.getName() + "' in type '" + theMethod.getDeclaringClass().getCanonicalName()
+ "' is of an invalid generic type (can not be a collection of a collection of a collection)");
}
}
if (parameterType.equals(SummaryEnum.class)) {
param = new SummaryEnumParameter();
} else if (parameterType.equals(PatchTypeEnum.class)) {
param = new PatchTypeParameter();
} else {
for (int i = 0; i < annotations.length && param == null; i++) {
Annotation nextAnnotation = annotations[i];
if (nextAnnotation instanceof RequiredParam) {
SearchParameter parameter = new SearchParameter();
parameter.setName(((RequiredParam) nextAnnotation).name());
parameter.setRequired(true);
parameter.setDeclaredTypes(((RequiredParam) nextAnnotation).targetTypes());
parameter.setCompositeTypes(((RequiredParam) nextAnnotation).compositeTypes());
parameter.setChainlists(((RequiredParam) nextAnnotation).chainWhitelist(), ((RequiredParam) nextAnnotation).chainBlacklist());
parameter.setType(theContext, parameterType, innerCollectionType, outerCollectionType);
MethodUtil.extractDescription(parameter, annotations);
param = parameter;
} else if (nextAnnotation instanceof OptionalParam) {
SearchParameter parameter = new SearchParameter();
parameter.setName(((OptionalParam) nextAnnotation).name());
parameter.setRequired(false);
parameter.setDeclaredTypes(((OptionalParam) nextAnnotation).targetTypes());
parameter.setCompositeTypes(((OptionalParam) nextAnnotation).compositeTypes());
parameter.setChainlists(((OptionalParam) nextAnnotation).chainWhitelist(), ((OptionalParam) nextAnnotation).chainBlacklist());
parameter.setType(theContext, parameterType, innerCollectionType, outerCollectionType);
MethodUtil.extractDescription(parameter, annotations);
param = parameter;
} else if (nextAnnotation instanceof RawParam) {
param = new RawParamsParmeter(parameters);
} else if (nextAnnotation instanceof IncludeParam) {
Class<? extends Collection<Include>> instantiableCollectionType;
Class<?> specType;
if (parameterType == String.class) {
instantiableCollectionType = null;
specType = String.class;
} else if ((parameterType != Include.class) || innerCollectionType == null || outerCollectionType != null) {
throw new ConfigurationException("Method '" + theMethod.getName() + "' is annotated with @" + IncludeParam.class.getSimpleName() + " but has a type other than Collection<"
+ Include.class.getSimpleName() + ">");
} else {
instantiableCollectionType = (Class<? extends Collection<Include>>) CollectionBinder.getInstantiableCollectionType(innerCollectionType, "Method '" + theMethod.getName() + "'");
specType = parameterType;
}
param = new IncludeParameter((IncludeParam) nextAnnotation, instantiableCollectionType, specType);
} else if (nextAnnotation instanceof ResourceParam) {
Mode mode;
if (IBaseResource.class.isAssignableFrom(parameterType)) {
mode = Mode.RESOURCE;
} else if (String.class.equals(parameterType)) {
mode = ResourceParameter.Mode.BODY;
} else if (byte[].class.equals(parameterType)) {
mode = ResourceParameter.Mode.BODY_BYTE_ARRAY;
} else if (EncodingEnum.class.equals(parameterType)) {
mode = Mode.ENCODING;
} else {
StringBuilder b = new StringBuilder();
b.append("Method '");
b.append(theMethod.getName());
b.append("' is annotated with @");
b.append(ResourceParam.class.getSimpleName());
b.append(" but has a type that is not an implemtation of ");
b.append(IBaseResource.class.getCanonicalName());
b.append(" or String or byte[]");
throw new ConfigurationException(b.toString());
}
param = new ResourceParameter((Class<? extends IBaseResource>) parameterType, theProvider, mode);
} else if (nextAnnotation instanceof IdParam || nextAnnotation instanceof VersionIdParam) {
param = new NullParameter();
} else if (nextAnnotation instanceof ServerBase) {
param = new ServerBaseParamBinder();
} else if (nextAnnotation instanceof Elements) {
param = new ElementsParameter();
} else if (nextAnnotation instanceof Since) {
param = new SinceParameter();
((SinceParameter) param).setType(theContext, parameterType, innerCollectionType, outerCollectionType);
} else if (nextAnnotation instanceof At) {
param = new AtParameter();
((AtParameter) param).setType(theContext, parameterType, innerCollectionType, outerCollectionType);
} else if (nextAnnotation instanceof Count) {
param = new CountParameter();
} else if (nextAnnotation instanceof Sort) {
param = new SortParameter(theContext);
} else if (nextAnnotation instanceof TransactionParam) {
param = new TransactionParameter(theContext);
} else if (nextAnnotation instanceof ConditionalUrlParam) {
param = new ConditionalParamBinder(theRestfulOperationTypeEnum, ((ConditionalUrlParam) nextAnnotation).supportsMultiple());
} else if (nextAnnotation instanceof OperationParam) {
Operation op = theMethod.getAnnotation(Operation.class);
param = new OperationParameter(theContext, op.name(), ((OperationParam) nextAnnotation));
} else if (nextAnnotation instanceof Validate.Mode) {
if (parameterType.equals(ValidationModeEnum.class) == false) {
throw new ConfigurationException(
"Parameter annotated with @" + Validate.class.getSimpleName() + "." + Validate.Mode.class.getSimpleName() + " must be of type " + ValidationModeEnum.class.getName());
}
param = new OperationParameter(theContext, Constants.EXTOP_VALIDATE, Constants.EXTOP_VALIDATE_MODE, 0, 1).setConverter(new IOperationParamConverter() {
@Override
public Object incomingServer(Object theObject) {
if (isNotBlank(theObject.toString())) {
ValidationModeEnum retVal = ValidationModeEnum.forCode(theObject.toString());
if (retVal == null) {
OperationParameter.throwInvalidMode(theObject.toString());
}
return retVal;
}
return null;
}
@Override
public Object outgoingClient(Object theObject) {
return ParametersUtil.createString(theContext, ((ValidationModeEnum) theObject).getCode());
}
});
} else if (nextAnnotation instanceof Validate.Profile) {
if (parameterType.equals(String.class) == false) {
throw new ConfigurationException(
"Parameter annotated with @" + Validate.class.getSimpleName() + "." + Validate.Profile.class.getSimpleName() + " must be of type " + String.class.getName());
}
param = new OperationParameter(theContext, Constants.EXTOP_VALIDATE, Constants.EXTOP_VALIDATE_PROFILE, 0, 1).setConverter(new IOperationParamConverter() {
@Override
public Object incomingServer(Object theObject) {
return theObject.toString();
}
@Override
public Object outgoingClient(Object theObject) {
return ParametersUtil.createString(theContext, theObject.toString());
}
});
} else {
continue;
}
}
}
if (param == null) {
throw new ConfigurationException(
"Parameter #" + ((paramIndex + 1)) + "/" + (parameterTypes.length) + " of method '" + theMethod.getName() + "' on type '" + theMethod.getDeclaringClass().getCanonicalName()
+ "' has no recognized FHIR interface parameter annotations. Don't know how to handle this parameter");
}
param.initializeTypes(theMethod, outerCollectionType, innerCollectionType, parameterType);
parameters.add(param);
paramIndex++;
}
return parameters;
}
}

View File

@ -326,72 +326,6 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
myDescription = theDescription;
}
public static BaseHttpClientInvocation createOperationInvocation(FhirContext theContext, String theResourceName, String theId, String theOperationName, IBaseParameters theInput,
boolean theUseHttpGet) {
StringBuilder b = new StringBuilder();
if (theResourceName != null) {
b.append(theResourceName);
if (isNotBlank(theId)) {
b.append('/');
b.append(theId);
}
}
if (b.length() > 0) {
b.append('/');
}
if (!theOperationName.startsWith("$")) {
b.append("$");
}
b.append(theOperationName);
if (!theUseHttpGet) {
return new HttpPostClientInvocation(theContext, theInput, b.toString());
}
FhirTerser t = theContext.newTerser();
List<Object> parameters = t.getValues(theInput, "Parameters.parameter");
Map<String, List<String>> params = new LinkedHashMap<String, List<String>>();
for (Object nextParameter : parameters) {
IPrimitiveType<?> nextNameDt = (IPrimitiveType<?>) t.getSingleValueOrNull((IBase) nextParameter, "name");
if (nextNameDt == null || nextNameDt.isEmpty()) {
ourLog.warn("Ignoring input parameter with no value in Parameters.parameter.name in operation client invocation");
continue;
}
String nextName = nextNameDt.getValueAsString();
if (!params.containsKey(nextName)) {
params.put(nextName, new ArrayList<String>());
}
IBaseDatatype value = (IBaseDatatype) t.getSingleValueOrNull((IBase) nextParameter, "value[x]");
if (value == null) {
continue;
}
if (!(value instanceof IPrimitiveType)) {
throw new IllegalArgumentException(
"Can not invoke operation as HTTP GET when it has parameters with a composite (non priitive) datatype as the value. Found value: " + value.getClass().getName());
}
IPrimitiveType<?> primitive = (IPrimitiveType<?>) value;
params.get(nextName).add(primitive.getValueAsString());
}
return new HttpGetClientInvocation(theContext, params, b.toString());
}
public static BaseHttpClientInvocation createProcessMsgInvocation(FhirContext theContext, String theOperationName, IBaseBundle theInput, Map<String, List<String>> urlParams) {
StringBuilder b = new StringBuilder();
if (b.length() > 0) {
b.append('/');
}
if (!theOperationName.startsWith("$")) {
b.append("$");
}
b.append(theOperationName);
BaseHttpClientInvocation.appendExtraParamsWithQuestionMark(urlParams, b, b.indexOf("?") == -1);
return new HttpPostClientInvocation(theContext, theInput, b.toString());
}
public static class ReturnType {
private int myMax;

View File

@ -25,7 +25,7 @@ import java.io.*;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.nio.charset.Charset;
import java.util.*;
import java.util.Collection;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.Validate;
@ -38,9 +38,7 @@ import ca.uhn.fhir.model.api.*;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.api.*;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.method.MethodUtil;
import ca.uhn.fhir.rest.param.IParameter;
import ca.uhn.fhir.rest.api.server.*;
import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.RestfulServerUtils;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
@ -82,14 +80,9 @@ public class ResourceParameter implements IParameter {
// ignore for now
}
@Override
public void translateClientArgumentIntoQueryArgument(FhirContext theContext, Object theSourceClientArgument, Map<String, List<String>> theTargetQueryArguments, IBaseResource theTargetResource) throws InternalErrorException {
// TODO Auto-generated method stub
}
@Override
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
public Object translateQueryParametersIntoServerArgument(IRequestDetails theRequest, IServerMethodBinding theMethodBinding) throws InternalErrorException, InvalidRequestException {
switch (myMode) {
case BODY:
try {
@ -156,7 +149,7 @@ public class ResourceParameter implements IParameter {
// This shouldn't happen since we're reading from a byte array..
throw new InternalErrorException(e);
}
encoding = MethodUtil.detectEncodingNoDefault(body);
encoding = EncodingEnum.detectEncodingNoDefault(body);
if (encoding == null) {
String msg = ctx.getLocalizer().getMessage(ResourceParameter.class, "noContentTypeInRequest", restOperationType);
throw new InvalidRequestException(msg);