001package ca.uhn.fhir.rest.method;
002
003/*
004 * #%L
005 * HAPI FHIR - Core Library
006 * %%
007 * Copyright (C) 2014 - 2016 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.ArrayList;
026import java.util.Collection;
027import java.util.Collections;
028import java.util.HashSet;
029import java.util.List;
030import java.util.Map;
031import java.util.Set;
032
033import org.hl7.fhir.instance.model.api.IBaseResource;
034
035import ca.uhn.fhir.context.ConfigurationException;
036import ca.uhn.fhir.context.FhirContext;
037import ca.uhn.fhir.rest.api.SummaryEnum;
038import ca.uhn.fhir.rest.param.CollectionBinder;
039import ca.uhn.fhir.rest.server.Constants;
040import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
041import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
042
043public class SummaryEnumParameter implements IParameter {
044
045        @SuppressWarnings("rawtypes")
046        private Class<? extends Collection> myInnerCollectionType;
047
048        @SuppressWarnings("unchecked")
049        @Override
050        public void translateClientArgumentIntoQueryArgument(FhirContext theContext, Object theSourceClientArgument, Map<String, List<String>> theTargetQueryArguments, IBaseResource theTargetResource) throws InternalErrorException {
051                if (theSourceClientArgument instanceof Collection) {
052                        List<String> values = new ArrayList<String>();
053                        for (SummaryEnum next : (Collection<SummaryEnum>) theSourceClientArgument) {
054                                if (next != null) {
055                                        values.add(next.getCode());
056                                }
057                        }
058                        theTargetQueryArguments.put(Constants.PARAM_SUMMARY, values);
059                } else {
060                        SummaryEnum ss = (SummaryEnum) theSourceClientArgument;
061                        if (ss != null) {
062                                theTargetQueryArguments.put(Constants.PARAM_SUMMARY, Collections.singletonList(ss.getCode()));
063                        }
064                }
065        }
066
067        @Override
068        @SuppressWarnings({ "rawtypes", "unchecked" })
069        public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
070                Set<SummaryEnum> value = getSummaryValueOrNull(theRequest);
071                if (value == null || value.isEmpty()) {
072                        return null;
073                }
074                
075                if (myInnerCollectionType == null) {
076                        return value.iterator().next();
077                }
078                
079                try {
080                        Collection retVal = myInnerCollectionType.newInstance();
081                        retVal.addAll(value);
082                        return retVal;
083                } catch (InstantiationException e) {
084                        throw new InternalErrorException("Failed to instantiate " + myInnerCollectionType, e);
085                } catch (IllegalAccessException e) {
086                        throw new InternalErrorException("Failed to instantiate " + myInnerCollectionType, e);
087                }
088        }
089
090        public static Set<SummaryEnum> getSummaryValueOrNull(RequestDetails theRequest) {
091                String[] summary = theRequest.getParameters().get(Constants.PARAM_SUMMARY);
092
093                Set<SummaryEnum> retVal;
094                if (summary == null || summary.length == 0) {
095                        retVal = null;
096                } else if (isBlank(summary[0])) {
097                        retVal = null;
098                } else if (summary.length == 1) {
099                        retVal = toCollectionOrNull(SummaryEnum.fromCode(summary[0]));
100                        if (retVal == null) {
101                                retVal = toCollectionOrNull(SummaryEnum.fromCode(summary[0].toLowerCase()));
102                        }
103                } else {
104                        retVal = new HashSet<SummaryEnum>();
105                        for (String next : summary) {
106                                SummaryEnum value = SummaryEnum.fromCode(next);
107                                if (value == null) {
108                                        value = SummaryEnum.fromCode(next.toLowerCase());
109                                }
110                                if (value != null) {
111                                        retVal.add(value);
112                                }
113                        }
114                }
115                
116                if (retVal != null) {
117                        if (retVal.contains(SummaryEnum.TEXT)) {
118                                if (retVal.size() > 1) {
119                                        String msg = theRequest.getServer().getFhirContext().getLocalizer().getMessage(SummaryEnumParameter.class, "cantCombineText");
120                                        throw new InvalidRequestException(msg);
121                                }
122                        }
123                }
124                
125                return retVal;
126        }
127
128        private static Set<SummaryEnum> toCollectionOrNull(SummaryEnum theFromCode) {
129                if (theFromCode == null) {
130                        return null;
131                }
132                return Collections.singleton(theFromCode);
133        }
134
135        @Override
136        public void initializeTypes(Method theMethod, Class<? extends Collection<?>> theOuterCollectionType, Class<? extends Collection<?>> theInnerCollectionType, Class<?> theParameterType) {
137                if (theOuterCollectionType != null) {
138                        throw new ConfigurationException("Method '" + theMethod.getName() + "' in type '" + theMethod.getDeclaringClass().getCanonicalName() + "' is of type " + SummaryEnum.class + " but can not be a collection of collections");
139                }
140                if (theInnerCollectionType != null) {
141                        myInnerCollectionType = CollectionBinder.getInstantiableCollectionType(theInnerCollectionType, SummaryEnum.class.getSimpleName());
142                }
143        }
144
145}