001/*
002 * #%L
003 * HAPI FHIR - Core Library
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.api;
021
022import ca.uhn.fhir.context.FhirContext;
023import ca.uhn.fhir.i18n.Msg;
024import ca.uhn.fhir.rest.annotation.Patch;
025import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
026import jakarta.annotation.Nonnull;
027
028import java.util.HashMap;
029import java.util.Map;
030
031import static org.apache.commons.lang3.StringUtils.defaultString;
032import static org.apache.commons.lang3.StringUtils.isBlank;
033
034/**
035 * Parameter type for methods annotated with {@link Patch}
036 */
037public enum PatchTypeEnum {
038        JSON_PATCH(Constants.CT_JSON_PATCH),
039        XML_PATCH(Constants.CT_XML_PATCH),
040        FHIR_PATCH_JSON(Constants.CT_FHIR_JSON_NEW),
041        FHIR_PATCH_XML(Constants.CT_FHIR_XML_NEW);
042
043        private static volatile Map<String, PatchTypeEnum> ourContentTypeToPatchType;
044        private final String myContentType;
045
046        PatchTypeEnum(String theContentType) {
047                myContentType = theContentType;
048        }
049
050        public String getContentType() {
051                return myContentType;
052        }
053
054        @Nonnull
055        public static PatchTypeEnum forContentTypeOrThrowInvalidRequestException(
056                        FhirContext theContext, String theContentType) {
057                String contentType = defaultString(theContentType);
058                int semiColonIdx = contentType.indexOf(';');
059                if (semiColonIdx != -1) {
060                        contentType = theContentType.substring(0, semiColonIdx);
061                }
062                contentType = contentType.trim();
063
064                Map<String, PatchTypeEnum> map = ourContentTypeToPatchType;
065                if (map == null) {
066                        map = new HashMap<>();
067                        for (PatchTypeEnum next : values()) {
068                                map.put(next.getContentType(), next);
069                        }
070                        ourContentTypeToPatchType = map;
071                }
072
073                PatchTypeEnum retVal = map.get(contentType);
074                if (retVal == null) {
075                        if (isBlank(contentType)) {
076                                String msg = theContext.getLocalizer().getMessage(PatchTypeEnum.class, "missingPatchContentType");
077                                throw new InvalidRequestException(Msg.code(1964) + msg);
078                        }
079
080                        String msg = theContext
081                                        .getLocalizer()
082                                        .getMessageSanitized(PatchTypeEnum.class, "invalidPatchContentType", contentType);
083                        throw new InvalidRequestException(Msg.code(1965) + msg);
084                }
085
086                return retVal;
087        }
088}