001package ca.uhn.fhir.rest.method; 002 003/* 004 * #%L 005 * HAPI FHIR - Core Library 006 * %% 007 * Copyright (C) 2014 - 2016 University Health Network 008 * %% 009 * Licensed under the Apache License, Version 2.0 (the "License"); 010 * you may not use this file except in compliance with the License. 011 * You may obtain a copy of the License at 012 * 013 * http://www.apache.org/licenses/LICENSE-2.0 014 * 015 * Unless required by applicable law or agreed to in writing, software 016 * distributed under the License is distributed on an "AS IS" BASIS, 017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 018 * See the License for the specific language governing permissions and 019 * limitations under the License. 020 * #L% 021 */ 022 023import java.lang.reflect.Method; 024import java.util.Collections; 025import java.util.List; 026import java.util.Map; 027import java.util.Set; 028 029import org.hl7.fhir.instance.model.api.IIdType; 030 031import ca.uhn.fhir.context.ConfigurationException; 032import ca.uhn.fhir.context.FhirContext; 033import ca.uhn.fhir.context.RuntimeResourceDefinition; 034import ca.uhn.fhir.model.api.IResource; 035import ca.uhn.fhir.model.primitive.IdDt; 036import ca.uhn.fhir.rest.annotation.Delete; 037import ca.uhn.fhir.rest.annotation.IdParam; 038import ca.uhn.fhir.rest.annotation.VersionIdParam; 039import ca.uhn.fhir.rest.api.RequestTypeEnum; 040import ca.uhn.fhir.rest.api.RestOperationTypeEnum; 041import ca.uhn.fhir.rest.client.BaseHttpClientInvocation; 042import ca.uhn.fhir.rest.server.IResourceProvider; 043import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; 044import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; 045 046public class DeleteMethodBinding extends BaseOutcomeReturningMethodBinding { 047 048 private String myResourceName; 049 private Integer myIdParameterIndex; 050 051 public DeleteMethodBinding(Method theMethod, FhirContext theContext, Object theProvider) { 052 super(theMethod, theContext, Delete.class, theProvider); 053 054 Delete deleteAnnotation = theMethod.getAnnotation(Delete.class); 055 Class<? extends IResource> resourceType = deleteAnnotation.type(); 056 if (resourceType != IResource.class) { 057 RuntimeResourceDefinition def = theContext.getResourceDefinition(resourceType); 058 myResourceName = def.getName(); 059 } else { 060 if (theProvider != null && theProvider instanceof IResourceProvider) { 061 RuntimeResourceDefinition def = theContext.getResourceDefinition(((IResourceProvider) theProvider).getResourceType()); 062 myResourceName = def.getName(); 063 } else { 064 throw new ConfigurationException( 065 "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?"); 066 } 067 } 068 069 myIdParameterIndex = MethodUtil.findIdParameterIndex(theMethod, getContext()); 070 if (myIdParameterIndex == null) { 071 throw new ConfigurationException("Method '" + theMethod.getName() + "' on type '" + theMethod.getDeclaringClass().getCanonicalName() + "' has no parameter annotated with the @" + IdParam.class.getSimpleName() + " annotation"); 072 } 073 074 Integer versionIdParameterIndex = MethodUtil.findVersionIdParameterIndex(theMethod); 075 if (versionIdParameterIndex != null) { 076 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"); 077 } 078 079 } 080 081 @Override 082 protected boolean allowVoidReturnType() { 083 return true; 084 } 085 086 @Override 087 public RestOperationTypeEnum getRestOperationType() { 088 return RestOperationTypeEnum.DELETE; 089 } 090 091 @Override 092 protected Set<RequestTypeEnum> provideAllowableRequestTypes() { 093 return Collections.singleton(RequestTypeEnum.DELETE); 094 } 095 096 @Override 097 protected BaseHttpClientInvocation createClientInvocation(Object[] theArgs, IResource theResource) { 098 StringBuilder urlExtension = new StringBuilder(); 099 urlExtension.append(getContext().getResourceDefinition(theResource).getName()); 100 101 return new HttpPostClientInvocation(getContext(), theResource, urlExtension.toString()); 102 } 103 104 @Override 105 public String getResourceName() { 106 return myResourceName; 107 } 108 109 @Override 110 public BaseHttpClientInvocation invokeClient(Object[] theArgs) throws InternalErrorException { 111 IdDt idDt = (IdDt) theArgs[myIdParameterIndex]; 112 if (idDt == null) { 113 throw new NullPointerException("ID can not be null"); 114 } 115 116 if (idDt.hasResourceType() == false) { 117 idDt = idDt.withResourceType(getResourceName()); 118 } else if (getResourceName().equals(idDt.getResourceType()) == false) { 119 throw new InvalidRequestException("ID parameter has the wrong resource type, expected '" + getResourceName() + "', found: " + idDt.getResourceType()); 120 } 121 122 HttpDeleteClientInvocation retVal = createDeleteInvocation(idDt); 123 124 for (int idx = 0; idx < theArgs.length; idx++) { 125 IParameter nextParam = getParameters().get(idx); 126 nextParam.translateClientArgumentIntoQueryArgument(getContext(), theArgs[idx], null, null); 127 } 128 129 return retVal; 130 } 131 132 public static HttpDeleteClientInvocation createDeleteInvocation(IIdType theId) { 133 HttpDeleteClientInvocation retVal = new HttpDeleteClientInvocation(theId); 134 return retVal; 135 } 136 137 @Override 138 protected void addParametersForServerRequest(RequestDetails theRequest, Object[] theParams) { 139 theParams[myIdParameterIndex] = theRequest.getId(); 140 } 141 142 @Override 143 protected String getMatchingOperation() { 144 return null; 145 } 146 147 public static HttpDeleteClientInvocation createDeleteInvocation(String theSearchUrl) { 148 HttpDeleteClientInvocation retVal = new HttpDeleteClientInvocation(theSearchUrl); 149 return retVal; 150 } 151 152 public static HttpDeleteClientInvocation createDeleteInvocation(String theResourceType, Map<String, List<String>> theParams) { 153 return new HttpDeleteClientInvocation(theResourceType, theParams); 154 } 155 156}