001package ca.uhn.fhir.rest.server.method;
002
003/*
004 * #%L
005 * HAPI FHIR - Server Framework
006 * %%
007 * Copyright (C) 2014 - 2021 Smile CDR, Inc.
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.annotation.Annotation;
024import java.lang.reflect.Method;
025import java.util.Arrays;
026import java.util.Collections;
027import java.util.ListIterator;
028import java.util.Set;
029
030import org.hl7.fhir.instance.model.api.IIdType;
031
032import ca.uhn.fhir.context.ConfigurationException;
033import ca.uhn.fhir.context.FhirContext;
034import ca.uhn.fhir.rest.annotation.Patch;
035import ca.uhn.fhir.rest.annotation.ResourceParam;
036import ca.uhn.fhir.rest.api.PatchTypeEnum;
037import ca.uhn.fhir.rest.api.RequestTypeEnum;
038import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
039import ca.uhn.fhir.rest.api.server.RequestDetails;
040
041import javax.annotation.Nonnull;
042
043/**
044 * Base class for an operation that has a resource type but not a resource body in the
045 * request body
046 *
047 */
048public class PatchMethodBinding extends BaseOutcomeReturningMethodBindingWithResourceIdButNoResourceBody {
049
050        private int myPatchTypeParameterIndex = -1;
051        private int myResourceParamIndex;
052
053        public PatchMethodBinding(Method theMethod, FhirContext theContext, Object theProvider) {
054                super(theMethod, theContext, theProvider, Patch.class, theMethod.getAnnotation(Patch.class).type());
055
056                for (ListIterator<Class<?>> iter = Arrays.asList(theMethod.getParameterTypes()).listIterator(); iter.hasNext();) {
057                        int nextIndex = iter.nextIndex();
058                        Class<?> next = iter.next();
059                        if (next.equals(PatchTypeEnum.class)) {
060                                myPatchTypeParameterIndex = nextIndex;
061                        }
062                        for (Annotation nextAnnotation : theMethod.getParameterAnnotations()[nextIndex]) {
063                                if (nextAnnotation instanceof ResourceParam) {
064                                        myResourceParamIndex = nextIndex;
065                                }
066                        }
067                }
068
069                if (myPatchTypeParameterIndex == -1) {
070                        throw new ConfigurationException("Method has no parameter of type " + PatchTypeEnum.class.getName() + " - " + theMethod.toString());
071                }
072                if (myResourceParamIndex == -1) {
073                        throw new ConfigurationException("Method has no parameter with @" + ResourceParam.class.getSimpleName() + " annotation - " + theMethod.toString());
074                }
075        }
076
077        @Override
078        protected boolean allowVoidReturnType() {
079                return true;
080        }
081
082        @Override
083        public MethodMatchEnum incomingServerRequestMatchesMethod(RequestDetails theRequest) {
084                MethodMatchEnum retVal = super.incomingServerRequestMatchesMethod(theRequest);
085                if (retVal.ordinal() > MethodMatchEnum.NONE.ordinal()) {
086                        PatchTypeParameter.getTypeForRequestOrThrowInvalidRequestException(theRequest);
087                }
088                return retVal;
089        }
090
091        @Nonnull
092        @Override
093        public RestOperationTypeEnum getRestOperationType() {
094                return RestOperationTypeEnum.PATCH;
095        }
096
097        @Override
098        protected Set<RequestTypeEnum> provideAllowableRequestTypes() {
099                return Collections.singleton(RequestTypeEnum.PATCH);
100        }
101
102
103
104        @Override
105        protected void addParametersForServerRequest(RequestDetails theRequest, Object[] theParams) {
106                IIdType id = theRequest.getId();
107                id = UpdateMethodBinding.applyETagAsVersion(theRequest, id);
108                theParams[getIdParameterIndex()] = id;
109        }
110
111        @Override
112        protected String getMatchingOperation() {
113                return null;
114        }
115
116
117}