More client work
This commit is contained in:
parent
b05ea01b45
commit
82193017d8
|
@ -3,7 +3,7 @@
|
||||||
<classpathentry including="**/*.java" kind="src" output="target/test-classes" path="src/test/java"/>
|
<classpathentry including="**/*.java" kind="src" output="target/test-classes" path="src/test/java"/>
|
||||||
<classpathentry excluding="**/*.java" kind="src" output="target/test-classes" path="src/test/resources"/>
|
<classpathentry excluding="**/*.java" kind="src" output="target/test-classes" path="src/test/resources"/>
|
||||||
<classpathentry including="**/*.java" kind="src" path="src/main/java"/>
|
<classpathentry including="**/*.java" kind="src" path="src/main/java"/>
|
||||||
<classpathentry kind="var" path="M2_REPO/javax/servlet/javax.servlet-api/3.1.0/javax.servlet-api-3.1.0.jar" sourcepath="M2_REPO/javax/servlet/javax.servlet-api/3.1.0/javax.servlet-api-3.1.0-sources.jar">
|
<classpathentry kind="var" path="M2_REPO/javax/servlet/javax.servlet-api/3.0.1/javax.servlet-api-3.0.1.jar" sourcepath="M2_REPO/javax/servlet/javax.servlet-api/3.1.0/javax.servlet-api-3.1.0-sources.jar">
|
||||||
<attributes>
|
<attributes>
|
||||||
<attribute name="javadoc_location" value="jar:file:/Users/james/.m2/repository/javax/servlet/javax.servlet-api/3.1.0/javax.servlet-api-3.1.0-javadoc.jar!/"/>
|
<attribute name="javadoc_location" value="jar:file:/Users/james/.m2/repository/javax/servlet/javax.servlet-api/3.1.0/javax.servlet-api-3.1.0-javadoc.jar!/"/>
|
||||||
</attributes>
|
</attributes>
|
||||||
|
@ -80,8 +80,7 @@
|
||||||
<attribute name="javadoc_location" value="jar:file:/Users/james/.m2/repository/xmlunit/xmlunit/1.5/xmlunit-1.5-javadoc.jar!/"/>
|
<attribute name="javadoc_location" value="jar:file:/Users/james/.m2/repository/xmlunit/xmlunit/1.5/xmlunit-1.5-javadoc.jar!/"/>
|
||||||
</attributes>
|
</attributes>
|
||||||
</classpathentry>
|
</classpathentry>
|
||||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
|
||||||
<classpathentry kind="var" path="M2_REPO/org/mockito/mockito-all/1.9.5/mockito-all-1.9.5.jar"/>
|
<classpathentry kind="var" path="M2_REPO/org/mockito/mockito-all/1.9.5/mockito-all-1.9.5.jar"/>
|
||||||
<classpathentry combineaccessrules="false" kind="src" path="/hapi-fhir-structures-dstu"/>
|
|
||||||
<classpathentry kind="output" path="target/classes"/>
|
<classpathentry kind="output" path="target/classes"/>
|
||||||
</classpath>
|
</classpath>
|
||||||
|
|
|
@ -5,10 +5,18 @@ import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.METHOD)
|
@Target(ElementType.METHOD)
|
||||||
public @interface Read {
|
public @interface Read {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the resource type that is returned by the method annotated
|
||||||
|
* with this annotation
|
||||||
|
*/
|
||||||
|
Class<? extends IResource> value();
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.PARAMETER)
|
@Target(ElementType.PARAMETER)
|
||||||
public @interface IdParam {
|
public @interface IdParam {
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
package ca.uhn.fhir.rest.client;
|
||||||
|
|
||||||
|
public class ClientInvocation {
|
||||||
|
|
||||||
|
}
|
|
@ -2,21 +2,34 @@ package ca.uhn.fhir.rest.client;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationHandler;
|
import java.lang.reflect.InvocationHandler;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.http.client.HttpClient;
|
import org.apache.http.client.HttpClient;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.rest.common.BaseMethodBinding;
|
||||||
|
|
||||||
public class ClientInvocationHandler implements InvocationHandler {
|
public class ClientInvocationHandler implements InvocationHandler {
|
||||||
|
|
||||||
private HttpClient myClient;
|
private HttpClient myClient;
|
||||||
|
private Map<Method, BaseMethodBinding> myBindings = new HashMap<Method, BaseMethodBinding>();
|
||||||
|
private FhirContext myContext;
|
||||||
|
|
||||||
public ClientInvocationHandler(HttpClient theClient) {
|
public ClientInvocationHandler(HttpClient theClient, FhirContext theContext) {
|
||||||
myClient = theClient;
|
myClient = theClient;
|
||||||
|
myContext = theContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object invoke(Object theProxy, Method theMethod, Object[] theArgs) throws Throwable {
|
public Object invoke(Object theProxy, Method theMethod, Object[] theArgs) throws Throwable {
|
||||||
// TODO Auto-generated method stub
|
BaseMethodBinding binding = myBindings.get(theMethod);
|
||||||
|
ClientInvocation clientInvocation = binding.invokeClient(theArgs);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addBinding(Method theMethod, BaseMethodBinding theBinding) {
|
||||||
|
myBindings.put(theMethod, theBinding);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package ca.uhn.fhir.rest.client;
|
package ca.uhn.fhir.rest.client;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationHandler;
|
import java.lang.reflect.InvocationHandler;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Proxy;
|
import java.lang.reflect.Proxy;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@ -11,7 +12,9 @@ import org.apache.http.impl.conn.SchemeRegistryFactory;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.ConfigurationException;
|
import ca.uhn.fhir.context.ConfigurationException;
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
import ca.uhn.fhir.rest.client.api.IRestfulClient;
|
import ca.uhn.fhir.rest.client.api.IRestfulClient;
|
||||||
|
import ca.uhn.fhir.rest.common.BaseMethodBinding;
|
||||||
|
|
||||||
public class RestfulClientFactory {
|
public class RestfulClientFactory {
|
||||||
|
|
||||||
|
@ -20,41 +23,50 @@ public class RestfulClientFactory {
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
* @param theContext The context
|
* @param theContext
|
||||||
|
* The context
|
||||||
*/
|
*/
|
||||||
public RestfulClientFactory(FhirContext theContext) {
|
public RestfulClientFactory(FhirContext theContext) {
|
||||||
myContext = theContext;
|
myContext = theContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new client instance
|
* Instantiates a new client instance
|
||||||
*
|
*
|
||||||
* @param theClientType The client type, which is an interface type to be instantiated
|
* @param theClientType
|
||||||
* @param theServerBase The URL of the base for the restful FHIR server to connect to
|
* The client type, which is an interface type to be instantiated
|
||||||
|
* @param theServerBase
|
||||||
|
* The URL of the base for the restful FHIR server to connect to
|
||||||
* @return A newly created client
|
* @return A newly created client
|
||||||
* @throws ConfigurationException If the interface type is not an interface
|
* @throws ConfigurationException
|
||||||
|
* If the interface type is not an interface
|
||||||
*/
|
*/
|
||||||
public <T extends IRestfulClient> T newClient(Class<T> theClientType, String theServerBase) {
|
public <T extends IRestfulClient> T newClient(Class<T> theClientType, String theServerBase){
|
||||||
if (!theClientType.isInterface()) {
|
if (!theClientType.isInterface()) {
|
||||||
throw new ConfigurationException(theClientType.getCanonicalName() + " is not an interface");
|
throw new ConfigurationException(theClientType.getCanonicalName() + " is not an interface");
|
||||||
}
|
}
|
||||||
|
|
||||||
PoolingClientConnectionManager connectionManager = new PoolingClientConnectionManager(SchemeRegistryFactory.createDefault(), 5000, TimeUnit.MILLISECONDS);
|
PoolingClientConnectionManager connectionManager = new PoolingClientConnectionManager(SchemeRegistryFactory.createDefault(), 5000, TimeUnit.MILLISECONDS);
|
||||||
HttpClient client = new DefaultHttpClient(connectionManager);
|
HttpClient client = new DefaultHttpClient(connectionManager);
|
||||||
|
|
||||||
ClientInvocationHandler theInvocationHandler = new ClientInvocationHandler(client);
|
ClientInvocationHandler theInvocationHandler = new ClientInvocationHandler(client, myContext);
|
||||||
|
|
||||||
|
for (Method nextMethod : theClientType.getMethods()) {
|
||||||
|
BaseMethodBinding binding = BaseMethodBinding.bindMethod(nextMethod);
|
||||||
|
theInvocationHandler.addBinding(nextMethod, binding);
|
||||||
|
}
|
||||||
|
|
||||||
T proxy = instantiateProxy(theClientType, theInvocationHandler);
|
T proxy = instantiateProxy(theClientType, theInvocationHandler);
|
||||||
|
|
||||||
return proxy;
|
return proxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private <T extends IRestfulClient> T instantiateProxy(Class<T> theClientType, InvocationHandler theInvocationHandler) {
|
private <T extends IRestfulClient> T instantiateProxy(Class<T> theClientType, InvocationHandler theInvocationHandler) {
|
||||||
T proxy = (T) Proxy.newProxyInstance(RestfulClientFactory.class.getClassLoader(), new Class[] {theClientType}, theInvocationHandler);
|
T proxy = (T) Proxy.newProxyInstance(RestfulClientFactory.class.getClassLoader(), new Class[] { theClientType }, theInvocationHandler);
|
||||||
return proxy;
|
return proxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,131 @@
|
||||||
|
package ca.uhn.fhir.rest.common;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.ConfigurationException;
|
||||||
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
|
import ca.uhn.fhir.model.api.annotation.ResourceDef;
|
||||||
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
|
import ca.uhn.fhir.rest.annotation.Read;
|
||||||
|
import ca.uhn.fhir.rest.client.ClientInvocation;
|
||||||
|
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||||
|
import ca.uhn.fhir.rest.server.Resource;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
|
import ca.uhn.fhir.rest.server.operations.Search;
|
||||||
|
|
||||||
|
public abstract class BaseMethodBinding {
|
||||||
|
|
||||||
|
private String myResourceName;
|
||||||
|
|
||||||
|
public BaseMethodBinding(Class<? extends IResource> theAnnotatedResourceType) {
|
||||||
|
ResourceDef resourceDefAnnotation = theAnnotatedResourceType.getAnnotation(ResourceDef.class);
|
||||||
|
if (resourceDefAnnotation == null) {
|
||||||
|
throw new ConfigurationException(theAnnotatedResourceType.getCanonicalName() + " has no @" + ResourceDef.class.getSimpleName()+ " annotation");
|
||||||
|
}
|
||||||
|
myResourceName = resourceDefAnnotation.name();
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract ReturnTypeEnum getReturnType();
|
||||||
|
|
||||||
|
public ClientInvocation invokeClient(Object[] theArgs) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract List<IResource> invokeServer(IResourceProvider theResourceProvider, IdDt theId, IdDt theVersionId, Map<String, String[]> theParameterValues) throws InvalidRequestException, InternalErrorException;
|
||||||
|
|
||||||
|
public abstract boolean matches(String theResourceName, IdDt theId, IdDt theVersion, Set<String> theParameterNames);
|
||||||
|
|
||||||
|
public String getResourceName() {
|
||||||
|
return myResourceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BaseMethodBinding bindMethod(Method theMethod) {
|
||||||
|
Read read = theMethod.getAnnotation(Read.class);
|
||||||
|
Search search = theMethod.getAnnotation(Search.class);
|
||||||
|
verifyExactlyOneValued(theMethod, read, search);
|
||||||
|
|
||||||
|
Class<? extends IResource> annotatedResourceType;
|
||||||
|
if (read != null) {
|
||||||
|
annotatedResourceType = read.value();
|
||||||
|
} else {
|
||||||
|
annotatedResourceType = search.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
Class<?> methodReturnType = theMethod.getReturnType();
|
||||||
|
|
||||||
|
if (read != null) {
|
||||||
|
return new ReadMethodBinding(annotatedResourceType, theMethod);
|
||||||
|
} else if (search != null) {
|
||||||
|
return new SearchMethodBinding(annotatedResourceType, theMethod);
|
||||||
|
} else {
|
||||||
|
throw new ConfigurationException("Did not detect any FHIR annotations on method '" + theMethod.getName() + "' on type: " + theMethod.getDeclaringClass().getCanonicalName());
|
||||||
|
}
|
||||||
|
|
||||||
|
// // each operation name must have a request type annotation and be
|
||||||
|
// unique
|
||||||
|
// if (null != read) {
|
||||||
|
// return rm;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// SearchMethodBinding sm = new SearchMethodBinding();
|
||||||
|
// if (null != search) {
|
||||||
|
// sm.setRequestType(SearchMethodBinding.RequestType.GET);
|
||||||
|
// } else if (null != theMethod.getAnnotation(PUT.class)) {
|
||||||
|
// sm.setRequestType(SearchMethodBinding.RequestType.PUT);
|
||||||
|
// } else if (null != theMethod.getAnnotation(POST.class)) {
|
||||||
|
// sm.setRequestType(SearchMethodBinding.RequestType.POST);
|
||||||
|
// } else if (null != theMethod.getAnnotation(DELETE.class)) {
|
||||||
|
// sm.setRequestType(SearchMethodBinding.RequestType.DELETE);
|
||||||
|
// } else {
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void verifyExactlyOneValued(Method theNextMethod, Object... theAnnotations) {
|
||||||
|
Object obj1 = null;
|
||||||
|
for (Object object : theAnnotations) {
|
||||||
|
if (object != null) {
|
||||||
|
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.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (obj1 == null) {
|
||||||
|
throw new ConfigurationException("Method " + theNextMethod.getName() + " on type '" + theNextMethod.getDeclaringClass().getSimpleName() + " has no FHIR method annotations.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static List<IResource> toResourceList(Object response) throws InternalErrorException {
|
||||||
|
if (response == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
} else if (response instanceof IResource) {
|
||||||
|
return Collections.singletonList((IResource) response);
|
||||||
|
} else if (response instanceof Collection) {
|
||||||
|
List<IResource> retVal = new ArrayList<IResource>();
|
||||||
|
for (Object next : ((Collection<?>) response)) {
|
||||||
|
retVal.add((IResource) next);
|
||||||
|
}
|
||||||
|
return retVal;
|
||||||
|
} else {
|
||||||
|
throw new InternalErrorException("Unexpected return type: " + response.getClass().getCanonicalName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ReturnTypeEnum {
|
||||||
|
BUNDLE, RESOURCE
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package ca.uhn.fhir.rest.server;
|
package ca.uhn.fhir.rest.common;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -10,23 +10,29 @@ import org.apache.commons.lang3.Validate;
|
||||||
import ca.uhn.fhir.context.ConfigurationException;
|
import ca.uhn.fhir.context.ConfigurationException;
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
import ca.uhn.fhir.model.primitive.IdDt;
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
|
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||||
|
import ca.uhn.fhir.rest.server.Util;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
|
|
||||||
class ReadMethod extends BaseMethod {
|
public class ReadMethodBinding extends BaseMethodBinding {
|
||||||
|
|
||||||
private Method myMethod;
|
private Method myMethod;
|
||||||
private Integer myIdIndex;
|
private Integer myIdIndex;
|
||||||
private Integer myVersionIdIndex;
|
private Integer myVersionIdIndex;
|
||||||
private int myParameterCount;
|
private int myParameterCount;
|
||||||
|
|
||||||
ReadMethod(Method theMethod, Integer theIdIndex, Integer theVersionIdIndex) {
|
public ReadMethodBinding(Class<? extends IResource> theAnnotatedResourceType, Method theMethod) {
|
||||||
Validate.notNull(theMethod, "Method must not be null");
|
super(theAnnotatedResourceType);
|
||||||
Validate.notNull(theIdIndex, "ID Index must not be null");
|
|
||||||
|
|
||||||
|
Validate.notNull(theMethod, "Method must not be null");
|
||||||
|
|
||||||
|
Integer idIndex = Util.findReadIdParameterIndex(theMethod);
|
||||||
|
Integer versionIdIndex = Util.findReadVersionIdParameterIndex(theMethod);
|
||||||
|
|
||||||
myMethod = theMethod;
|
myMethod = theMethod;
|
||||||
myIdIndex = theIdIndex;
|
myIdIndex = idIndex;
|
||||||
myVersionIdIndex = theVersionIdIndex;
|
myVersionIdIndex = versionIdIndex;
|
||||||
myParameterCount = myMethod.getParameterTypes().length;
|
myParameterCount = myMethod.getParameterTypes().length;
|
||||||
|
|
||||||
Class<?>[] parameterTypes = theMethod.getParameterTypes();
|
Class<?>[] parameterTypes = theMethod.getParameterTypes();
|
||||||
|
@ -41,7 +47,7 @@ class ReadMethod extends BaseMethod {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean matches(String theResourceName, IdDt theId, IdDt theVersion, Set<String> theParameterNames) {
|
public boolean matches(String theResourceName, IdDt theId, IdDt theVersion, Set<String> theParameterNames) {
|
||||||
if (!theResourceName.equals(getResource().getResourceName())) {
|
if (!theResourceName.equals(getResourceName())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (theParameterNames.isEmpty() == false) {
|
if (theParameterNames.isEmpty() == false) {
|
||||||
|
@ -62,7 +68,7 @@ class ReadMethod extends BaseMethod {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<IResource> invoke(IResourceProvider theResourceProvider, IdDt theId, IdDt theVersionId, Map<String, String[]> theParameterValues) throws InvalidRequestException,
|
public List<IResource> invokeServer(IResourceProvider theResourceProvider, IdDt theId, IdDt theVersionId, Map<String, String[]> theParameterValues) throws InvalidRequestException,
|
||||||
InternalErrorException {
|
InternalErrorException {
|
||||||
Object[] params = new Object[myParameterCount];
|
Object[] params = new Object[myParameterCount];
|
||||||
params[myIdIndex] = theId;
|
params[myIdIndex] = theId;
|
|
@ -1,41 +1,41 @@
|
||||||
package ca.uhn.fhir.rest.server;
|
package ca.uhn.fhir.rest.common;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.junit.internal.MethodSorter;
|
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.ConfigurationException;
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
import ca.uhn.fhir.model.primitive.IdDt;
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
|
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||||
|
import ca.uhn.fhir.rest.server.Parameter;
|
||||||
|
import ca.uhn.fhir.rest.server.Util;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by dsotnikov on 2/25/2014.
|
* Created by dsotnikov on 2/25/2014.
|
||||||
*/
|
*/
|
||||||
public class SearchMethod extends BaseMethod {
|
public class SearchMethodBinding extends BaseMethodBinding {
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SearchMethod.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SearchMethodBinding.class);
|
||||||
|
|
||||||
private Method method;
|
private Method method;
|
||||||
|
|
||||||
private List<Parameter> parameters;
|
private List<Parameter> parameters;
|
||||||
private RequestType requestType;
|
private RequestType requestType;
|
||||||
private Class<?> resourceType;
|
private Class<?> myDeclaredResourceType;
|
||||||
|
|
||||||
public SearchMethod() {
|
public SearchMethodBinding(Class<? extends IResource> theAnnotatedResourceType, Method theMethod) {
|
||||||
}
|
super(theAnnotatedResourceType);
|
||||||
|
this.method = theMethod;
|
||||||
public SearchMethod(Method method, List<Parameter> parameters) {
|
this.parameters = Util.getResourceParameters(theMethod);
|
||||||
this.method = method;
|
|
||||||
this.parameters = parameters;
|
this.myDeclaredResourceType = theMethod.getReturnType();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Method getMethod() {
|
public Method getMethod() {
|
||||||
|
@ -50,8 +50,8 @@ public class SearchMethod extends BaseMethod {
|
||||||
return requestType;
|
return requestType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class getResourceType() {
|
public Class getDeclaredResourceType() {
|
||||||
return resourceType.getClass();
|
return myDeclaredResourceType.getClass();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -60,7 +60,7 @@ public class SearchMethod extends BaseMethod {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<IResource> invoke(IResourceProvider theResourceProvider, IdDt theId, IdDt theVersionId, Map<String, String[]> parameterValues) throws InvalidRequestException, InternalErrorException {
|
public List<IResource> invokeServer(IResourceProvider theResourceProvider, IdDt theId, IdDt theVersionId, Map<String, String[]> parameterValues) throws InvalidRequestException, InternalErrorException {
|
||||||
assert theId == null;
|
assert theId == null;
|
||||||
assert theVersionId == null;
|
assert theVersionId == null;
|
||||||
|
|
||||||
|
@ -94,12 +94,12 @@ public class SearchMethod extends BaseMethod {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean matches(String theResourceName, IdDt theId, IdDt theVersion, Set<String> theParameterNames) {
|
public boolean matches(String theResourceName, IdDt theId, IdDt theVersion, Set<String> theParameterNames) {
|
||||||
if (!theResourceName.equals(getResource().getResourceName())) {
|
if (!theResourceName.equals(getResourceName())) {
|
||||||
ourLog.info("Method {} doesn't match because resource name {} != {}", method.getName(), theResourceName, getResource().getResourceName());
|
ourLog.trace("Method {} doesn't match because resource name {} != {}", method.getName(), theResourceName, getResourceName());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (theId != null || theVersion != null) {
|
if (theId != null || theVersion != null) {
|
||||||
ourLog.info("Method {} doesn't match because ID or Version are not null: {} - {}", theId, theVersion);
|
ourLog.trace("Method {} doesn't match because ID or Version are not null: {} - {}", theId, theVersion);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,13 +108,13 @@ public class SearchMethod extends BaseMethod {
|
||||||
Parameter temp = this.parameters.get(i);
|
Parameter temp = this.parameters.get(i);
|
||||||
methodParamsTemp.add(temp.getName());
|
methodParamsTemp.add(temp.getName());
|
||||||
if (temp.isRequired() && !theParameterNames.contains(temp.getName())) {
|
if (temp.isRequired() && !theParameterNames.contains(temp.getName())) {
|
||||||
ourLog.info("Method {} doesn't match param '{}' is not present", temp.getName());
|
ourLog.trace("Method {} doesn't match param '{}' is not present", method.getName(), temp.getName());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
boolean retVal = methodParamsTemp.containsAll(theParameterNames);
|
boolean retVal = methodParamsTemp.containsAll(theParameterNames);
|
||||||
|
|
||||||
ourLog.info("Method {} matches: {}", method.getName(), retVal);
|
ourLog.trace("Method {} matches: {}", method.getName(), retVal);
|
||||||
|
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
@ -132,7 +132,7 @@ public class SearchMethod extends BaseMethod {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setResourceType(Class<?> resourceType) {
|
public void setResourceType(Class<?> resourceType) {
|
||||||
this.resourceType = resourceType;
|
this.myDeclaredResourceType = resourceType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static enum RequestType {
|
public static enum RequestType {
|
|
@ -1,53 +0,0 @@
|
||||||
package ca.uhn.fhir.rest.server;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
|
||||||
import ca.uhn.fhir.model.primitive.IdDt;
|
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
|
||||||
|
|
||||||
abstract class BaseMethod {
|
|
||||||
|
|
||||||
public enum ReturnTypeEnum {
|
|
||||||
RESOURCE, BUNDLE
|
|
||||||
}
|
|
||||||
|
|
||||||
private Resource resource;
|
|
||||||
|
|
||||||
public Resource getResource() {
|
|
||||||
return resource;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract ReturnTypeEnum getReturnType();
|
|
||||||
|
|
||||||
public abstract boolean matches(String theResourceName, IdDt theId, IdDt theVersion, Set<String> theParameterNames);
|
|
||||||
|
|
||||||
public void setResource(Resource theResource) {
|
|
||||||
this.resource = theResource;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract List<IResource> invoke(IResourceProvider theResourceProvider, IdDt theId, IdDt theVersionId, Map<String, String[]> theParameterValues) throws InvalidRequestException,
|
|
||||||
InternalErrorException;
|
|
||||||
|
|
||||||
protected static List<IResource> toResourceList(Object response) throws InternalErrorException {
|
|
||||||
if (response == null) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
} else if (response instanceof IResource) {
|
|
||||||
return Collections.singletonList((IResource) response);
|
|
||||||
} else if (response instanceof Collection) {
|
|
||||||
List<IResource> retVal = new ArrayList<IResource>();
|
|
||||||
for (Object next : ((Collection<?>) response)) {
|
|
||||||
retVal.add((IResource) next);
|
|
||||||
}
|
|
||||||
return retVal;
|
|
||||||
} else {
|
|
||||||
throw new InternalErrorException("Unexpected return type: " + response.getClass().getCanonicalName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,6 +5,7 @@ import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import ca.uhn.fhir.model.primitive.IdDt;
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
|
import ca.uhn.fhir.rest.common.BaseMethodBinding;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by dsotnikov on 2/25/2014.
|
* Created by dsotnikov on 2/25/2014.
|
||||||
|
@ -14,25 +15,25 @@ public class Resource {
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(Resource.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(Resource.class);
|
||||||
|
|
||||||
private String resourceName;
|
private String resourceName;
|
||||||
private List<BaseMethod> methods = new ArrayList<BaseMethod>();
|
private List<BaseMethodBinding> methods = new ArrayList<BaseMethodBinding>();
|
||||||
private IResourceProvider resourceProvider;
|
private IResourceProvider resourceProvider;
|
||||||
|
|
||||||
public Resource() {
|
public Resource() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Resource(String resourceName, List<BaseMethod> methods) {
|
public Resource(String resourceName, List<BaseMethodBinding> methods) {
|
||||||
this.resourceName = resourceName;
|
this.resourceName = resourceName;
|
||||||
this.methods = methods;
|
this.methods = methods;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BaseMethod getMethod(String theResourceName, IdDt theId, IdDt theVersionId, Set<String> theParameters) throws Exception {
|
public BaseMethodBinding getMethod(String theResourceName, IdDt theId, IdDt theVersionId, Set<String> theParameters) throws Exception {
|
||||||
if (null == methods) {
|
if (null == methods) {
|
||||||
ourLog.warn("No methods exist for resource provider: {}", resourceProvider.getClass());
|
ourLog.warn("No methods exist for resource provider: {}", resourceProvider.getClass());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
ourLog.info("Looking for a handler for {} / {} / {} / {}", new Object[] {theResourceName,theId, theVersionId, theParameters});
|
ourLog.info("Looking for a handler for {} / {} / {} / {}", new Object[] {theResourceName,theId, theVersionId, theParameters});
|
||||||
for (BaseMethod rm : methods) {
|
for (BaseMethodBinding rm : methods) {
|
||||||
if (rm.matches(theResourceName, theId, theVersionId, theParameters)) {
|
if (rm.matches(theResourceName, theId, theVersionId, theParameters)) {
|
||||||
ourLog.info("Handler {} matches", rm);
|
ourLog.info("Handler {} matches", rm);
|
||||||
return rm;
|
return rm;
|
||||||
|
@ -51,17 +52,16 @@ public class Resource {
|
||||||
this.resourceName = resourceName;
|
this.resourceName = resourceName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<BaseMethod> getMethods() {
|
public List<BaseMethodBinding> getMethods() {
|
||||||
return methods;
|
return methods;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMethods(List<BaseMethod> methods) {
|
public void setMethods(List<BaseMethodBinding> methods) {
|
||||||
this.methods = methods;
|
this.methods = methods;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addMethod(BaseMethod method) {
|
public void addMethod(BaseMethodBinding method) {
|
||||||
this.methods.add(method);
|
this.methods.add(method);
|
||||||
method.setResource(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,14 +1,10 @@
|
||||||
package ca.uhn.fhir.rest.server;
|
package ca.uhn.fhir.rest.server;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.net.URL;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Enumeration;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -20,22 +16,20 @@ import javax.servlet.http.HttpServlet;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||||
import ca.uhn.fhir.model.api.Bundle;
|
import ca.uhn.fhir.model.api.Bundle;
|
||||||
import ca.uhn.fhir.model.api.BundleEntry;
|
import ca.uhn.fhir.model.api.BundleEntry;
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
import ca.uhn.fhir.model.primitive.IdDt;
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
import ca.uhn.fhir.parser.XmlParser;
|
import ca.uhn.fhir.rest.common.BaseMethodBinding;
|
||||||
import ca.uhn.fhir.rest.annotation.Read;
|
import ca.uhn.fhir.rest.common.SearchMethodBinding;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.AbstractResponseException;
|
import ca.uhn.fhir.rest.server.exceptions.AbstractResponseException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.MethodNotFoundException;
|
import ca.uhn.fhir.rest.server.exceptions.MethodNotFoundException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||||
import ca.uhn.fhir.rest.server.operations.DELETE;
|
|
||||||
import ca.uhn.fhir.rest.server.operations.Search;
|
|
||||||
import ca.uhn.fhir.rest.server.operations.POST;
|
|
||||||
import ca.uhn.fhir.rest.server.operations.PUT;
|
|
||||||
|
|
||||||
public abstract class RestfulServer extends HttpServlet {
|
public abstract class RestfulServer extends HttpServlet {
|
||||||
|
|
||||||
|
@ -50,38 +44,6 @@ public abstract class RestfulServer extends HttpServlet {
|
||||||
// map of request handler resources keyed by resource name
|
// map of request handler resources keyed by resource name
|
||||||
private Map<String, Resource> resources = new HashMap<String, Resource>();
|
private Map<String, Resource> resources = new HashMap<String, Resource>();
|
||||||
|
|
||||||
private boolean addResourceMethod(Resource resource, Method method) throws Exception {
|
|
||||||
|
|
||||||
// each operation name must have a request type annotation and be unique
|
|
||||||
if (null != method.getAnnotation(Read.class)) {
|
|
||||||
Integer idIndex = Util.findReadIdParameterIndex(method);
|
|
||||||
Integer versionIdIndex = Util.findReadVersionIdParameterIndex(method);
|
|
||||||
ReadMethod rm = new ReadMethod(method, idIndex, versionIdIndex);
|
|
||||||
resource.addMethod(rm);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
SearchMethod sm = new SearchMethod();
|
|
||||||
if (null != method.getAnnotation(Search.class)) {
|
|
||||||
sm.setRequestType(SearchMethod.RequestType.GET);
|
|
||||||
} else if (null != method.getAnnotation(PUT.class)) {
|
|
||||||
sm.setRequestType(SearchMethod.RequestType.PUT);
|
|
||||||
} else if (null != method.getAnnotation(POST.class)) {
|
|
||||||
sm.setRequestType(SearchMethod.RequestType.POST);
|
|
||||||
} else if (null != method.getAnnotation(DELETE.class)) {
|
|
||||||
sm.setRequestType(SearchMethod.RequestType.DELETE);
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
sm.setMethod(method);
|
|
||||||
sm.setResourceType(method.getReturnType());
|
|
||||||
sm.setParameters(Util.getResourceParameters(method));
|
|
||||||
|
|
||||||
resource.addMethod(sm);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private EncodingUtil determineResponseEncoding(Map<String, String[]> theParams) {
|
private EncodingUtil determineResponseEncoding(Map<String, String[]> theParams) {
|
||||||
String[] format = theParams.remove(Constants.PARAM_FORMAT);
|
String[] format = theParams.remove(Constants.PARAM_FORMAT);
|
||||||
|
@ -91,22 +53,22 @@ public abstract class RestfulServer extends HttpServlet {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
protected void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||||
handleRequest(SearchMethod.RequestType.DELETE, request, response);
|
handleRequest(SearchMethodBinding.RequestType.DELETE, request, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||||
handleRequest(SearchMethod.RequestType.GET, request, response);
|
handleRequest(SearchMethodBinding.RequestType.GET, request, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||||
handleRequest(SearchMethod.RequestType.POST, request, response);
|
handleRequest(SearchMethodBinding.RequestType.POST, request, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||||
handleRequest(SearchMethod.RequestType.PUT, request, response);
|
handleRequest(SearchMethodBinding.RequestType.PUT, request, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void findResourceMethods(IResourceProvider theProvider) throws Exception {
|
private void findResourceMethods(IResourceProvider theProvider) throws Exception {
|
||||||
|
@ -120,16 +82,17 @@ public abstract class RestfulServer extends HttpServlet {
|
||||||
resources.put(definition.getName(), r);
|
resources.put(definition.getName(), r);
|
||||||
|
|
||||||
ourLog.info("Scanning type for RESTful methods: {}", theProvider.getClass());
|
ourLog.info("Scanning type for RESTful methods: {}", theProvider.getClass());
|
||||||
|
|
||||||
Class<?> clazz = theProvider.getClass();
|
Class<?> clazz = theProvider.getClass();
|
||||||
for (Method m : clazz.getDeclaredMethods()) {
|
for (Method m : clazz.getDeclaredMethods()) {
|
||||||
if (Modifier.isPublic(m.getModifiers())) {
|
if (Modifier.isPublic(m.getModifiers())) {
|
||||||
ourLog.info("Scanning public method: {}#{}", theProvider.getClass(), m.getName());
|
ourLog.info("Scanning public method: {}#{}", theProvider.getClass(), m.getName());
|
||||||
|
|
||||||
boolean foundMethod = addResourceMethod(r, m);
|
BaseMethodBinding foundMethodBinding = BaseMethodBinding.bindMethod(m);
|
||||||
if (foundMethod) {
|
if (foundMethodBinding != null) {
|
||||||
|
r.addMethod(foundMethodBinding);
|
||||||
ourLog.info(" * Method: {}#{} is a handler", theProvider.getClass(), m.getName());
|
ourLog.info(" * Method: {}#{} is a handler", theProvider.getClass(), m.getName());
|
||||||
}else {
|
} else {
|
||||||
ourLog.info(" * Method: {}#{} is not a handler", theProvider.getClass(), m.getName());
|
ourLog.info(" * Method: {}#{} is not a handler", theProvider.getClass(), m.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -138,19 +101,20 @@ public abstract class RestfulServer extends HttpServlet {
|
||||||
|
|
||||||
public abstract Collection<IResourceProvider> getResourceProviders();
|
public abstract Collection<IResourceProvider> getResourceProviders();
|
||||||
|
|
||||||
protected void handleRequest(SearchMethod.RequestType requestType, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
protected void handleRequest(SearchMethodBinding.RequestType requestType, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||||
try {
|
try {
|
||||||
String resourceName = null;
|
String resourceName = null;
|
||||||
Long identity = null;
|
Long identity = null;
|
||||||
|
|
||||||
String requestPath = request.getRequestURI();
|
String requestPath = StringUtils.defaultString(request.getRequestURI());
|
||||||
requestPath = requestPath.substring(request.getContextPath().length());
|
String contextPath = StringUtils.defaultString(request.getContextPath());
|
||||||
if (requestPath.charAt(0)=='/') {
|
requestPath = requestPath.substring(contextPath.length());
|
||||||
|
if (requestPath.charAt(0) == '/') {
|
||||||
requestPath = requestPath.substring(1);
|
requestPath = requestPath.substring(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
ourLog.info("Request URI: {}", requestPath);
|
ourLog.info("Request URI: {}", requestPath);
|
||||||
|
|
||||||
Map<String, String[]> params = new HashMap<String, String[]>(request.getParameterMap());
|
Map<String, String[]> params = new HashMap<String, String[]>(request.getParameterMap());
|
||||||
EncodingUtil responseEncoding = determineResponseEncoding(params);
|
EncodingUtil responseEncoding = determineResponseEncoding(params);
|
||||||
|
|
||||||
|
@ -178,21 +142,23 @@ public abstract class RestfulServer extends HttpServlet {
|
||||||
//
|
//
|
||||||
// if (identity != null && !tok.hasMoreTokens()) {
|
// if (identity != null && !tok.hasMoreTokens()) {
|
||||||
// if (params == null || params.isEmpty()) {
|
// if (params == null || params.isEmpty()) {
|
||||||
// IResource resource = resourceBinding.getResourceProvider().getResourceById(identity);
|
// IResource resource =
|
||||||
|
// resourceBinding.getResourceProvider().getResourceById(identity);
|
||||||
// if (resource == null) {
|
// if (resource == null) {
|
||||||
// throw new ResourceNotFoundException(identity);
|
// throw new ResourceNotFoundException(identity);
|
||||||
// }
|
// }
|
||||||
// streamResponseAsResource(response, resource, resourceBinding, responseEncoding);
|
// streamResponseAsResource(response, resource, resourceBinding,
|
||||||
|
// responseEncoding);
|
||||||
// return;
|
// return;
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
BaseMethod resourceMethod = resourceBinding.getMethod(resourceName, id, versionId, params.keySet());
|
BaseMethodBinding resourceMethod = resourceBinding.getMethod(resourceName, id, versionId, params.keySet());
|
||||||
if (null == resourceMethod) {
|
if (null == resourceMethod) {
|
||||||
throw new MethodNotFoundException("No resource method available for the supplied parameters " + params);
|
throw new MethodNotFoundException("No resource method available for the supplied parameters " + params);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<IResource> result = resourceMethod.invoke(resourceBinding.getResourceProvider(), id, versionId, params);
|
List<IResource> result = resourceMethod.invokeServer(resourceBinding.getResourceProvider(), id, versionId, params);
|
||||||
switch (resourceMethod.getReturnType()) {
|
switch (resourceMethod.getReturnType()) {
|
||||||
case BUNDLE:
|
case BUNDLE:
|
||||||
streamResponseAsBundle(response, result, responseEncoding);
|
streamResponseAsBundle(response, result, responseEncoding);
|
||||||
|
@ -209,13 +175,13 @@ public abstract class RestfulServer extends HttpServlet {
|
||||||
// resourceMethod.get
|
// resourceMethod.get
|
||||||
|
|
||||||
} catch (AbstractResponseException e) {
|
} catch (AbstractResponseException e) {
|
||||||
|
|
||||||
if (e instanceof InternalErrorException) {
|
if (e instanceof InternalErrorException) {
|
||||||
ourLog.error("Failure during REST processing", e);
|
ourLog.error("Failure during REST processing", e);
|
||||||
} else {
|
} else {
|
||||||
ourLog.warn("Failure during REST processing: {}", e.toString());
|
ourLog.warn("Failure during REST processing: {}", e.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
response.setStatus(e.getStatusCode());
|
response.setStatus(e.getStatusCode());
|
||||||
response.setContentType("text/plain");
|
response.setContentType("text/plain");
|
||||||
response.setCharacterEncoding("UTF-8");
|
response.setCharacterEncoding("UTF-8");
|
||||||
|
@ -293,6 +259,4 @@ public abstract class RestfulServer extends HttpServlet {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,16 @@ package ca.uhn.fhir.rest.server.operations;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
|
||||||
public @interface Search {
|
public @interface Search {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the resource type that is returned by the method annotated
|
||||||
|
* with this annotation
|
||||||
|
*/
|
||||||
|
Class<? extends IResource> value();
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package ca.uhn.fhir.rest.client;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.model.api.Bundle;
|
||||||
|
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
|
||||||
|
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||||
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
|
import ca.uhn.fhir.rest.annotation.Read;
|
||||||
|
import ca.uhn.fhir.rest.client.api.IRestfulClient;
|
||||||
|
import ca.uhn.fhir.rest.server.operations.Search;
|
||||||
|
import ca.uhn.fhir.rest.server.parameters.Required;
|
||||||
|
|
||||||
|
public interface ITestClient extends IRestfulClient {
|
||||||
|
|
||||||
|
@Read(value=Patient.class)
|
||||||
|
Patient getPatientById(@Read.IdParam IdDt theId);
|
||||||
|
|
||||||
|
@Search(value=Patient.class)
|
||||||
|
Patient findPatientByMrn(@Required(name = Patient.SP_IDENTIFIER) IdentifierDt theId);
|
||||||
|
|
||||||
|
@Search(value=Patient.class)
|
||||||
|
Bundle findPatientByLastName(@Required(name = Patient.SP_FAMILY) IdentifierDt theId);
|
||||||
|
}
|
|
@ -51,7 +51,7 @@ public class DummyPatientResourceProvider implements IResourceProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Search
|
@Search(Patient.class)
|
||||||
public Patient getPatient(@Required(name = "identifier") IdentifierDt theIdentifier) {
|
public Patient getPatient(@Required(name = "identifier") IdentifierDt theIdentifier) {
|
||||||
for (Patient next : myIdToPatient.values()) {
|
for (Patient next : myIdToPatient.values()) {
|
||||||
for (IdentifierDt nextId : next.getIdentifier()) {
|
for (IdentifierDt nextId : next.getIdentifier()) {
|
||||||
|
@ -75,7 +75,7 @@ public class DummyPatientResourceProvider implements IResourceProvider {
|
||||||
* The resource identity
|
* The resource identity
|
||||||
* @return The resource
|
* @return The resource
|
||||||
*/
|
*/
|
||||||
@Read
|
@Read(Patient.class)
|
||||||
public Patient getResourceById(@Read.IdParam IdDt theId) {
|
public Patient getResourceById(@Read.IdParam IdDt theId) {
|
||||||
return myIdToPatient.get(theId.getValue());
|
return myIdToPatient.get(theId.getValue());
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,20 +10,17 @@ import java.util.Set;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||||
|
import ca.uhn.fhir.rest.common.SearchMethodBinding;
|
||||||
import ca.uhn.fhir.rest.server.Parameter;
|
import ca.uhn.fhir.rest.server.Parameter;
|
||||||
import ca.uhn.fhir.rest.server.SearchMethod;
|
|
||||||
|
|
||||||
public class ResourceMethodTest {
|
public class ResourceMethodTest {
|
||||||
|
|
||||||
private SearchMethod rm;
|
private SearchMethodBinding rm;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void before() {
|
public void before() throws NoSuchMethodException, SecurityException {
|
||||||
Resource resource = new Resource();
|
rm = new SearchMethodBinding(Patient.class, ResourceMethodTest.class.getMethod("before"));
|
||||||
resource.setResourceName("ResName");
|
|
||||||
|
|
||||||
rm = new SearchMethod();
|
|
||||||
rm.setResource(resource);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
Loading…
Reference in New Issue