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