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