001package ca.uhn.fhir.rest.server.method;
002
003import static org.apache.commons.lang3.StringUtils.isBlank;
004/*
005 * #%L
006 * HAPI FHIR - Server Framework
007 * %%
008 * Copyright (C) 2014 - 2021 Smile CDR, Inc.
009 * %%
010 * Licensed under the Apache License, Version 2.0 (the "License");
011 * you may not use this file except in compliance with the License.
012 * You may obtain a copy of the License at
013 *
014 * http://www.apache.org/licenses/LICENSE-2.0
015 *
016 * Unless required by applicable law or agreed to in writing, software
017 * distributed under the License is distributed on an "AS IS" BASIS,
018 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
019 * See the License for the specific language governing permissions and
020 * limitations under the License.
021 * #L%
022 */
023import static org.apache.commons.lang3.StringUtils.isNotBlank;
024
025import java.lang.reflect.Method;
026import java.util.Collections;
027import java.util.Set;
028
029import org.hl7.fhir.instance.model.api.IBaseResource;
030import org.hl7.fhir.instance.model.api.IIdType;
031
032import ca.uhn.fhir.context.FhirContext;
033import ca.uhn.fhir.rest.annotation.Update;
034import ca.uhn.fhir.rest.api.Constants;
035import ca.uhn.fhir.rest.api.MethodOutcome;
036import ca.uhn.fhir.rest.api.RequestTypeEnum;
037import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
038import ca.uhn.fhir.rest.api.server.RequestDetails;
039import ca.uhn.fhir.rest.param.ParameterUtil;
040import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
041
042import javax.annotation.Nonnull;
043
044public class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithResourceParam {
045
046        public UpdateMethodBinding(Method theMethod, FhirContext theContext, Object theProvider) {
047                super(theMethod, theContext, Update.class, theProvider);
048        }
049
050        @Override
051        protected void addParametersForServerRequest(RequestDetails theRequest, Object[] theParams) {
052                IIdType id = theRequest.getId();
053                id = applyETagAsVersion(theRequest, id);
054                if (theRequest.getId() != null && theRequest.getId().hasVersionIdPart() == false) {
055                        if (id != null && id.hasVersionIdPart()) {
056                                theRequest.getId().setValue(id.getValue());
057                        }
058                }
059                super.addParametersForServerRequest(theRequest, theParams);
060        }
061
062        public static IIdType applyETagAsVersion(RequestDetails theRequest, IIdType id) {
063                String ifMatchValue = theRequest.getHeader(Constants.HEADER_IF_MATCH);
064                if (isNotBlank(ifMatchValue)) {
065                        ifMatchValue = ParameterUtil.parseETagValue(ifMatchValue);
066                        if (id != null && id.hasVersionIdPart() == false) {
067                                id = id.withVersion(ifMatchValue);
068                        }
069                }
070                return id;
071        }
072
073        @Override
074        protected String getMatchingOperation() {
075                return null;
076        }
077
078        @Nonnull
079        @Override
080        public RestOperationTypeEnum getRestOperationType() {
081                return RestOperationTypeEnum.UPDATE;
082        }
083
084        /*
085         * @Override public boolean incomingServerRequestMatchesMethod(RequestDetails theRequest) { if
086         * (super.incomingServerRequestMatchesMethod(theRequest)) { if (myVersionIdParameterIndex != null) { if
087         * (theRequest.getVersionId() == null) { return false; } } else { if (theRequest.getVersionId() != null) { return
088         * false; } } return true; } else { return false; } }
089         */
090
091        @Override
092        protected Set<RequestTypeEnum> provideAllowableRequestTypes() {
093                return Collections.singleton(RequestTypeEnum.PUT);
094        }
095
096        @Override
097        protected void validateResourceIdAndUrlIdForNonConditionalOperation(IBaseResource theResource, String theResourceId, String theUrlId, String theMatchUrl) {
098                if (isBlank(theMatchUrl)) {
099                        if (isBlank(theUrlId)) {
100                                String msg = getContext().getLocalizer().getMessage(BaseOutcomeReturningMethodBindingWithResourceParam.class, "noIdInUrlForUpdate");
101                                throw new InvalidRequestException(msg);
102                        }
103                        if (isBlank(theResourceId)) {
104                                String msg = getContext().getLocalizer().getMessage(BaseOutcomeReturningMethodBindingWithResourceParam.class, "noIdInBodyForUpdate");
105                                throw new InvalidRequestException(msg);
106                        }
107                        if (!theResourceId.equals(theUrlId)) {
108                                String msg = getContext().getLocalizer().getMessage(BaseOutcomeReturningMethodBindingWithResourceParam.class, "incorrectIdForUpdate", theResourceId, theUrlId);
109                                throw new InvalidRequestException(msg);
110                        }
111                } else {
112                        theResource.setId((IIdType) null);
113                }
114
115        }
116}