/*
* Copyright 2007-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.paoding.rose.web.paramresolver;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import net.paoding.rose.web.annotation.FlashParam;
import net.paoding.rose.web.annotation.Param;
import org.apache.commons.lang.StringUtils;
import org.springframework.util.ClassUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Errors;
import org.springframework.web.multipart.MultipartFile;
/**
*
* @author 王志亮 [qieqie.wang@gmail.com]
*
*/
public class ParameterNameDiscovererImpl {
public String[] getParameterNames(Method method) {
Class<?>[] parameterTypes = method.getParameterTypes();
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
String[] names = new String[parameterTypes.length];
Map<String, Integer> counts = new HashMap<String, Integer>();
for (int i = 0; i < names.length; i++) {
Annotation[] annotations = parameterAnnotations[i];
for (Annotation annotation : annotations) {
String name = null;
if (annotation instanceof Param) {
name = ((Param) annotation).value();
} else if (annotation instanceof FlashParam) {
name = ((FlashParam) annotation).value();
}
if (name != null) {
if (StringUtils.isNotEmpty(name)) {
names[i] = name;
if ((parameterTypes[i] == BindingResult.class || parameterTypes[i] == Errors.class)
&& !name.endsWith("BindingResult")) {
names[i] = name + "BindingResult";
}
}
break;
}
}
if (names[i] != null) {
continue;
}
if (parameterTypes[i] == BindingResult.class || parameterTypes[i] == Errors.class) {
if (i > 0 && names[i - 1] != null) {
names[i] = names[i - 1] + "BindingResult";
continue;
}
}
String rawName = getParameterRawName(parameterTypes[i]);
if (rawName == null) {
continue;
}
names[i] = rawName;
Integer count = counts.get(rawName);
if (count == null) {
counts.put(rawName, 1);
} else {
counts.put(rawName, count + 1);
if (count == 1) {
for (int j = 0; j < i; j++) {
if (names[j] != null && names[j].equals(rawName)) {
names[j] = rawName + "1";
break;
}
}
}
if (names[i] == rawName) {
names[i] = names[i] + (count + 1);
}
}
}
Set<String> uniques = new HashSet<String>();
for (String name : names) {
if (name == null) {
continue;
}
if (uniques.contains(name)) {
// action方法不能有相同名字的@Param参数
throw new IllegalArgumentException("params with same name: '" + name + "'");
}
uniques.add(name);
}
return names;
}
protected String getParameterRawName(Class<?> clz) {
if (ClassUtils.isPrimitiveOrWrapper(clz) //
|| clz == String.class //
|| Map.class.isAssignableFrom(clz) //
|| Collection.class.isAssignableFrom(clz) //
|| clz.isArray() //
|| clz == MultipartFile.class) {
return null;
}
if (clz == MultipartFile.class) {
return null;
}
return ClassUtils.getShortNameAsProperty(clz);
}
public String[] getParameterNames(@SuppressWarnings("unchecked") Constructor ctor) {
throw new UnsupportedOperationException();
}
}