Starting work on #19
This commit is contained in:
parent
bda33737f1
commit
9217ee28bf
|
@ -30,13 +30,52 @@ import ca.uhn.fhir.model.dstu.resource.Patient;
|
|||
import ca.uhn.fhir.rest.param.CompositeParam;
|
||||
import ca.uhn.fhir.rest.param.ReferenceParam;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
|
||||
/**
|
||||
* Parameter annotation which specifies a search parameter for a {@link Search} method.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface OptionalParam {
|
||||
|
||||
public static final String ALLOW_CHAIN_ANY = "*";
|
||||
|
||||
/**
|
||||
* For reference parameters ({@link ReferenceParam}) this value may be
|
||||
* used to indicate which chain values (if any) are <b>not</b> valid
|
||||
* for the given parameter. Values here will supercede any values specified
|
||||
* in {@link #chainWhitelist()}
|
||||
* <p>
|
||||
* If the parameter annotated with this annotation is not a {@link ReferenceParam},
|
||||
* this value must not be populated.
|
||||
* </p>
|
||||
*/
|
||||
String[] chainBlacklist() default {};
|
||||
|
||||
/**
|
||||
* For reference parameters ({@link ReferenceParam}) this value may be
|
||||
* used to indicate which chain values (if any) are valid for the given
|
||||
* parameter. If the list contains the value {@link #ALLOW_CHAIN_ANY}, as is
|
||||
* the default, all values are valid. Any values specified in
|
||||
* {@link #chainBlacklist()} will supercede (have priority over) values
|
||||
* here.
|
||||
* <p>
|
||||
* If the parameter annotated with this annotation is not a {@link ReferenceParam},
|
||||
* this value must not be populated.
|
||||
* </p>
|
||||
*/
|
||||
String[] chainWhitelist() default {ALLOW_CHAIN_ANY};
|
||||
|
||||
/**
|
||||
* For composite parameters ({@link CompositeParam}) this value may be
|
||||
* used to indicate the parameter type(s) which may be referenced by this param.
|
||||
* <p>
|
||||
* If the parameter annotated with this annotation is not a {@link CompositeParam},
|
||||
* this value must not be populated.
|
||||
* </p>
|
||||
*/
|
||||
Class<? extends IQueryParameterType>[] compositeTypes() default {};
|
||||
|
||||
/**
|
||||
* This is the name for the parameter. Generally this should be a
|
||||
* simple string (e.g. "name", or "identifier") which will be the name
|
||||
* of the URL parameter used to populate this method parameter.
|
||||
|
@ -54,9 +93,9 @@ public @interface OptionalParam {
|
|||
* </p>
|
||||
*/
|
||||
String name();
|
||||
|
||||
|
||||
/**
|
||||
* For resource reference parameters ({@link ReferenceParam}) this parameter may be
|
||||
* For resource reference parameters ({@link ReferenceParam}) this value may be
|
||||
* used to indicate the resource type(s) which may be referenced by this param.
|
||||
* <p>
|
||||
* If the parameter annotated with this annotation is not a {@link ReferenceParam},
|
||||
|
@ -64,15 +103,4 @@ public @interface OptionalParam {
|
|||
* </p>
|
||||
*/
|
||||
Class<? extends IResource>[] targetTypes() default {};
|
||||
|
||||
/**
|
||||
* For composite parameters ({@link CompositeParam}) this parameter may be
|
||||
* used to indicate the parameter type(s) which may be referenced by this param.
|
||||
* <p>
|
||||
* If the parameter annotated with this annotation is not a {@link CompositeParam},
|
||||
* this value must not be populated.
|
||||
* </p>
|
||||
*/
|
||||
Class<? extends IQueryParameterType>[] compositeTypes() default {};
|
||||
|
||||
}
|
||||
|
|
|
@ -36,44 +36,61 @@ import ca.uhn.fhir.rest.param.ReferenceParam;
|
|||
*/
|
||||
public @interface RequiredParam {
|
||||
/**
|
||||
* This is the name for the parameter. Generally this should be a
|
||||
* simple string (e.g. "name", or "identifier") which will be the name
|
||||
* of the URL parameter used to populate this method parameter.
|
||||
* For reference parameters ({@link ReferenceParam}) this value may be used to indicate which chain values (if any)
|
||||
* are <b>not</b> valid for the given parameter. Values here will supercede any values specified in
|
||||
* {@link #chainWhitelist()}
|
||||
* <p>
|
||||
* Most resource model classes have constants which may be used to
|
||||
* supply values for this field, e.g. {@link Patient#SP_NAME} or
|
||||
* {@link Observation#SP_DATE}
|
||||
* </p>
|
||||
* If the parameter annotated with this annotation is not a {@link ReferenceParam}, this value must not be
|
||||
* populated.
|
||||
* </p>
|
||||
*/
|
||||
String[] chainBlacklist() default {};
|
||||
|
||||
/**
|
||||
* For reference parameters ({@link ReferenceParam}) this value may be used to indicate which chain values (if any)
|
||||
* are valid for the given parameter. If the list contains the value {@link OptionalParam#ALLOW_CHAIN_ANY}, as is
|
||||
* the default, all values are valid. Any values specified in {@link #chainBlacklist()} will supercede (have
|
||||
* priority over) values here.
|
||||
* <p>
|
||||
* If you wish to specify a parameter for a resource reference which
|
||||
* only accepts a specific chained value, it is also valid to supply
|
||||
* a chained name here, such as "patient.name". It is recommended to
|
||||
* supply this using constants where possible, e.g.
|
||||
* <code>{@link Observation#SP_SUBJECT} + '.' + {@link Patient#SP_IDENTIFIER}</code>
|
||||
* If the parameter annotated with this annotation is not a {@link ReferenceParam}, this value must not be
|
||||
* populated.
|
||||
* </p>
|
||||
*/
|
||||
String[] chainWhitelist() default { OptionalParam.ALLOW_CHAIN_ANY };
|
||||
|
||||
/**
|
||||
* For composite parameters ({@link CompositeParam}) this parameter may be used to indicate the parameter type(s)
|
||||
* which may be referenced by this param.
|
||||
* <p>
|
||||
* If the parameter annotated with this annotation is not a {@link CompositeParam}, this value must not be
|
||||
* populated.
|
||||
* </p>
|
||||
*/
|
||||
Class<? extends IQueryParameterType>[] compositeTypes() default {};
|
||||
|
||||
/**
|
||||
* This is the name for the parameter. Generally this should be a simple string (e.g. "name", or "identifier") which
|
||||
* will be the name of the URL parameter used to populate this method parameter.
|
||||
* <p>
|
||||
* Most resource model classes have constants which may be used to supply values for this field, e.g.
|
||||
* {@link Patient#SP_NAME} or {@link Observation#SP_DATE}
|
||||
* </p>
|
||||
* <p>
|
||||
* If you wish to specify a parameter for a resource reference which only accepts a specific chained value, it is
|
||||
* also valid to supply a chained name here, such as "patient.name". It is recommended to supply this using
|
||||
* constants where possible, e.g. <code>{@link Observation#SP_SUBJECT} + '.' + {@link Patient#SP_IDENTIFIER}</code>
|
||||
* </p>
|
||||
*/
|
||||
String name();
|
||||
|
||||
/**
|
||||
* For resource reference parameters ({@link ReferenceParam}) this parameter may be
|
||||
* used to indicate the resource type(s) which may be referenced by this param.
|
||||
* <p>
|
||||
* If the parameter annotated with this annotation is not a {@link ReferenceParam},
|
||||
* this value must not be populated.
|
||||
* </p>
|
||||
*/
|
||||
Class<? extends IResource>[] targetTypes() default {};
|
||||
|
||||
|
||||
/**
|
||||
* For composite parameters ({@link CompositeParam}) this parameter may be
|
||||
* used to indicate the parameter type(s) which may be referenced by this param.
|
||||
* <p>
|
||||
* If the parameter annotated with this annotation is not a {@link CompositeParam},
|
||||
* this value must not be populated.
|
||||
* </p>
|
||||
*/
|
||||
Class<? extends IQueryParameterType>[] compositeTypes() default {};
|
||||
|
||||
/**
|
||||
* For resource reference parameters ({@link ReferenceParam}) this parameter may be used to indicate the resource
|
||||
* type(s) which may be referenced by this param.
|
||||
* <p>
|
||||
* If the parameter annotated with this annotation is not a {@link ReferenceParam}, this value must not be
|
||||
* populated.
|
||||
* </p>
|
||||
*/
|
||||
Class<? extends IResource>[] targetTypes() default {};
|
||||
|
||||
}
|
||||
|
|
|
@ -95,11 +95,14 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
myParameters = MethodUtil.getResourceParameters(theMethod);
|
||||
}
|
||||
|
||||
|
||||
public List<Class<?>> getAllowableParamAnnotations() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public FhirContext getContext() {
|
||||
return myContext;
|
||||
}
|
||||
|
||||
public Set<String> getIncludes() {
|
||||
Set<String> retVal = new TreeSet<String>();
|
||||
for (IParameter next : myParameters) {
|
||||
|
@ -110,14 +113,14 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
return retVal;
|
||||
}
|
||||
|
||||
public FhirContext getContext() {
|
||||
return myContext;
|
||||
}
|
||||
|
||||
public Method getMethod() {
|
||||
return myMethod;
|
||||
}
|
||||
|
||||
public OtherOperationTypeEnum getOtherOperationType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<IParameter> getParameters() {
|
||||
return myParameters;
|
||||
}
|
||||
|
@ -127,7 +130,8 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the resource this method handles, or <code>null</code> if this method is not resource specific
|
||||
* Returns the name of the resource this method handles, or <code>null</code> if this method is not resource
|
||||
* specific
|
||||
*/
|
||||
public abstract String getResourceName();
|
||||
|
||||
|
@ -135,10 +139,6 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
|
||||
public abstract RestfulOperationSystemEnum getSystemOperationType();
|
||||
|
||||
public OtherOperationTypeEnum getOtherOperationType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract boolean incomingServerRequestMatchesMethod(Request theRequest);
|
||||
|
||||
public abstract BaseHttpClientInvocation invokeClient(Object[] theArgs) throws InternalErrorException;
|
||||
|
@ -267,16 +267,14 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
if (theProvider instanceof IResourceProvider) {
|
||||
returnTypeFromRp = ((IResourceProvider) theProvider).getResourceType();
|
||||
if (!verifyIsValidResourceReturnType(returnTypeFromRp)) {
|
||||
throw new ConfigurationException("getResourceType() from " + IResourceProvider.class.getSimpleName() + " type " + theMethod.getDeclaringClass().getCanonicalName() + " returned "
|
||||
+ toLogString(returnTypeFromRp) + " - Must return a resource type");
|
||||
throw new ConfigurationException("getResourceType() from " + IResourceProvider.class.getSimpleName() + " type " + theMethod.getDeclaringClass().getCanonicalName() + " returned " + toLogString(returnTypeFromRp) + " - Must return a resource type");
|
||||
}
|
||||
}
|
||||
|
||||
Class<?> returnTypeFromMethod = theMethod.getReturnType();
|
||||
if (getTags != null) {
|
||||
if (!TagList.class.equals(returnTypeFromMethod)) {
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' from type " + theMethod.getDeclaringClass().getCanonicalName() + " is annotated with @"
|
||||
+ GetTags.class.getSimpleName() + " but does not return type " + TagList.class.getName());
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' from type " + theMethod.getDeclaringClass().getCanonicalName() + " is annotated with @" + GetTags.class.getSimpleName() + " but does not return type " + TagList.class.getName());
|
||||
}
|
||||
} else if (MethodOutcome.class.equals(returnTypeFromMethod)) {
|
||||
// returns a method outcome
|
||||
|
@ -289,15 +287,13 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
} else if (Collection.class.isAssignableFrom(returnTypeFromMethod)) {
|
||||
returnTypeFromMethod = ReflectionUtil.getGenericCollectionTypeOfMethodReturnType(theMethod);
|
||||
if (!verifyIsValidResourceReturnType(returnTypeFromMethod) && !IResource.class.equals(returnTypeFromMethod)) {
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' from " + IResourceProvider.class.getSimpleName() + " type " + theMethod.getDeclaringClass().getCanonicalName()
|
||||
+ " returns a collection with generic type " + toLogString(returnTypeFromMethod)
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' from " + IResourceProvider.class.getSimpleName() + " type " + theMethod.getDeclaringClass().getCanonicalName() + " returns a collection with generic type " + toLogString(returnTypeFromMethod)
|
||||
+ " - Must return a resource type or a collection (List, Set) with a resource type parameter (e.g. List<Patient> or List<IResource> )");
|
||||
}
|
||||
} else {
|
||||
if (!IResource.class.equals(returnTypeFromMethod) && !verifyIsValidResourceReturnType(returnTypeFromMethod)) {
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' from " + IResourceProvider.class.getSimpleName() + " type " + theMethod.getDeclaringClass().getCanonicalName()
|
||||
+ " returns " + toLogString(returnTypeFromMethod) + " - Must return a resource type (eg Patient, " + Bundle.class.getSimpleName() + ", "
|
||||
+ IBundleProvider.class.getSimpleName() + ", etc., see the documentation for more details)");
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' from " + IResourceProvider.class.getSimpleName() + " type " + theMethod.getDeclaringClass().getCanonicalName() + " returns " + toLogString(returnTypeFromMethod)
|
||||
+ " - Must return a resource type (eg Patient, " + Bundle.class.getSimpleName() + ", " + IBundleProvider.class.getSimpleName() + ", etc., see the documentation for more details)");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -327,13 +323,12 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
if (returnTypeFromRp != null) {
|
||||
if (returnTypeFromAnnotation != null && returnTypeFromAnnotation != IResource.class) {
|
||||
if (!returnTypeFromRp.isAssignableFrom(returnTypeFromAnnotation)) {
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' in type " + theMethod.getDeclaringClass().getCanonicalName() + " returns type "
|
||||
+ returnTypeFromMethod.getCanonicalName() + " - Must return " + returnTypeFromRp.getCanonicalName() + " (or a subclass of it) per IResourceProvider contract");
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' in type " + theMethod.getDeclaringClass().getCanonicalName() + " returns type " + returnTypeFromMethod.getCanonicalName() + " - Must return " + returnTypeFromRp.getCanonicalName()
|
||||
+ " (or a subclass of it) per IResourceProvider contract");
|
||||
}
|
||||
if (!returnTypeFromRp.isAssignableFrom(returnTypeFromAnnotation)) {
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' in type " + theMethod.getDeclaringClass().getCanonicalName() + " claims to return type "
|
||||
+ returnTypeFromAnnotation.getCanonicalName() + " per method annotation - Must return " + returnTypeFromRp.getCanonicalName()
|
||||
+ " (or a subclass of it) per IResourceProvider contract");
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' in type " + theMethod.getDeclaringClass().getCanonicalName() + " claims to return type " + returnTypeFromAnnotation.getCanonicalName() + " per method annotation - Must return "
|
||||
+ returnTypeFromRp.getCanonicalName() + " (or a subclass of it) per IResourceProvider contract");
|
||||
}
|
||||
returnType = returnTypeFromAnnotation;
|
||||
} else {
|
||||
|
@ -342,8 +337,8 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
} else {
|
||||
if (returnTypeFromAnnotation != IResource.class) {
|
||||
if (!verifyIsValidResourceReturnType(returnTypeFromAnnotation)) {
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' from " + IResourceProvider.class.getSimpleName() + " type "
|
||||
+ theMethod.getDeclaringClass().getCanonicalName() + " returns " + toLogString(returnTypeFromAnnotation) + " according to annotation - Must return a resource type");
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' from " + IResourceProvider.class.getSimpleName() + " type " + theMethod.getDeclaringClass().getCanonicalName() + " returns " + toLogString(returnTypeFromAnnotation)
|
||||
+ " according to annotation - Must return a resource type");
|
||||
}
|
||||
returnType = returnTypeFromAnnotation;
|
||||
} else {
|
||||
|
@ -354,7 +349,6 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
if (read != null) {
|
||||
return new ReadMethodBinding(returnType, theMethod, theContext, theProvider);
|
||||
} else if (search != null) {
|
||||
String queryName = search.queryName();
|
||||
return new SearchMethodBinding(returnType, theMethod, theContext, theProvider);
|
||||
} else if (conformance != null) {
|
||||
return new ConformanceMethodBinding(theMethod, theContext, theProvider);
|
||||
|
@ -409,8 +403,8 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
if (obj1 == null) {
|
||||
obj1 = object;
|
||||
} else {
|
||||
throw new ConfigurationException("Method " + theNextMethod.getName() + " on type '" + theNextMethod.getDeclaringClass().getSimpleName() + " has annotations @"
|
||||
+ obj1.getClass().getSimpleName() + " and @" + object.getClass().getSimpleName() + ". Can not have both.");
|
||||
throw new ConfigurationException("Method " + theNextMethod.getName() + " on type '" + theNextMethod.getDeclaringClass().getSimpleName() + " has annotations @" + obj1.getClass().getSimpleName() + " and @" + object.getClass().getSimpleName()
|
||||
+ ". Can not have both.");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,10 +18,13 @@ import javax.servlet.ServletRequest;
|
|||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.swing.text.html.Option;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.client.utils.DateUtils;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
|
@ -420,6 +423,7 @@ public class MethodUtil {
|
|||
parameter.setRequired(true);
|
||||
parameter.setDeclaredTypes(((RequiredParam) nextAnnotation).targetTypes());
|
||||
parameter.setCompositeTypes(((RequiredParam) nextAnnotation).compositeTypes());
|
||||
parameter.setChainlists(((RequiredParam) nextAnnotation).chainWhitelist(), ((RequiredParam) nextAnnotation).chainBlacklist());
|
||||
parameter.setType(parameterType, innerCollectionType, outerCollectionType);
|
||||
MethodUtil.extractDescription(parameter, annotations);
|
||||
param = parameter;
|
||||
|
@ -429,6 +433,7 @@ public class MethodUtil {
|
|||
parameter.setRequired(false);
|
||||
parameter.setDeclaredTypes(((OptionalParam) nextAnnotation).targetTypes());
|
||||
parameter.setCompositeTypes(((OptionalParam) nextAnnotation).compositeTypes());
|
||||
parameter.setChainlists(((OptionalParam) nextAnnotation).chainWhitelist(), ((OptionalParam) nextAnnotation).chainBlacklist());
|
||||
parameter.setType(parameterType, innerCollectionType, outerCollectionType);
|
||||
MethodUtil.extractDescription(parameter, annotations);
|
||||
param = parameter;
|
||||
|
|
|
@ -23,6 +23,7 @@ package ca.uhn.fhir.rest.method;
|
|||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
|
@ -54,13 +55,13 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
|||
public class SearchMethodBinding extends BaseResourceReturningMethodBinding {
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SearchMethodBinding.class);
|
||||
|
||||
private Class<? extends IResource> myDeclaredResourceType;
|
||||
private String myQueryName;
|
||||
private String myDescription;
|
||||
private String myCompartmentName;
|
||||
|
||||
private Class<? extends IResource> myDeclaredResourceType;
|
||||
private String myDescription;
|
||||
private Integer myIdParamIndex;
|
||||
|
||||
private String myQueryName;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public SearchMethodBinding(Class<? extends IResource> theReturnResourceType, Method theMethod, FhirContext theContext, Object theProvider) {
|
||||
super(theReturnResourceType, theMethod, theContext, theProvider);
|
||||
|
@ -79,7 +80,13 @@ public class SearchMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
}
|
||||
}
|
||||
|
||||
for (IParameter next : getParameters()) {
|
||||
/*
|
||||
* Check for parameter combinations and names that are invalid
|
||||
*/
|
||||
List<IParameter> parameters = getParameters();
|
||||
List<SearchParameter> searchParameters = new ArrayList<SearchParameter>();
|
||||
for (int i =0; i < parameters.size(); i++) {
|
||||
IParameter next = parameters.get(i);
|
||||
if (!(next instanceof SearchParameter)) {
|
||||
continue;
|
||||
}
|
||||
|
@ -91,8 +98,17 @@ public class SearchMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
throw new ConfigurationException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
searchParameters.add(sp);
|
||||
}
|
||||
|
||||
for (int i = 0; i < searchParameters.size(); i++) {
|
||||
SearchParameter next = searchParameters.get(i);
|
||||
// next.
|
||||
}
|
||||
|
||||
/*
|
||||
* Only compartment searching methods may have an ID parameter
|
||||
*/
|
||||
if (isBlank(myCompartmentName) && myIdParamIndex != null) {
|
||||
String msg = theContext.getLocalizer().getMessage(getClass().getName() + ".idWithoutCompartment", theMethod.getName(), theMethod.getDeclaringClass());
|
||||
throw new ConfigurationException(msg);
|
||||
|
@ -100,14 +116,14 @@ public class SearchMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return myDescription;
|
||||
}
|
||||
|
||||
public Class<? extends IResource> getDeclaredResourceType() {
|
||||
return myDeclaredResourceType;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return myDescription;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestfulOperationTypeEnum getResourceOperationType() {
|
||||
return RestfulOperationTypeEnum.SEARCH_TYPE;
|
||||
|
@ -123,100 +139,6 @@ public class SearchMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseHttpClientInvocation invokeClient(Object[] theArgs) throws InternalErrorException {
|
||||
assert (myQueryName == null || ((theArgs != null ? theArgs.length : 0) == getParameters().size())) : "Wrong number of arguments: " + (theArgs != null ? theArgs.length : "null");
|
||||
|
||||
Map<String, List<String>> queryStringArgs = new LinkedHashMap<String, List<String>>();
|
||||
|
||||
if (myQueryName != null) {
|
||||
queryStringArgs.put(Constants.PARAM_QUERY, Collections.singletonList(myQueryName));
|
||||
}
|
||||
|
||||
IdDt id = (IdDt) (myIdParamIndex != null ? theArgs[myIdParamIndex] : null);
|
||||
|
||||
String resourceName = getResourceName();
|
||||
BaseHttpClientInvocation retVal = createSearchInvocation(getContext(), resourceName, queryStringArgs, id, myCompartmentName, null);
|
||||
|
||||
if (theArgs != null) {
|
||||
for (int idx = 0; idx < theArgs.length; idx++) {
|
||||
IParameter nextParam = getParameters().get(idx);
|
||||
nextParam.translateClientArgumentIntoQueryArgument(getContext(), theArgs[idx], queryStringArgs, retVal);
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static BaseHttpClientInvocation createSearchInvocation(FhirContext theContext, String theResourceName, Map<String, List<String>> theParameters, IdDt theId, String theCompartmentName, SearchStyleEnum theSearchStyle) {
|
||||
SearchStyleEnum searchStyle = theSearchStyle;
|
||||
if (searchStyle == null) {
|
||||
int length = 0;
|
||||
for (Entry<String, List<String>> nextEntry : theParameters.entrySet()) {
|
||||
length += nextEntry.getKey().length();
|
||||
for (String next : nextEntry.getValue()) {
|
||||
length += next.length();
|
||||
}
|
||||
}
|
||||
|
||||
if (length < 5000) {
|
||||
searchStyle = SearchStyleEnum.GET;
|
||||
} else {
|
||||
searchStyle = SearchStyleEnum.POST;
|
||||
}
|
||||
}
|
||||
|
||||
BaseHttpClientInvocation invocation;
|
||||
|
||||
boolean compartmentSearch = false;
|
||||
if (theCompartmentName != null) {
|
||||
if (theId == null || !theId.hasIdPart()) {
|
||||
String msg = theContext.getLocalizer().getMessage(SearchMethodBinding.class.getName() + ".idNullForCompartmentSearch");
|
||||
throw new InvalidRequestException(msg);
|
||||
} else {
|
||||
compartmentSearch = true;
|
||||
}
|
||||
}
|
||||
|
||||
switch (searchStyle) {
|
||||
case GET:
|
||||
default:
|
||||
if (compartmentSearch) {
|
||||
invocation = new HttpGetClientInvocation(theParameters, theResourceName, theId.getIdPart(), theCompartmentName);
|
||||
} else {
|
||||
invocation = new HttpGetClientInvocation(theParameters, theResourceName);
|
||||
}
|
||||
break;
|
||||
case GET_WITH_SEARCH:
|
||||
if (compartmentSearch) {
|
||||
invocation = new HttpGetClientInvocation(theParameters, theResourceName, theId.getIdPart(), theCompartmentName, Constants.PARAM_SEARCH);
|
||||
} else {
|
||||
invocation = new HttpGetClientInvocation(theParameters, theResourceName, Constants.PARAM_SEARCH);
|
||||
}
|
||||
break;
|
||||
case POST:
|
||||
if (compartmentSearch) {
|
||||
invocation = new HttpPostClientInvocation(theContext, theParameters, theResourceName, theId.getIdPart(), theCompartmentName, Constants.PARAM_SEARCH);
|
||||
} else {
|
||||
invocation = new HttpPostClientInvocation(theContext, theParameters, theResourceName, Constants.PARAM_SEARCH);
|
||||
}
|
||||
}
|
||||
|
||||
return invocation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBundleProvider invokeServer(RequestDetails theRequest, Object[] theMethodParams) throws InvalidRequestException, InternalErrorException {
|
||||
if (myIdParamIndex != null) {
|
||||
theMethodParams[myIdParamIndex] = theRequest.getId();
|
||||
}
|
||||
|
||||
Object response = invokeServerMethod(theMethodParams);
|
||||
|
||||
return toResourceList(response);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean incomingServerRequestMatchesMethod(Request theRequest) {
|
||||
if (!theRequest.getResourceName().equals(getResourceName())) {
|
||||
|
@ -260,7 +182,9 @@ public class SearchMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
if (qualifiedParamNames.contains(name)) {
|
||||
methodParamsTemp.add(name);
|
||||
} else if (unqualifiedNames.contains(name)) {
|
||||
methodParamsTemp.addAll(theRequest.getUnqualifiedToQualifiedNames().get(name));
|
||||
List<String> qualifiedNames = theRequest.getUnqualifiedToQualifiedNames().get(name);
|
||||
qualifiedNames = processWhitelistAndBlacklist(qualifiedNames, temp.getQualifierWhitelist(), temp.getQualifierBlacklist());
|
||||
methodParamsTemp.addAll(qualifiedNames);
|
||||
} else {
|
||||
ourLog.trace("Method {} doesn't match param '{}' is not present", getMethod().getName(), name);
|
||||
return false;
|
||||
|
@ -270,7 +194,9 @@ public class SearchMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
if (qualifiedParamNames.contains(name)) {
|
||||
methodParamsTemp.add(name);
|
||||
} else if (unqualifiedNames.contains(name)) {
|
||||
methodParamsTemp.addAll(theRequest.getUnqualifiedToQualifiedNames().get(name));
|
||||
List<String> qualifiedNames = theRequest.getUnqualifiedToQualifiedNames().get(name);
|
||||
qualifiedNames = processWhitelistAndBlacklist(qualifiedNames, temp.getQualifierWhitelist(), temp.getQualifierBlacklist());
|
||||
methodParamsTemp.addAll(qualifiedNames);
|
||||
} else {
|
||||
methodParamsTemp.add(name);
|
||||
}
|
||||
|
@ -317,10 +243,135 @@ public class SearchMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseHttpClientInvocation invokeClient(Object[] theArgs) throws InternalErrorException {
|
||||
assert (myQueryName == null || ((theArgs != null ? theArgs.length : 0) == getParameters().size())) : "Wrong number of arguments: " + (theArgs != null ? theArgs.length : "null");
|
||||
|
||||
Map<String, List<String>> queryStringArgs = new LinkedHashMap<String, List<String>>();
|
||||
|
||||
if (myQueryName != null) {
|
||||
queryStringArgs.put(Constants.PARAM_QUERY, Collections.singletonList(myQueryName));
|
||||
}
|
||||
|
||||
IdDt id = (IdDt) (myIdParamIndex != null ? theArgs[myIdParamIndex] : null);
|
||||
|
||||
String resourceName = getResourceName();
|
||||
BaseHttpClientInvocation retVal = createSearchInvocation(getContext(), resourceName, queryStringArgs, id, myCompartmentName, null);
|
||||
|
||||
if (theArgs != null) {
|
||||
for (int idx = 0; idx < theArgs.length; idx++) {
|
||||
IParameter nextParam = getParameters().get(idx);
|
||||
nextParam.translateClientArgumentIntoQueryArgument(getContext(), theArgs[idx], queryStringArgs, retVal);
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBundleProvider invokeServer(RequestDetails theRequest, Object[] theMethodParams) throws InvalidRequestException, InternalErrorException {
|
||||
if (myIdParamIndex != null) {
|
||||
theMethodParams[myIdParamIndex] = theRequest.getId();
|
||||
}
|
||||
|
||||
Object response = invokeServerMethod(theMethodParams);
|
||||
|
||||
return toResourceList(response);
|
||||
|
||||
}
|
||||
|
||||
public void setResourceType(Class<? extends IResource> resourceType) {
|
||||
this.myDeclaredResourceType = resourceType;
|
||||
}
|
||||
|
||||
private List<String> processWhitelistAndBlacklist(List<String> theQualifiedNames, Set<String> theQualifierWhitelist, Set<String> theQualifierBlacklist) {
|
||||
if (theQualifierWhitelist == null && theQualifierBlacklist == null) {
|
||||
return theQualifiedNames;
|
||||
}
|
||||
ArrayList<String> retVal = new ArrayList<String>(theQualifiedNames.size());
|
||||
for (String next : theQualifiedNames) {
|
||||
String qualifier = "";
|
||||
int idx = next.indexOf('.');
|
||||
if (idx > -1 && next.length() > (idx + 1)) {
|
||||
qualifier = next.substring(idx);
|
||||
}
|
||||
|
||||
if (theQualifierWhitelist != null) {
|
||||
if (!theQualifierWhitelist.contains(qualifier)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (theQualifierBlacklist != null) {
|
||||
if (theQualifierBlacklist.contains(qualifier)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
retVal.add(next);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static BaseHttpClientInvocation createSearchInvocation(FhirContext theContext, String theResourceName, Map<String, List<String>> theParameters, IdDt theId, String theCompartmentName, SearchStyleEnum theSearchStyle) {
|
||||
SearchStyleEnum searchStyle = theSearchStyle;
|
||||
if (searchStyle == null) {
|
||||
int length = 0;
|
||||
for (Entry<String, List<String>> nextEntry : theParameters.entrySet()) {
|
||||
length += nextEntry.getKey().length();
|
||||
for (String next : nextEntry.getValue()) {
|
||||
length += next.length();
|
||||
}
|
||||
}
|
||||
|
||||
if (length < 5000) {
|
||||
searchStyle = SearchStyleEnum.GET;
|
||||
} else {
|
||||
searchStyle = SearchStyleEnum.POST;
|
||||
}
|
||||
}
|
||||
|
||||
BaseHttpClientInvocation invocation;
|
||||
|
||||
boolean compartmentSearch = false;
|
||||
if (theCompartmentName != null) {
|
||||
if (theId == null || !theId.hasIdPart()) {
|
||||
String msg = theContext.getLocalizer().getMessage(SearchMethodBinding.class.getName() + ".idNullForCompartmentSearch");
|
||||
throw new InvalidRequestException(msg);
|
||||
} else {
|
||||
compartmentSearch = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Are we doing a get (GET [base]/Patient?name=foo) or a get with search (GET [base]/Patient/_search?name=foo)
|
||||
* or a post (POST [base]/Patient with parameters in the POST body)
|
||||
*/
|
||||
switch (searchStyle) {
|
||||
case GET:
|
||||
default:
|
||||
if (compartmentSearch) {
|
||||
invocation = new HttpGetClientInvocation(theParameters, theResourceName, theId.getIdPart(), theCompartmentName);
|
||||
} else {
|
||||
invocation = new HttpGetClientInvocation(theParameters, theResourceName);
|
||||
}
|
||||
break;
|
||||
case GET_WITH_SEARCH:
|
||||
if (compartmentSearch) {
|
||||
invocation = new HttpGetClientInvocation(theParameters, theResourceName, theId.getIdPart(), theCompartmentName, Constants.PARAM_SEARCH);
|
||||
} else {
|
||||
invocation = new HttpGetClientInvocation(theParameters, theResourceName, Constants.PARAM_SEARCH);
|
||||
}
|
||||
break;
|
||||
case POST:
|
||||
if (compartmentSearch) {
|
||||
invocation = new HttpPostClientInvocation(theContext, theParameters, theResourceName, theId.getIdPart(), theCompartmentName, Constants.PARAM_SEARCH);
|
||||
} else {
|
||||
invocation = new HttpPostClientInvocation(theContext, theParameters, theResourceName, Constants.PARAM_SEARCH);
|
||||
}
|
||||
}
|
||||
|
||||
return invocation;
|
||||
}
|
||||
|
||||
public static enum RequestType {
|
||||
DELETE, GET, OPTIONS, POST, PUT
|
||||
}
|
||||
|
|
|
@ -25,7 +25,9 @@ import java.util.Arrays;
|
|||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
|
||||
|
@ -39,6 +41,7 @@ import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
|
|||
import ca.uhn.fhir.model.dstu.composite.QuantityDt;
|
||||
import ca.uhn.fhir.model.dstu.valueset.SearchParamTypeEnum;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.rest.annotation.OptionalParam;
|
||||
import ca.uhn.fhir.rest.param.BaseQueryParameter;
|
||||
import ca.uhn.fhir.rest.param.CodingListParam;
|
||||
import ca.uhn.fhir.rest.param.CompositeAndListParam;
|
||||
|
@ -107,6 +110,8 @@ public class SearchParameter extends BaseQueryParameter {
|
|||
ourParamTypes.put(CompositeOrListParam.class, SearchParamTypeEnum.COMPOSITE);
|
||||
ourParamTypes.put(CompositeAndListParam.class, SearchParamTypeEnum.COMPOSITE);
|
||||
}
|
||||
private Set<String> myQualifierBlacklist;
|
||||
private Set<String> myQualifierWhitelist;
|
||||
private List<Class<? extends IQueryParameterType>> myCompositeTypes;
|
||||
private List<Class<? extends IResource>> myDeclaredTypes;
|
||||
private String myDescription;
|
||||
|
@ -114,7 +119,6 @@ public class SearchParameter extends BaseQueryParameter {
|
|||
private IParamBinder myParamBinder;
|
||||
private SearchParamTypeEnum myParamType;
|
||||
private boolean myRequired;
|
||||
|
||||
private Class<?> myType;
|
||||
|
||||
public SearchParameter() {
|
||||
|
@ -142,6 +146,16 @@ public class SearchParameter extends BaseQueryParameter {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getQualifierBlacklist() {
|
||||
return myQualifierBlacklist;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getQualifierWhitelist() {
|
||||
return myQualifierWhitelist;
|
||||
}
|
||||
|
||||
public List<Class<? extends IResource>> getDeclaredTypes() {
|
||||
return Collections.unmodifiableList(myDeclaredTypes);
|
||||
}
|
||||
|
@ -189,6 +203,31 @@ public class SearchParameter extends BaseQueryParameter {
|
|||
return myParamBinder.parse(getName(), theString);
|
||||
}
|
||||
|
||||
public void setChainlists(String[] theChainWhitelist, String[] theChainBlacklist) {
|
||||
myQualifierWhitelist = new HashSet<String>(theChainWhitelist.length);
|
||||
for (int i = 0; i < theChainWhitelist.length; i++) {
|
||||
if (theChainWhitelist[i].equals(OptionalParam.ALLOW_CHAIN_ANY)) {
|
||||
myQualifierWhitelist = null;
|
||||
break;
|
||||
} else if (theChainWhitelist[i].equals("")) {
|
||||
myQualifierWhitelist.add("");
|
||||
} else {
|
||||
myQualifierWhitelist.add('.' + theChainWhitelist[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (theChainBlacklist.length > 0) {
|
||||
myQualifierBlacklist = new HashSet<String>(theChainBlacklist.length);
|
||||
for (String next : theChainBlacklist) {
|
||||
if (next.equals("")) {
|
||||
myQualifierBlacklist.add("");
|
||||
} else {
|
||||
myQualifierBlacklist.add('.' + next);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setCompositeTypes(Class<? extends IQueryParameterType>[] theCompositeTypes) {
|
||||
myCompositeTypes = Arrays.asList(theCompositeTypes);
|
||||
}
|
||||
|
@ -215,7 +254,7 @@ public class SearchParameter extends BaseQueryParameter {
|
|||
if (IQueryParameterType.class.isAssignableFrom(type)) {
|
||||
myParamBinder = new QueryParameterTypeBinder((Class<? extends IQueryParameterType>) type, myCompositeTypes);
|
||||
} else if (IQueryParameterOr.class.isAssignableFrom(type)) {
|
||||
myParamBinder = new QueryParameterOrBinder((Class<? extends IQueryParameterOr<?>>) type,myCompositeTypes);
|
||||
myParamBinder = new QueryParameterOrBinder((Class<? extends IQueryParameterOr<?>>) type, myCompositeTypes);
|
||||
} else if (IQueryParameterAnd.class.isAssignableFrom(type)) {
|
||||
myParamBinder = new QueryParameterAndBinder((Class<? extends IQueryParameterAnd<?>>) type, myCompositeTypes);
|
||||
} else if (String.class.equals(type)) {
|
||||
|
|
|
@ -20,11 +20,14 @@ package ca.uhn.fhir.rest.param;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
|
@ -113,6 +116,17 @@ public abstract class BaseQueryParameter implements IParameter {
|
|||
}
|
||||
|
||||
private void parseParams(RequestDetails theRequest, List<QualifiedParamList> paramList, String theQualifiedParamName, String theQualifier) {
|
||||
if (getQualifierWhitelist() != null) {
|
||||
if (!getQualifierWhitelist().contains(defaultString(theQualifier)) ){
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (getQualifierBlacklist() != null) {
|
||||
if (getQualifierBlacklist().contains(defaultString(theQualifier))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
String[] value = theRequest.getParameters().get(theQualifiedParamName);
|
||||
if (value != null) {
|
||||
for (String nextParam : value) {
|
||||
|
@ -129,5 +143,19 @@ public abstract class BaseQueryParameter implements IParameter {
|
|||
public void initializeTypes(Method theMethod, Class<? extends Collection<?>> theOuterCollectionType, Class<? extends Collection<?>> theInnerCollectionType, Class<?> theParameterType) {
|
||||
// ignore for now
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns null if blacklist is "none"
|
||||
*/
|
||||
public Set<String> getQualifierBlacklist() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns null if whitelist is "all"
|
||||
*/
|
||||
public Set<String> getQualifierWhitelist() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package ca.uhn.fhir.rest.server;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
@ -32,6 +34,7 @@ import ca.uhn.fhir.model.dstu.valueset.ResourceTypeEnum;
|
|||
import ca.uhn.fhir.rest.annotation.OptionalParam;
|
||||
import ca.uhn.fhir.rest.annotation.Search;
|
||||
import ca.uhn.fhir.rest.param.ReferenceParam;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import ca.uhn.fhir.testutil.RandomServerPortProvider;
|
||||
|
||||
/**
|
||||
|
@ -99,6 +102,68 @@ public class ReferenceParameterTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithMultipleParamsOfTheSameName1() throws Exception {
|
||||
{
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Organization?partof=po123");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
assertThat(responseContent, containsString("value=\"thePartOfId po123 null\""));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithMultipleParamsOfTheSameName2() throws Exception {
|
||||
{
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Organization?partof.name=poname");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
assertThat(responseContent, containsString("value=\"thePartOfName poname\""));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithMultipleParamsOfTheSameName3() throws Exception {
|
||||
{
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Organization?partof=po123&partof.name=poname");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
assertThat(responseContent, containsString("value=\"thePartOfId po123 null\""));
|
||||
assertThat(responseContent, containsString("value=\"thePartOfName poname\""));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithMultipleParamsOfTheSameName4() throws Exception {
|
||||
{
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Organization?partof.fooChain=po123&partof.name=poname");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
assertThat(responseContent, containsString("value=\"thePartOfId po123 fooChain\""));
|
||||
assertThat(responseContent, containsString("value=\"thePartOfName poname\""));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithMultipleParamsOfTheSameName5() throws Exception {
|
||||
{
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Organization?partof.bar=po123");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
assertThat(responseContent, containsString("value=\"theBarId po123 bar\""));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithValueAndChain() throws Exception {
|
||||
{
|
||||
|
@ -116,7 +181,9 @@ public class ReferenceParameterTest {
|
|||
assertEquals("2name", p.getName().get(2).getFamilyFirstRep().getValue());
|
||||
}
|
||||
}
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ReferenceParameterTest.class);
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ReferenceParameterTest.class);
|
||||
|
||||
@Test
|
||||
public void testParamTypesInConformanceStatement() throws Exception {
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/metadata?_pretty=true");
|
||||
|
@ -125,20 +192,20 @@ private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger
|
|||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
ourLog.info(responseContent);
|
||||
|
||||
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
Conformance conf = ourCtx.newXmlParser().parseResource(Conformance.class,responseContent);
|
||||
|
||||
RestResource res = conf.getRestFirstRep().getResourceFirstRep();
|
||||
Conformance conf = ourCtx.newXmlParser().parseResource(Conformance.class, responseContent);
|
||||
|
||||
RestResource res = conf.getRestFirstRep().getResource().get(1);
|
||||
assertEquals("Patient", res.getType().getValue());
|
||||
|
||||
|
||||
RestResourceSearchParam param = res.getSearchParamFirstRep();
|
||||
assertEquals(Patient.SP_PROVIDER, param.getName().getValue());
|
||||
|
||||
|
||||
assertEquals(1, param.getTarget().size());
|
||||
assertEquals(ResourceTypeEnum.ORGANIZATION, param.getTarget().get(0).getValueAsEnum());
|
||||
}
|
||||
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() throws Exception {
|
||||
ourServer.stop();
|
||||
|
@ -154,7 +221,7 @@ private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger
|
|||
ServletHandler proxyHandler = new ServletHandler();
|
||||
RestfulServer servlet = new RestfulServer();
|
||||
ourCtx = servlet.getFhirContext();
|
||||
servlet.setResourceProviders(patientProvider);
|
||||
servlet.setResourceProviders(patientProvider, new DummyOrganizationResourceProvider());
|
||||
ServletHolder servletHolder = new ServletHolder(servlet);
|
||||
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
||||
ourServer.setHandler(proxyHandler);
|
||||
|
@ -168,13 +235,78 @@ private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger
|
|||
ourCtx = servlet.getFhirContext();
|
||||
}
|
||||
|
||||
public static class DummyOrganizationResourceProvider implements IResourceProvider {
|
||||
|
||||
@Override
|
||||
public Class<? extends IResource> getResourceType() {
|
||||
return Organization.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* https://github.com/jamesagnew/hapi-fhir/issues/18
|
||||
*/
|
||||
//@formatter:off
|
||||
@Search
|
||||
public List<Organization> searchByName(
|
||||
@OptionalParam(name = "partof", chainWhitelist= {"", "fooChain"}) ReferenceParam thePartOfId,
|
||||
@OptionalParam(name = "partof.name") StringParam thePartOfName) {
|
||||
//@formatter:on
|
||||
|
||||
ArrayList<Organization> retVal = new ArrayList<Organization>();
|
||||
if (thePartOfId != null) {
|
||||
Organization org = new Organization();
|
||||
org.setId("1");
|
||||
org.getName().setValue("thePartOfId " + thePartOfId.getValue() + " " + thePartOfId.getChain());
|
||||
retVal.add(org);
|
||||
}
|
||||
if (thePartOfName != null) {
|
||||
Organization org = new Organization();
|
||||
org.setId("2");
|
||||
org.getName().setValue("thePartOfName " + thePartOfName.getValue());
|
||||
retVal.add(org);
|
||||
}
|
||||
if (retVal.isEmpty()) {
|
||||
Organization org = new Organization();
|
||||
org.setId("0");
|
||||
org.getName().setValue("none");
|
||||
retVal.add(org);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
//@formatter:off
|
||||
@Search
|
||||
public List<Organization> searchByNameWithDifferentChain(
|
||||
@OptionalParam(name = "partof", chainWhitelist= {"bar"}) ReferenceParam theBarId) {
|
||||
//@formatter:on
|
||||
|
||||
ArrayList<Organization> retVal = new ArrayList<Organization>();
|
||||
if (theBarId != null) {
|
||||
Organization org = new Organization();
|
||||
org.setId("1");
|
||||
org.getName().setValue("theBarId " + theBarId.getValue() + " " + theBarId.getChain());
|
||||
retVal.add(org);
|
||||
}
|
||||
if (retVal.isEmpty()) {
|
||||
Organization org = new Organization();
|
||||
org.setId("0");
|
||||
org.getName().setValue("none");
|
||||
retVal.add(org);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Created by dsotnikov on 2/25/2014.
|
||||
*/
|
||||
public static class DummyPatientResourceProvider implements IResourceProvider {
|
||||
|
||||
@Search
|
||||
public List<Patient> findPatient(@OptionalParam(name = Patient.SP_PROVIDER, targetTypes= {Organization.class}) ReferenceParam theParam) {
|
||||
public List<Patient> findPatient(@OptionalParam(name = Patient.SP_PROVIDER, targetTypes = { Organization.class }) ReferenceParam theParam) {
|
||||
ArrayList<Patient> retVal = new ArrayList<Patient>();
|
||||
|
||||
Patient p = new Patient();
|
||||
|
|
Loading…
Reference in New Issue