001package ca.uhn.fhir.rest.server.method;
002
003/*
004 * #%L
005 * HAPI FHIR - Server Framework
006 * %%
007 * Copyright (C) 2014 - 2022 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 */
022import ca.uhn.fhir.i18n.Msg;
023import static org.apache.commons.lang3.StringUtils.isBlank;
024
025import java.lang.reflect.Method;
026import java.util.*;
027
028import ca.uhn.fhir.context.ConfigurationException;
029import ca.uhn.fhir.rest.api.Constants;
030import ca.uhn.fhir.rest.api.SummaryEnum;
031import ca.uhn.fhir.rest.api.server.RequestDetails;
032import ca.uhn.fhir.rest.param.binder.CollectionBinder;
033import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
034import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
035
036public class SummaryEnumParameter implements IParameter {
037
038        @SuppressWarnings("rawtypes")
039        private Class<? extends Collection> myInnerCollectionType;
040
041
042        @Override
043        @SuppressWarnings({ "rawtypes", "unchecked" })
044        public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
045                Set<SummaryEnum> value = getSummaryValueOrNull(theRequest);
046                if (value == null || value.isEmpty()) {
047                        return null;
048                }
049                
050                if (myInnerCollectionType == null) {
051                        return value.iterator().next();
052                }
053                
054                try {
055                        Collection retVal = myInnerCollectionType.newInstance();
056                        retVal.addAll(value);
057                        return retVal;
058                } catch (InstantiationException e) {
059                        throw new InternalErrorException(Msg.code(378) + "Failed to instantiate " + myInnerCollectionType, e);
060                } catch (IllegalAccessException e) {
061                        throw new InternalErrorException(Msg.code(379) + "Failed to instantiate " + myInnerCollectionType, e);
062                }
063        }
064
065        public static Set<SummaryEnum> getSummaryValueOrNull(RequestDetails theRequest) {
066                String[] summary = theRequest.getParameters().get(Constants.PARAM_SUMMARY);
067
068                Set<SummaryEnum> retVal;
069                if (summary == null || summary.length == 0) {
070                        retVal = null;
071                } else if (isBlank(summary[0])) {
072                        retVal = null;
073                } else if (summary.length == 1 && summary[0].indexOf(',') == -1) {
074                        retVal = toCollectionOrNull(SummaryEnum.fromCode(summary[0]));
075                        if (retVal == null) {
076                                retVal = toCollectionOrNull(SummaryEnum.fromCode(summary[0].toLowerCase()));
077                        }
078                } else {
079                        retVal = new HashSet<>();
080                        for (String nextParamValue : summary) {
081                                for (String nextParamValueTok : nextParamValue.split(",")) {
082                                        SummaryEnum value = SummaryEnum.fromCode(nextParamValueTok);
083                                        if (value == null) {
084                                                value = SummaryEnum.fromCode(nextParamValueTok.toLowerCase());
085                                        }
086                                        if (value != null) {
087                                                retVal.add(value);
088                                        }
089                                }
090                        }
091                }
092                
093                if (retVal != null) {
094                        if (retVal.contains(SummaryEnum.TEXT)) {
095                                if (retVal.size() > 1) {
096                                        String msg = theRequest.getServer().getFhirContext().getLocalizer().getMessage(SummaryEnumParameter.class, "cantCombineText");
097                                        throw new InvalidRequestException(Msg.code(380) + msg);
098                                }
099                        }
100                }
101                
102                return retVal;
103        }
104
105        private static Set<SummaryEnum> toCollectionOrNull(SummaryEnum theFromCode) {
106                if (theFromCode == null) {
107                        return null;
108                }
109                return Collections.singleton(theFromCode);
110        }
111
112        @Override
113        public void initializeTypes(Method theMethod, Class<? extends Collection<?>> theOuterCollectionType, Class<? extends Collection<?>> theInnerCollectionType, Class<?> theParameterType) {
114                if (theOuterCollectionType != null) {
115                        throw new ConfigurationException(Msg.code(381) + "Method '" + theMethod.getName() + "' in type '" + theMethod.getDeclaringClass().getCanonicalName() + "' is of type " + SummaryEnum.class + " but can not be a collection of collections");
116                }
117                if (theInnerCollectionType != null) {
118                        myInnerCollectionType = CollectionBinder.getInstantiableCollectionType(theInnerCollectionType, SummaryEnum.class.getSimpleName());
119                }
120        }
121
122}