Start to implement delete
This commit is contained in:
parent
ad05d8262e
commit
7d319fa770
|
@ -1,10 +0,0 @@
|
|||
package ca.uhn.fhir.rest.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
|
||||
public @interface DELETE {
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package ca.uhn.fhir.rest.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
|
||||
/**
|
||||
* RESTful method annotation to be used for the FHIR
|
||||
* <a href="http://hl7.org/implement/standards/fhir/http.html#delete">delete</a> method.
|
||||
*
|
||||
* <p>
|
||||
* Delete is used to remove an existing resource, meaning that any attempts to
|
||||
* do a non-version-specific read of that resource will fail.
|
||||
* </p>
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(value=ElementType.METHOD)
|
||||
public @interface Delete {
|
||||
|
||||
Class<? extends IResource> resourceType() default NotSpecified.class;
|
||||
|
||||
|
||||
interface NotSpecified extends IResource{
|
||||
// nothing
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package ca.uhn.fhir.rest.api;
|
||||
|
||||
import ca.uhn.fhir.model.dstu.resource.OperationOutcome;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
|
||||
public class MethodOutcome {
|
||||
|
@ -7,10 +8,15 @@ public class MethodOutcome {
|
|||
private IdDt myId;
|
||||
private IdDt myVersionId;
|
||||
private boolean myCreated;
|
||||
private OperationOutcome myOperationOutcome;
|
||||
|
||||
public MethodOutcome() {
|
||||
}
|
||||
|
||||
public MethodOutcome(IdDt theId) {
|
||||
myId=theId;
|
||||
}
|
||||
|
||||
public MethodOutcome(boolean theCreated, IdDt theId, IdDt theVersionId) {
|
||||
super();
|
||||
myId = theId;
|
||||
|
@ -50,4 +56,12 @@ public class MethodOutcome {
|
|||
myCreated=theCreated;
|
||||
}
|
||||
|
||||
public void setOperationOutcome(OperationOutcome theOperationOutcome) {
|
||||
myOperationOutcome=theOperationOutcome;
|
||||
}
|
||||
|
||||
public OperationOutcome getOperationOutcome() {
|
||||
return myOperationOutcome;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
package ca.uhn.fhir.rest.client;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.client.methods.HttpDelete;
|
||||
import org.apache.http.client.methods.HttpRequestBase;
|
||||
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
|
||||
public class DeleteClientInvocation extends BaseClientInvocation {
|
||||
|
||||
private String myUrlPath;
|
||||
|
||||
public DeleteClientInvocation(String... theUrlFragments) {
|
||||
super();
|
||||
myUrlPath = StringUtils.join(theUrlFragments, '/');
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpRequestBase asHttpRequest(String theUrlBase) throws DataFormatException, IOException {
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append(theUrlBase);
|
||||
b.append(myUrlPath);
|
||||
|
||||
HttpDelete retVal = new HttpDelete(b.toString());
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -81,7 +81,7 @@ public class RestfulClientFactory implements IRestfulClientFactory {
|
|||
}
|
||||
resReturnType = (Class<? extends IResource>) returnTypeColl;
|
||||
}
|
||||
BaseMethodBinding binding = BaseMethodBinding.bindMethod(resReturnType, nextMethod, myContext);
|
||||
BaseMethodBinding binding = BaseMethodBinding.bindMethod(resReturnType, nextMethod, myContext,null);
|
||||
invocationHandler.addBinding(nextMethod, binding);
|
||||
}
|
||||
myInvocationHandlers.put(theClientType, invocationHandler);
|
||||
|
|
|
@ -22,6 +22,7 @@ import ca.uhn.fhir.model.dstu.valueset.RestfulOperationSystemEnum;
|
|||
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationTypeEnum;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.annotation.Create;
|
||||
import ca.uhn.fhir.rest.annotation.Delete;
|
||||
import ca.uhn.fhir.rest.annotation.Metadata;
|
||||
import ca.uhn.fhir.rest.annotation.Read;
|
||||
import ca.uhn.fhir.rest.annotation.Search;
|
||||
|
@ -30,6 +31,7 @@ import ca.uhn.fhir.rest.client.BaseClientInvocation;
|
|||
import ca.uhn.fhir.rest.client.exceptions.NonFhirResponseException;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.EncodingUtil;
|
||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
|
@ -75,13 +77,15 @@ public abstract class BaseMethodBinding {
|
|||
return parser;
|
||||
}
|
||||
|
||||
public static BaseMethodBinding bindMethod(Class<? extends IResource> theReturnType, Method theMethod, FhirContext theContext) {
|
||||
public static BaseMethodBinding bindMethod(Class<? extends IResource> theReturnType, Method theMethod, FhirContext theContext, IResourceProvider theProvider) {
|
||||
Read read = theMethod.getAnnotation(Read.class);
|
||||
Search search = theMethod.getAnnotation(Search.class);
|
||||
Metadata conformance = theMethod.getAnnotation(Metadata.class);
|
||||
Create create = theMethod.getAnnotation(Create.class);
|
||||
Update update = theMethod.getAnnotation(Update.class);
|
||||
if (!verifyMethodHasZeroOrOneOperationAnnotation(theMethod, read, search, conformance,create,update)) {
|
||||
Delete delete = theMethod.getAnnotation(Delete.class);
|
||||
// ** if you add another annotation above, also add it to the next line:
|
||||
if (!verifyMethodHasZeroOrOneOperationAnnotation(theMethod, read, search, conformance,create,update,delete)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -109,6 +113,8 @@ public abstract class BaseMethodBinding {
|
|||
return new CreateMethodBinding(theMethod, theContext);
|
||||
} else if (update != null) {
|
||||
return new UpdateMethodBinding(theMethod, theContext);
|
||||
} else if (delete != null) {
|
||||
return new DeleteMethodBinding(theMethod, theContext, theProvider);
|
||||
} else {
|
||||
throw new ConfigurationException("Did not detect any FHIR annotations on method '" + theMethod.getName() + "' on type: " + theMethod.getDeclaringClass().getCanonicalName());
|
||||
}
|
||||
|
@ -202,7 +208,7 @@ public abstract class BaseMethodBinding {
|
|||
public abstract Object invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException, BaseServerResponseException;
|
||||
|
||||
public static BaseMethodBinding bindSystemMethod(Method theMethod, FhirContext theContext) {
|
||||
return bindMethod(null, theMethod, theContext);
|
||||
return bindMethod(null, theMethod, theContext, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,17 +18,14 @@ import org.apache.commons.lang3.StringUtils;
|
|||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.dstu.resource.OperationOutcome;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.client.BaseClientInvocation;
|
||||
import ca.uhn.fhir.rest.method.SearchMethodBinding.RequestType;
|
||||
import ca.uhn.fhir.rest.param.IParameter;
|
||||
import ca.uhn.fhir.rest.param.ResourceParameter;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.EncodingUtil;
|
||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
|
@ -51,48 +48,36 @@ public abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBindin
|
|||
ALLOWED_PARAMS = Collections.unmodifiableSet(set);
|
||||
}
|
||||
|
||||
private int myResourceParameterIndex;
|
||||
private List<IParameter> myParameters;
|
||||
private String myResourceName;
|
||||
private boolean myReturnVoid;
|
||||
|
||||
public BaseOutcomeReturningMethodBinding(Method theMethod, FhirContext theContext, Class<?> theMethodAnnotation) {
|
||||
super(theMethod, theContext);
|
||||
myParameters = Util.getResourceParameters(theMethod);
|
||||
ResourceParameter resourceParameter = null;
|
||||
|
||||
int index = 0;
|
||||
for (IParameter next : myParameters) {
|
||||
if (next instanceof ResourceParameter) {
|
||||
resourceParameter = (ResourceParameter) next;
|
||||
myResourceName = theContext.getResourceDefinition(resourceParameter.getResourceType()).getName();
|
||||
myResourceParameterIndex = index;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
if (resourceParameter == null) {
|
||||
throw new ConfigurationException("Method " + theMethod.getName() + " in type " + theMethod.getDeclaringClass().getCanonicalName() + " does not have a parameter annotated with @" + ResourceParam.class.getSimpleName());
|
||||
}
|
||||
|
||||
if (!theMethod.getReturnType().equals(MethodOutcome.class)) {
|
||||
throw new ConfigurationException("Method " + theMethod.getName() + " in type " + theMethod.getDeclaringClass().getCanonicalName() + " is a @" + theMethodAnnotation.getSimpleName() + " method but it does not return " + MethodOutcome.class);
|
||||
if (!allowVoidReturnType()) {
|
||||
throw new ConfigurationException("Method " + theMethod.getName() + " in type " + theMethod.getDeclaringClass().getCanonicalName() + " is a @" + theMethodAnnotation.getSimpleName()
|
||||
+ " method but it does not return " + MethodOutcome.class);
|
||||
} else if (theMethod.getReturnType() == Void.class) {
|
||||
myReturnVoid = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseClientInvocation invokeClient(Object[] theArgs) throws InternalErrorException {
|
||||
IResource resource = (IResource) theArgs[myResourceParameterIndex];
|
||||
if (resource == null) {
|
||||
throw new NullPointerException("Resource can not be null");
|
||||
}
|
||||
|
||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(resource);
|
||||
String resourceName = def.getName();
|
||||
|
||||
return createClientInvocation(theArgs, resource, resourceName);
|
||||
protected List<IParameter> getParameters() {
|
||||
return myParameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses may override to allow a void method return type, which is allowable for some methods (e.g. delete)
|
||||
*/
|
||||
protected boolean allowVoidReturnType() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
protected abstract BaseClientInvocation createClientInvocation(Object[] theArgs, IResource resource, String resourceName);
|
||||
|
||||
@Override
|
||||
|
@ -100,6 +85,10 @@ public abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBindin
|
|||
switch (theResponseStatusCode) {
|
||||
case Constants.STATUS_HTTP_200_OK:
|
||||
case Constants.STATUS_HTTP_201_CREATED:
|
||||
case Constants.STATUS_HTTP_204_NO_CONTENT:
|
||||
if (myReturnVoid) {
|
||||
return null;
|
||||
}
|
||||
List<String> locationHeaders = theHeaders.get("location");
|
||||
MethodOutcome retVal = new MethodOutcome();
|
||||
if (locationHeaders != null && locationHeaders.size() > 0) {
|
||||
|
@ -128,7 +117,7 @@ public abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBindin
|
|||
}
|
||||
|
||||
protected void parseContentLocation(MethodOutcome theOutcomeToPopulate, String theLocationHeader) {
|
||||
String resourceNamePart = "/" + myResourceName + "/";
|
||||
String resourceNamePart = "/" + getResourceName() + "/";
|
||||
int resourceIndex = theLocationHeader.lastIndexOf(resourceNamePart);
|
||||
if (resourceIndex > -1) {
|
||||
int idIndexStart = resourceIndex + resourceNamePart.length();
|
||||
|
@ -146,9 +135,7 @@ public abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBindin
|
|||
}
|
||||
}
|
||||
|
||||
public String getResourceName() {
|
||||
return myResourceName;
|
||||
}
|
||||
public abstract String getResourceName();
|
||||
|
||||
@Override
|
||||
public void invokeServer(RestfulServer theServer, Request theRequest, HttpServletResponse theResponse) throws BaseServerResponseException, IOException {
|
||||
|
@ -166,7 +153,7 @@ public abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBindin
|
|||
}
|
||||
|
||||
addAdditionalParams(theRequest, params);
|
||||
|
||||
|
||||
MethodOutcome response;
|
||||
try {
|
||||
response = (MethodOutcome) this.getMethod().invoke(theRequest.getResourceProvider(), params);
|
||||
|
@ -179,24 +166,28 @@ public abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBindin
|
|||
}
|
||||
|
||||
if (response == null) {
|
||||
throw new ConfigurationException("Method " + getMethod().getName() + " in type " + getMethod().getDeclaringClass().getCanonicalName() + " returned null");
|
||||
}
|
||||
|
||||
if (response.isCreated()) {
|
||||
theResponse.setStatus(Constants.STATUS_HTTP_201_CREATED);
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append(theRequest.getFhirServerBase());
|
||||
b.append('/');
|
||||
b.append(myResourceName);
|
||||
b.append('/');
|
||||
b.append(response.getId().getValue());
|
||||
if (response.getVersionId() != null && response.getVersionId().isEmpty() == false) {
|
||||
b.append("/_history/");
|
||||
b.append(response.getVersionId().getValue());
|
||||
if (myReturnVoid == false) {
|
||||
throw new ConfigurationException("Method " + getMethod().getName() + " in type " + getMethod().getDeclaringClass().getCanonicalName() + " returned null");
|
||||
}
|
||||
} else if (!myReturnVoid) {
|
||||
if (response.isCreated()) {
|
||||
theResponse.setStatus(Constants.STATUS_HTTP_201_CREATED);
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append(theRequest.getFhirServerBase());
|
||||
b.append('/');
|
||||
b.append(getResourceName());
|
||||
b.append('/');
|
||||
b.append(response.getId().getValue());
|
||||
if (response.getVersionId() != null && response.getVersionId().isEmpty() == false) {
|
||||
b.append("/_history/");
|
||||
b.append(response.getVersionId().getValue());
|
||||
}
|
||||
theResponse.addHeader("Location", b.toString());
|
||||
} else {
|
||||
theResponse.setStatus(Constants.STATUS_HTTP_200_OK);
|
||||
}
|
||||
theResponse.addHeader("Location", b.toString());
|
||||
} else {
|
||||
theResponse.setStatus(Constants.STATUS_HTTP_200_OK);
|
||||
theResponse.setStatus(Constants.STATUS_HTTP_204_NO_CONTENT);
|
||||
}
|
||||
|
||||
theServer.addHapiHeader(theResponse);
|
||||
|
@ -221,7 +212,7 @@ public abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBindin
|
|||
}
|
||||
|
||||
protected abstract Set<RequestType> provideAllowableRequestTypes();
|
||||
|
||||
|
||||
@Override
|
||||
public boolean matches(Request theRequest) {
|
||||
Set<RequestType> allowableRequestTypes = provideAllowableRequestTypes();
|
||||
|
@ -229,7 +220,7 @@ public abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBindin
|
|||
if (!allowableRequestTypes.contains(requestType)) {
|
||||
return false;
|
||||
}
|
||||
if (!myResourceName.equals(theRequest.getResourceName())) {
|
||||
if (!getResourceName().equals(theRequest.getResourceName())) {
|
||||
return false;
|
||||
}
|
||||
if (StringUtils.isNotBlank(theRequest.getOperation())) {
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
package ca.uhn.fhir.rest.method;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
||||
import ca.uhn.fhir.rest.client.BaseClientInvocation;
|
||||
import ca.uhn.fhir.rest.param.IParameter;
|
||||
import ca.uhn.fhir.rest.param.ResourceParameter;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
|
||||
public abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends BaseOutcomeReturningMethodBinding {
|
||||
private int myResourceParameterIndex;
|
||||
private String myResourceName;
|
||||
|
||||
public BaseOutcomeReturningMethodBindingWithResourceParam(Method theMethod, FhirContext theContext, Class<?> theMethodAnnotation) {
|
||||
super(theMethod, theContext, theMethodAnnotation);
|
||||
|
||||
ResourceParameter resourceParameter = null;
|
||||
|
||||
int index = 0;
|
||||
for (IParameter next : getParameters()) {
|
||||
if (next instanceof ResourceParameter) {
|
||||
resourceParameter = (ResourceParameter) next;
|
||||
myResourceName = theContext.getResourceDefinition(resourceParameter.getResourceType()).getName();
|
||||
myResourceParameterIndex = index;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
if (resourceParameter == null) {
|
||||
throw new ConfigurationException("Method " + theMethod.getName() + " in type " + theMethod.getDeclaringClass().getCanonicalName() + " does not have a parameter annotated with @"
|
||||
+ ResourceParam.class.getSimpleName());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getResourceName() {
|
||||
return myResourceName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseClientInvocation invokeClient(Object[] theArgs) throws InternalErrorException {
|
||||
IResource resource = (IResource) theArgs[myResourceParameterIndex];
|
||||
if (resource == null) {
|
||||
throw new NullPointerException("Resource can not be null");
|
||||
}
|
||||
|
||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(resource);
|
||||
String resourceName = def.getName();
|
||||
|
||||
return createClientInvocation(theArgs, resource, resourceName);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -13,7 +13,7 @@ import ca.uhn.fhir.rest.client.BaseClientInvocation;
|
|||
import ca.uhn.fhir.rest.client.PostClientInvocation;
|
||||
import ca.uhn.fhir.rest.method.SearchMethodBinding.RequestType;
|
||||
|
||||
public class CreateMethodBinding extends BaseOutcomeReturningMethodBinding {
|
||||
public class CreateMethodBinding extends BaseOutcomeReturningMethodBindingWithResourceParam {
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
package ca.uhn.fhir.rest.method;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationSystemEnum;
|
||||
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationTypeEnum;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.annotation.Delete;
|
||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||
import ca.uhn.fhir.rest.annotation.VersionIdParam;
|
||||
import ca.uhn.fhir.rest.client.BaseClientInvocation;
|
||||
import ca.uhn.fhir.rest.client.DeleteClientInvocation;
|
||||
import ca.uhn.fhir.rest.client.PostClientInvocation;
|
||||
import ca.uhn.fhir.rest.method.SearchMethodBinding.RequestType;
|
||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
|
||||
public class DeleteMethodBinding extends BaseOutcomeReturningMethodBinding {
|
||||
|
||||
|
||||
|
||||
private String myResourceName;
|
||||
private Integer myIdParameterIndex;
|
||||
|
||||
public DeleteMethodBinding(Method theMethod, FhirContext theContext, IResourceProvider theProvider) {
|
||||
super(theMethod, theContext, Delete.class);
|
||||
|
||||
Delete deleteAnnotation = theMethod.getAnnotation(Delete.class);
|
||||
Class<? extends IResource> resourceType = deleteAnnotation.resourceType();
|
||||
if (resourceType != Delete.NotSpecified.class) {
|
||||
RuntimeResourceDefinition def = theContext.getResourceDefinition(resourceType);
|
||||
myResourceName = def.getName();
|
||||
} else {
|
||||
if (theProvider!=null) {
|
||||
RuntimeResourceDefinition def = theContext.getResourceDefinition(theProvider.getResourceType());
|
||||
myResourceName = def.getName();
|
||||
}else {
|
||||
throw new ConfigurationException("Can not determine resource type for method '"+theMethod.getName() + "' on type " + theMethod.getDeclaringClass().getCanonicalName() + " - Did you forget to include the resourceType() value on the @" + Delete.class.getSimpleName() + " method annotation?");
|
||||
}
|
||||
}
|
||||
|
||||
myIdParameterIndex = Util.findIdParameterIndex(theMethod);
|
||||
if (myIdParameterIndex == null) {
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' on type '" + theMethod.getDeclaringClass().getCanonicalName() + "' has no parameter annotated with the @" + IdParam.class.getSimpleName() + " annotation");
|
||||
}
|
||||
|
||||
Integer versionIdParameterIndex = Util.findVersionIdParameterIndex(theMethod);
|
||||
if (versionIdParameterIndex!=null) {
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' on type '" + theMethod.getDeclaringClass().getCanonicalName() + "' has a parameter annotated with the @" + VersionIdParam.class.getSimpleName() + " annotation but delete methods may not have this annotation");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean allowVoidReturnType() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestfulOperationTypeEnum getResourceOperationType() {
|
||||
return RestfulOperationTypeEnum.DELETE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestfulOperationSystemEnum getSystemOperationType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<RequestType> provideAllowableRequestTypes() {
|
||||
return Collections.singleton(RequestType.DELETE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BaseClientInvocation createClientInvocation(Object[] theArgs, IResource resource, String resourceName) {
|
||||
StringBuilder urlExtension = new StringBuilder();
|
||||
urlExtension.append(resourceName);
|
||||
|
||||
return new PostClientInvocation(getContext(), resource, urlExtension.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getResourceName() {
|
||||
return myResourceName;
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public boolean matches(Request theRequest) {
|
||||
// // TODO Auto-generated method stub
|
||||
// return super.matches(theRequest);
|
||||
// }
|
||||
|
||||
@Override
|
||||
public BaseClientInvocation invokeClient(Object[] theArgs) throws InternalErrorException {
|
||||
IdDt idDt = (IdDt) theArgs[myIdParameterIndex];
|
||||
if (idDt == null) {
|
||||
throw new NullPointerException("ID can not be null");
|
||||
}
|
||||
String id = idDt.getValue();
|
||||
|
||||
DeleteClientInvocation retVal = new DeleteClientInvocation(getResourceName(), id);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
|
@ -23,7 +23,7 @@ import ca.uhn.fhir.rest.method.SearchMethodBinding.RequestType;
|
|||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
public class UpdateMethodBinding extends BaseOutcomeReturningMethodBinding {
|
||||
public class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithResourceParam {
|
||||
|
||||
private Integer myIdParameterIndex;
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ public class Constants {
|
|||
public static final int STATUS_HTTP_409_CONFLICT = 409;
|
||||
public static final int STATUS_HTTP_412_PRECONDITION_FAILED = 412;
|
||||
public static final String HEADER_CONTENT_LOCATION = "Content-Location";
|
||||
public static final int STATUS_HTTP_204_NO_CONTENT = 204;
|
||||
|
||||
static {
|
||||
Map<String, EncodingUtil> valToEncoding = new HashMap<String, EncodingUtil>();
|
||||
|
|
|
@ -101,7 +101,7 @@ public abstract class RestfulServer extends HttpServlet {
|
|||
if (Modifier.isPublic(m.getModifiers())) {
|
||||
ourLog.debug("Scanning public method: {}#{}", theProvider.getClass(), m.getName());
|
||||
|
||||
BaseMethodBinding foundMethodBinding = BaseMethodBinding.bindMethod(theProvider.getResourceType(), m, myFhirContext);
|
||||
BaseMethodBinding foundMethodBinding = BaseMethodBinding.bindMethod(theProvider.getResourceType(), m, myFhirContext, theProvider);
|
||||
if (foundMethodBinding != null) {
|
||||
r.addMethod(foundMethodBinding);
|
||||
ourLog.info(" * Method: {}#{} is a handler", theProvider.getClass(), m.getName());
|
||||
|
|
|
@ -14,6 +14,7 @@ import java.util.concurrent.TimeUnit;
|
|||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpDelete;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.client.methods.HttpPut;
|
||||
|
@ -41,6 +42,7 @@ import ca.uhn.fhir.model.dstu.composite.HumanNameDt;
|
|||
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
|
||||
import ca.uhn.fhir.model.dstu.resource.Conformance;
|
||||
import ca.uhn.fhir.model.dstu.resource.DiagnosticReport;
|
||||
import ca.uhn.fhir.model.dstu.resource.OperationOutcome;
|
||||
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||
import ca.uhn.fhir.model.dstu.valueset.IdentifierUseEnum;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
|
@ -48,6 +50,7 @@ import ca.uhn.fhir.model.primitive.StringDt;
|
|||
import ca.uhn.fhir.model.primitive.UriDt;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.annotation.Create;
|
||||
import ca.uhn.fhir.rest.annotation.Delete;
|
||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||
import ca.uhn.fhir.rest.annotation.IncludeParam;
|
||||
import ca.uhn.fhir.rest.annotation.OptionalParam;
|
||||
|
@ -547,6 +550,27 @@ public class ResfulServerMethodTest {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDelete() throws Exception {
|
||||
|
||||
// HttpPost httpPost = new HttpPost("http://localhost:" + ourPort +
|
||||
// "/Patient/1");
|
||||
// httpPost.setEntity(new StringEntity("test",
|
||||
// ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||
|
||||
HttpDelete httpGet = new HttpDelete("http://localhost:" + ourPort + "/Patient/1234");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
ourLog.info("Response was:\n{}", responseContent);
|
||||
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
|
||||
OperationOutcome patient = (OperationOutcome) ourCtx.newXmlParser().parseBundle(responseContent).getEntries().get(0).getResource();
|
||||
assertEquals("1234", patient.getIssueFirstRep().getDetails().getValue());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrettyPrint() throws Exception {
|
||||
|
||||
|
@ -718,6 +742,12 @@ public class ResfulServerMethodTest {
|
|||
return new MethodOutcome(true, id, version);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Delete()
|
||||
public void deleteDiagnosticReport(@IdParam IdDt theId) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -768,6 +798,15 @@ public class ResfulServerMethodTest {
|
|||
return new MethodOutcome(true, id, version);
|
||||
}
|
||||
|
||||
@Delete()
|
||||
public MethodOutcome deletePatient(@IdParam IdDt theId) {
|
||||
MethodOutcome retVal = new MethodOutcome();
|
||||
retVal.setOperationOutcome(new OperationOutcome());
|
||||
retVal.getOperationOutcome().addIssue().setDetails(theId.getValue());
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
@Search(queryName="someQueryNoParams")
|
||||
public Patient getPatientNoParams() {
|
||||
Patient next = getIdToPatient().get("1");
|
||||
|
|
Loading…
Reference in New Issue