001/*
002 * Copyright 2002-2018 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.web.method.annotation;
018
019import java.util.LinkedHashMap;
020import java.util.Map;
021
022import org.springframework.core.MethodParameter;
023import org.springframework.util.LinkedMultiValueMap;
024import org.springframework.util.MultiValueMap;
025import org.springframework.util.StringUtils;
026import org.springframework.web.bind.annotation.RequestParam;
027import org.springframework.web.bind.support.WebDataBinderFactory;
028import org.springframework.web.context.request.NativeWebRequest;
029import org.springframework.web.method.support.HandlerMethodArgumentResolver;
030import org.springframework.web.method.support.ModelAndViewContainer;
031
032/**
033 * Resolves {@link Map} method arguments annotated with an @{@link RequestParam}
034 * where the annotation does not specify a request parameter name.
035 * See {@link RequestParamMethodArgumentResolver} for resolving {@link Map}
036 * method arguments with a request parameter name.
037 *
038 * <p>The created {@link Map} contains all request parameter name/value pairs.
039 * If the method parameter type is {@link MultiValueMap} instead, the created
040 * map contains all request parameters and all their values for cases where
041 * request parameters have multiple values.
042 *
043 * @author Arjen Poutsma
044 * @author Rossen Stoyanchev
045 * @since 3.1
046 * @see RequestParamMethodArgumentResolver
047 */
048public class RequestParamMapMethodArgumentResolver implements HandlerMethodArgumentResolver {
049
050        @Override
051        public boolean supportsParameter(MethodParameter parameter) {
052                RequestParam requestParam = parameter.getParameterAnnotation(RequestParam.class);
053                return (requestParam != null && Map.class.isAssignableFrom(parameter.getParameterType()) &&
054                                !StringUtils.hasText(requestParam.name()));
055        }
056
057        @Override
058        public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
059                        NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
060
061                Map<String, String[]> parameterMap = webRequest.getParameterMap();
062                if (MultiValueMap.class.isAssignableFrom(parameter.getParameterType())) {
063                        MultiValueMap<String, String> result = new LinkedMultiValueMap<String, String>(parameterMap.size());
064                        for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
065                                for (String value : entry.getValue()) {
066                                        result.add(entry.getKey(), value);
067                                }
068                        }
069                        return result;
070                }
071                else {
072                        Map<String, String> result = new LinkedHashMap<String, String>(parameterMap.size());
073                        for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
074                                if (entry.getValue().length > 0) {
075                                        result.put(entry.getKey(), entry.getValue()[0]);
076                                }
077                        }
078                        return result;
079                }
080        }
081
082}