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