Continue refactor for HAPI 3
This commit is contained in:
parent
9281ccafc3
commit
f1d2ee9092
|
@ -1,5 +1,7 @@
|
|||
package ca.uhn.fhir.rest.client.api;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
|
@ -10,7 +12,7 @@ package ca.uhn.fhir.rest.client.api;
|
|||
* 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
|
||||
* 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,
|
||||
|
@ -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,51 +35,66 @@ 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
|
||||
*/
|
||||
FhirContext getFhirContext();
|
||||
|
||||
|
||||
/**
|
||||
* Do not call this method in client code. It is a part of the internal HAPI API and
|
||||
* Do not call this method in client code. It is a part of the internal HAPI API and
|
||||
* is subject to change!
|
||||
*/
|
||||
IHttpClient getHttpClient();
|
||||
|
||||
|
||||
/**
|
||||
* Returns the client interceptors that have been registered with this client
|
||||
*/
|
||||
List<IClientInterceptor> getInterceptors();
|
||||
|
||||
/**
|
||||
* Base URL for the server, with no trailing "/"
|
||||
*/
|
||||
String getServerBase();
|
||||
|
||||
|
||||
/**
|
||||
* Register a new interceptor for this client. An interceptor can be used to add additional
|
||||
* logging, or add security headers, or pre-process responses, etc.
|
||||
* logging, or add security headers, or pre-process responses, etc.
|
||||
*/
|
||||
void registerInterceptor(IClientInterceptor theInterceptor);
|
||||
|
||||
/**
|
||||
* Specifies that the client should use the given encoding to do its
|
||||
* Specifies that the client should use the given encoding to do its
|
||||
* queries. This means that the client will append the "_format" param
|
||||
* to GET methods (read/search/etc), and will add an appropriate header for
|
||||
* write methods.
|
||||
* write methods.
|
||||
*
|
||||
* @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>.
|
||||
* @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);
|
||||
|
||||
|
||||
/**
|
||||
* Specifies that the client should request that the server respond with "pretty printing"
|
||||
* 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);
|
||||
|
||||
|
@ -87,10 +103,10 @@ public interface IRestfulClient {
|
|||
* to be applied globally on this client.
|
||||
*/
|
||||
void setSummary(SummaryEnum theSummary);
|
||||
|
||||
|
||||
/**
|
||||
* Remove an intercaptor that was previously registered using {@link IRestfulClient#registerInterceptor(IClientInterceptor)}
|
||||
*/
|
||||
void unregisterInterceptor(IClientInterceptor theInterceptor);
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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
|
||||
|
@ -10,7 +12,7 @@ package ca.uhn.fhir.rest.param;
|
|||
* 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
|
||||
* 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,
|
||||
|
@ -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;
|
||||
}
|
||||
return -1;
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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,56 +214,14 @@ 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());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
if (theArgument instanceof Integer) {
|
||||
return new IntegerDt((Integer) theArgument);
|
||||
}
|
||||
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);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -205,13 +245,13 @@ public class ParameterUtil {
|
|||
b.append(next);
|
||||
} else {
|
||||
switch (theValue.charAt(i + 1)) {
|
||||
case '$':
|
||||
case ',':
|
||||
case '|':
|
||||
case '\\':
|
||||
continue;
|
||||
default:
|
||||
b.append(next);
|
||||
case '$':
|
||||
case ',':
|
||||
case '|':
|
||||
case '\\':
|
||||
continue;
|
||||
default:
|
||||
b.append(next);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
msg = getFhirContext().getLocalizer().getMessage(BaseClient.class, "failedToParseResponse", httpRequest.getHttpVerbName(), httpRequest.getUri(), e.toString());
|
||||
throw new FhirClientConnectionException(msg, e);
|
||||
} catch (RuntimeException e) {
|
||||
throw e;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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> {
|
||||
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
@ -46,13 +41,8 @@ public abstract class BaseOutcomeReturningMethodBindingWithResourceIdButNoResour
|
|||
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());
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
@ -96,7 +36,7 @@ import ca.uhn.fhir.util.UrlUtil;
|
|||
* 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
|
||||
* 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,
|
||||
|
@ -108,9 +48,9 @@ import ca.uhn.fhir.util.UrlUtil;
|
|||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class MethodUtil {
|
||||
|
||||
|
||||
private static final String LABEL = "label=\"";
|
||||
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(MethodUtil.class);
|
||||
private static final Set<String> ourServletRequestTypes = new HashSet<String>();
|
||||
private static final Set<String> ourServletResponseTypes = new HashSet<String>();
|
||||
|
@ -121,16 +61,15 @@ public class MethodUtil {
|
|||
ourServletRequestTypes.add("javax.servlet.http.HttpServletRequest");
|
||||
ourServletResponseTypes.add("javax.servlet.http.HttpServletResponse");
|
||||
}
|
||||
|
||||
|
||||
/** Non instantiable */
|
||||
private 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);
|
||||
TagList list = (TagList) ((IResource) resource).getResourceMetadata().get(ResourceMetadataKeyEnum.TAG_LIST);
|
||||
if (list != null) {
|
||||
for (Tag tag : list) {
|
||||
if (StringUtils.isNotBlank(tag.getTerm())) {
|
||||
|
@ -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())) {
|
||||
|
@ -177,7 +115,7 @@ public class MethodUtil {
|
|||
urlExtension.append(theId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HttpPostClientInvocation retVal;
|
||||
if (StringUtils.isBlank(theResourceBody)) {
|
||||
retVal = new HttpPostClientInvocation(theContext, theResource, urlExtension.toString());
|
||||
|
@ -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;
|
||||
|
@ -205,11 +144,11 @@ public class MethodUtil {
|
|||
retVal.setIfNoneExistString(theIfNoneExistUrl);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
public static HttpPatchClientInvocation createPatchInvocation(FhirContext theContext, IIdType theId, PatchTypeEnum thePatchType, String theBody) {
|
||||
return PatchMethodBinding.createPatchInvocation(theContext, theId, thePatchType, theBody);
|
||||
}
|
||||
|
||||
|
||||
public static HttpPatchClientInvocation createPatchInvocation(FhirContext theContext, String theUrl, PatchTypeEnum thePatchType, String theBody) {
|
||||
return PatchMethodBinding.createPatchInvocation(theContext, theUrl, thePatchType, theBody);
|
||||
}
|
||||
|
@ -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)) {
|
||||
|
@ -282,7 +219,7 @@ public class MethodUtil {
|
|||
} else {
|
||||
retVal = new HttpPutClientInvocation(theContext, theResourceBody, false, urlExtension);
|
||||
}
|
||||
|
||||
|
||||
retVal.setForceResourceId(theId);
|
||||
|
||||
if (theId.hasVersionIdPart()) {
|
||||
|
@ -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,10 +282,11 @@ 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)");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (parameterType.equals(SummaryEnum.class)) {
|
||||
param = new SummaryEnumParameter();
|
||||
} else if (parameterType.equals(PatchTypeEnum.class)) {
|
||||
|
@ -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) {
|
||||
|
@ -463,10 +362,10 @@ public class MethodUtil {
|
|||
param = new ElementsParameter();
|
||||
} else if (nextAnnotation instanceof Since) {
|
||||
param = new SinceParameter();
|
||||
((SinceParameter)param).setType(theContext, parameterType, innerCollectionType, outerCollectionType);
|
||||
((SinceParameter) param).setType(theContext, parameterType, innerCollectionType, outerCollectionType);
|
||||
} else if (nextAnnotation instanceof At) {
|
||||
param = new AtParameter();
|
||||
((AtParameter)param).setType(theContext, parameterType, innerCollectionType, outerCollectionType);
|
||||
((AtParameter) param).setType(theContext, parameterType, innerCollectionType, outerCollectionType);
|
||||
} else if (nextAnnotation instanceof Count) {
|
||||
param = new CountParameter();
|
||||
} else if (nextAnnotation instanceof Sort) {
|
||||
|
@ -474,13 +373,14 @@ public class MethodUtil {
|
|||
} else if (nextAnnotation instanceof TransactionParam) {
|
||||
param = new TransactionParameter(theContext);
|
||||
} else if (nextAnnotation instanceof ConditionalUrlParam) {
|
||||
param = new ConditionalParamBinder(theRestfulOperationTypeEnum, ((ConditionalUrlParam)nextAnnotation).supportsMultiple());
|
||||
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());
|
||||
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
|
||||
|
@ -494,22 +394,23 @@ public class MethodUtil {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object outgoingClient(Object theObject) {
|
||||
return ParametersUtil.createString(theContext, ((ValidationModeEnum)theObject).getCode());
|
||||
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());
|
||||
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());
|
||||
|
@ -524,8 +425,9 @@ public class MethodUtil {
|
|||
}
|
||||
|
||||
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");
|
||||
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);
|
||||
|
@ -644,42 +546,41 @@ public class MethodUtil {
|
|||
return parseQueryParams(theContext, paramType, theUnqualifiedParamName, theParameters);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This is a utility method intended provided to help the JPA module.
|
||||
*/
|
||||
public static IQueryParameterAnd<?> parseQueryParams(FhirContext theContext, RestSearchParameterTypeEnum paramType, String theUnqualifiedParamName, List<QualifiedParamList> theParameters) {
|
||||
QueryParameterAndBinder binder = null;
|
||||
switch (paramType) {
|
||||
case COMPOSITE:
|
||||
throw new UnsupportedOperationException();
|
||||
case DATE:
|
||||
binder = new QueryParameterAndBinder(DateAndListParam.class, Collections.<Class<? extends IQueryParameterType>> emptyList());
|
||||
break;
|
||||
case NUMBER:
|
||||
binder = new QueryParameterAndBinder(NumberAndListParam.class, Collections.<Class<? extends IQueryParameterType>> emptyList());
|
||||
break;
|
||||
case QUANTITY:
|
||||
binder = new QueryParameterAndBinder(QuantityAndListParam.class, Collections.<Class<? extends IQueryParameterType>> emptyList());
|
||||
break;
|
||||
case REFERENCE:
|
||||
binder = new QueryParameterAndBinder(ReferenceAndListParam.class, Collections.<Class<? extends IQueryParameterType>> emptyList());
|
||||
break;
|
||||
case STRING:
|
||||
binder = new QueryParameterAndBinder(StringAndListParam.class, Collections.<Class<? extends IQueryParameterType>> emptyList());
|
||||
break;
|
||||
case TOKEN:
|
||||
binder = new QueryParameterAndBinder(TokenAndListParam.class, Collections.<Class<? extends IQueryParameterType>> emptyList());
|
||||
break;
|
||||
case URI:
|
||||
binder = new QueryParameterAndBinder(UriAndListParam.class, Collections.<Class<? extends IQueryParameterType>> emptyList());
|
||||
break;
|
||||
case HAS:
|
||||
binder = new QueryParameterAndBinder(HasAndListParam.class, Collections.<Class<? extends IQueryParameterType>> emptyList());
|
||||
break;
|
||||
case COMPOSITE:
|
||||
throw new UnsupportedOperationException();
|
||||
case DATE:
|
||||
binder = new QueryParameterAndBinder(DateAndListParam.class, Collections.<Class<? extends IQueryParameterType>> emptyList());
|
||||
break;
|
||||
case NUMBER:
|
||||
binder = new QueryParameterAndBinder(NumberAndListParam.class, Collections.<Class<? extends IQueryParameterType>> emptyList());
|
||||
break;
|
||||
case QUANTITY:
|
||||
binder = new QueryParameterAndBinder(QuantityAndListParam.class, Collections.<Class<? extends IQueryParameterType>> emptyList());
|
||||
break;
|
||||
case REFERENCE:
|
||||
binder = new QueryParameterAndBinder(ReferenceAndListParam.class, Collections.<Class<? extends IQueryParameterType>> emptyList());
|
||||
break;
|
||||
case STRING:
|
||||
binder = new QueryParameterAndBinder(StringAndListParam.class, Collections.<Class<? extends IQueryParameterType>> emptyList());
|
||||
break;
|
||||
case TOKEN:
|
||||
binder = new QueryParameterAndBinder(TokenAndListParam.class, Collections.<Class<? extends IQueryParameterType>> emptyList());
|
||||
break;
|
||||
case URI:
|
||||
binder = new QueryParameterAndBinder(UriAndListParam.class, Collections.<Class<? extends IQueryParameterType>> emptyList());
|
||||
break;
|
||||
case HAS:
|
||||
binder = new QueryParameterAndBinder(HasAndListParam.class, Collections.<Class<? extends IQueryParameterType>> emptyList());
|
||||
break;
|
||||
}
|
||||
|
||||
//FIXME null access
|
||||
// FIXME null access
|
||||
return binder.parse(theContext, theUnqualifiedParamName, theParameters);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -10,7 +10,7 @@ package ca.uhn.fhir.rest.client.method;
|
|||
* 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
|
||||
* 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,
|
||||
|
@ -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;
|
||||
|
|
|
@ -10,7 +10,7 @@ package ca.uhn.fhir.rest.client.method;
|
|||
* 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
|
||||
* 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,
|
||||
|
@ -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,45 +42,9 @@ 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>>");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ package ca.uhn.fhir.rest.client.method;
|
|||
* 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
|
||||
* 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,
|
||||
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,13 +48,7 @@ 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) {
|
||||
FhirContext context = getContext();
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -125,7 +125,7 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
myPreferTypesList = createPreferTypesList();
|
||||
}
|
||||
|
||||
|
@ -145,104 +145,15 @@ 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;
|
||||
if (myResourceListCollectionType != null && IBaseResource.class.isAssignableFrom(myResourceListCollectionType)) {
|
||||
preferTypes = new ArrayList<Class<? extends IBaseResource>>(1);
|
||||
preferTypes.add((Class<? extends IBaseResource>) myResourceListCollectionType);
|
||||
// } else if (myResourceType != null) {
|
||||
// preferTypes = new ArrayList<Class<? extends IBaseResource>>(1);
|
||||
// preferTypes.add((Class<? extends IBaseResource>) myResourceListCollectionType);
|
||||
// } else if (myResourceType != null) {
|
||||
// preferTypes = new ArrayList<Class<? extends IBaseResource>>(1);
|
||||
// preferTypes.add((Class<? extends IBaseResource>) myResourceListCollectionType);
|
||||
}
|
||||
return preferTypes;
|
||||
}
|
||||
|
@ -268,7 +179,7 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
|
|||
return theRequest.getResponse().streamResponseAsResource(responseObject.getResource(), prettyPrint, summaryMode, Constants.STATUS_HTTP_200_OK, null, theRequest.isRespondGzip(),
|
||||
isAddContentLocationHeader());
|
||||
|
||||
}
|
||||
}
|
||||
// Is this request coming from a browser
|
||||
String uaHeader = theRequest.getHeader("user-agent");
|
||||
boolean requestIsBrowser = false;
|
||||
|
@ -305,112 +216,112 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
|
|||
final ResourceOrDstu1Bundle responseObject;
|
||||
|
||||
switch (getReturnType()) {
|
||||
case BUNDLE: {
|
||||
|
||||
/*
|
||||
* Figure out the self-link for this request
|
||||
*/
|
||||
String serverBase = theRequest.getServerBaseForRequest();
|
||||
String linkSelf;
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append(serverBase);
|
||||
if (isNotBlank(theRequest.getRequestPath())) {
|
||||
b.append('/');
|
||||
b.append(theRequest.getRequestPath());
|
||||
}
|
||||
// For POST the URL parameters get jumbled with the post body parameters so don't include them, they might be huge
|
||||
if (theRequest.getRequestType() == RequestTypeEnum.GET) {
|
||||
boolean first = true;
|
||||
Map<String, String[]> parameters = theRequest.getParameters();
|
||||
for (String nextParamName : new TreeSet<String>(parameters.keySet())) {
|
||||
for (String nextParamValue : parameters.get(nextParamName)) {
|
||||
if (first) {
|
||||
b.append('?');
|
||||
first = false;
|
||||
} else {
|
||||
b.append('&');
|
||||
}
|
||||
b.append(UrlUtil.escape(nextParamName));
|
||||
b.append('=');
|
||||
b.append(UrlUtil.escape(nextParamValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
linkSelf = b.toString();
|
||||
|
||||
if (getMethodReturnType() == MethodReturnTypeEnum.BUNDLE_RESOURCE) {
|
||||
IBaseResource resource;
|
||||
IPrimitiveType<Date> lastUpdated;
|
||||
if (resultObj instanceof IBundleProvider) {
|
||||
IBundleProvider result = (IBundleProvider) resultObj;
|
||||
resource = result.getResources(0, 1).get(0);
|
||||
lastUpdated = result.getPublished();
|
||||
} else {
|
||||
resource = (IBaseResource) resultObj;
|
||||
lastUpdated = theServer.getFhirContext().getVersion().getLastUpdated(resource);
|
||||
}
|
||||
case BUNDLE: {
|
||||
|
||||
/*
|
||||
* We assume that the bundle we got back from the handling method may not have everything populated (e.g. self links, bundle type, etc) so we do that here.
|
||||
* Figure out the self-link for this request
|
||||
*/
|
||||
IVersionSpecificBundleFactory bundleFactory = theServer.getFhirContext().newBundleFactory();
|
||||
bundleFactory.initializeWithBundleResource(resource);
|
||||
bundleFactory.addRootPropertiesToBundle(null, theRequest.getFhirServerBase(), linkSelf, count, getResponseBundleType(), lastUpdated);
|
||||
String serverBase = theRequest.getServerBaseForRequest();
|
||||
String linkSelf;
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append(serverBase);
|
||||
if (isNotBlank(theRequest.getRequestPath())) {
|
||||
b.append('/');
|
||||
b.append(theRequest.getRequestPath());
|
||||
}
|
||||
// For POST the URL parameters get jumbled with the post body parameters so don't include them, they might be huge
|
||||
if (theRequest.getRequestType() == RequestTypeEnum.GET) {
|
||||
boolean first = true;
|
||||
Map<String, String[]> parameters = theRequest.getParameters();
|
||||
for (String nextParamName : new TreeSet<String>(parameters.keySet())) {
|
||||
for (String nextParamValue : parameters.get(nextParamName)) {
|
||||
if (first) {
|
||||
b.append('?');
|
||||
first = false;
|
||||
} else {
|
||||
b.append('&');
|
||||
}
|
||||
b.append(UrlUtil.escape(nextParamName));
|
||||
b.append('=');
|
||||
b.append(UrlUtil.escape(nextParamValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
linkSelf = b.toString();
|
||||
|
||||
responseObject = new ResourceOrDstu1Bundle(resource);
|
||||
} else {
|
||||
Set<Include> includes = getRequestIncludesFromParams(params);
|
||||
if (getMethodReturnType() == MethodReturnTypeEnum.BUNDLE_RESOURCE) {
|
||||
IBaseResource resource;
|
||||
IPrimitiveType<Date> lastUpdated;
|
||||
if (resultObj instanceof IBundleProvider) {
|
||||
IBundleProvider result = (IBundleProvider) resultObj;
|
||||
resource = result.getResources(0, 1).get(0);
|
||||
lastUpdated = result.getPublished();
|
||||
} else {
|
||||
resource = (IBaseResource) resultObj;
|
||||
lastUpdated = theServer.getFhirContext().getVersion().getLastUpdated(resource);
|
||||
}
|
||||
|
||||
/*
|
||||
* We assume that the bundle we got back from the handling method may not have everything populated (e.g. self links, bundle type, etc) so we do that here.
|
||||
*/
|
||||
IVersionSpecificBundleFactory bundleFactory = theServer.getFhirContext().newBundleFactory();
|
||||
bundleFactory.initializeWithBundleResource(resource);
|
||||
bundleFactory.addRootPropertiesToBundle(null, theRequest.getFhirServerBase(), linkSelf, count, getResponseBundleType(), lastUpdated);
|
||||
|
||||
responseObject = new ResourceOrDstu1Bundle(resource);
|
||||
} else {
|
||||
Set<Include> includes = getRequestIncludesFromParams(params);
|
||||
|
||||
IBundleProvider result = (IBundleProvider) resultObj;
|
||||
if (count == null) {
|
||||
count = result.preferredPageSize();
|
||||
}
|
||||
|
||||
Integer offsetI = RestfulServerUtils.tryToExtractNamedParameter(theRequest, Constants.PARAM_PAGINGOFFSET);
|
||||
if (offsetI == null || offsetI < 0) {
|
||||
offsetI = 0;
|
||||
}
|
||||
|
||||
Integer resultSize = result.size();
|
||||
int start;
|
||||
if (resultSize != null) {
|
||||
start = Math.max(0, Math.min(offsetI, resultSize - 1));
|
||||
} else {
|
||||
start = offsetI;
|
||||
}
|
||||
|
||||
IVersionSpecificBundleFactory bundleFactory = theServer.getFhirContext().newBundleFactory();
|
||||
|
||||
ResponseEncoding responseEncoding = RestfulServerUtils.determineResponseEncodingNoDefault(theRequest, theServer.getDefaultResponseEncoding());
|
||||
EncodingEnum linkEncoding = theRequest.getParameters().containsKey(Constants.PARAM_FORMAT) && responseEncoding != null ? responseEncoding.getEncoding() : null;
|
||||
|
||||
boolean prettyPrint = RestfulServerUtils.prettyPrintResponse(theServer, theRequest);
|
||||
bundleFactory.initializeBundleFromBundleProvider(theServer, result, linkEncoding, theRequest.getFhirServerBase(), linkSelf, prettyPrint, start, count, null, getResponseBundleType(),
|
||||
includes);
|
||||
Bundle bundle = bundleFactory.getDstu1Bundle();
|
||||
if (bundle != null) {
|
||||
responseObject = new ResourceOrDstu1Bundle(bundle);
|
||||
} else {
|
||||
IBaseResource resBundle = bundleFactory.getResourceBundle();
|
||||
responseObject = new ResourceOrDstu1Bundle(resBundle);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RESOURCE: {
|
||||
IBundleProvider result = (IBundleProvider) resultObj;
|
||||
if (count == null) {
|
||||
count = result.preferredPageSize();
|
||||
if (result.size() == 0) {
|
||||
throw new ResourceNotFoundException(theRequest.getId());
|
||||
} else if (result.size() > 1) {
|
||||
throw new InternalErrorException("Method returned multiple resources");
|
||||
}
|
||||
|
||||
Integer offsetI = RestfulServerUtils.tryToExtractNamedParameter(theRequest, Constants.PARAM_PAGINGOFFSET);
|
||||
if (offsetI == null || offsetI < 0) {
|
||||
offsetI = 0;
|
||||
}
|
||||
|
||||
Integer resultSize = result.size();
|
||||
int start;
|
||||
if (resultSize != null) {
|
||||
start = Math.max(0, Math.min(offsetI, resultSize - 1));
|
||||
} else {
|
||||
start = offsetI;
|
||||
}
|
||||
|
||||
IVersionSpecificBundleFactory bundleFactory = theServer.getFhirContext().newBundleFactory();
|
||||
|
||||
ResponseEncoding responseEncoding = RestfulServerUtils.determineResponseEncodingNoDefault(theRequest, theServer.getDefaultResponseEncoding());
|
||||
EncodingEnum linkEncoding = theRequest.getParameters().containsKey(Constants.PARAM_FORMAT) && responseEncoding != null ? responseEncoding.getEncoding() : null;
|
||||
|
||||
boolean prettyPrint = RestfulServerUtils.prettyPrintResponse(theServer, theRequest);
|
||||
bundleFactory.initializeBundleFromBundleProvider(theServer, result, linkEncoding, theRequest.getFhirServerBase(), linkSelf, prettyPrint, start, count, null, getResponseBundleType(),
|
||||
includes);
|
||||
Bundle bundle = bundleFactory.getDstu1Bundle();
|
||||
if (bundle != null) {
|
||||
responseObject = new ResourceOrDstu1Bundle(bundle);
|
||||
} else {
|
||||
IBaseResource resBundle = bundleFactory.getResourceBundle();
|
||||
responseObject = new ResourceOrDstu1Bundle(resBundle);
|
||||
}
|
||||
IBaseResource resource = result.getResources(0, 1).get(0);
|
||||
responseObject = new ResourceOrDstu1Bundle(resource);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RESOURCE: {
|
||||
IBundleProvider result = (IBundleProvider) resultObj;
|
||||
if (result.size() == 0) {
|
||||
throw new ResourceNotFoundException(theRequest.getId());
|
||||
} else if (result.size() > 1) {
|
||||
throw new InternalErrorException("Method returned multiple resources");
|
||||
}
|
||||
|
||||
IBaseResource resource = result.getResources(0, 1).get(0);
|
||||
responseObject = new ResourceOrDstu1Bundle(resource);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new IllegalStateException(); // should not happen
|
||||
default:
|
||||
throw new IllegalStateException(); // should not happen
|
||||
}
|
||||
return responseObject;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue