001package net.gdface.utils;
002
003import java.io.IOException;
004import java.lang.reflect.Constructor;
005import java.lang.reflect.Member;
006import java.lang.reflect.Method;
007import java.util.HashMap;
008import java.util.Map;
009
010import net.gdface.utils.Assert;
011
012import org.apache.bytecode.ChainedParamReader;
013
014/**
015 * 获取构造函数或方法的参数名<br>
016 * 当不能获取参数名的情况下,
017 * {@link returnFakeNameIfFail}为{@code false}时返回{@code null},否则返回返回arg,arg2...格式的替代名<br>
018 * {@link returnFakeNameIfFail}默认为{@code true}
019 * @author guyadong
020 *
021 */
022public class ParameterNames {
023        private final Map<Class<?>, ChainedParamReader> readers = new HashMap<Class<?>, ChainedParamReader>();
024        private final Class<?> clazz;
025        /** 当获取无法参数名时是否返回arg,arg2...格式的替代名字 */
026        private boolean returnFakeNameIfFail = true;
027        public ParameterNames setReturnFakeNameIfFail(boolean returnFakeNameIfFail) {
028                this.returnFakeNameIfFail = returnFakeNameIfFail;
029                return this;
030        }
031
032        /**
033         * @param clazz 要构造函数或方法的参数名的类,为{@code null}时所有getParameterNames方法返回{@code null}
034         */
035        public ParameterNames(Class<?> clazz) {
036                this.clazz = clazz;
037                if(null != clazz){
038                        try {
039                                Class<?> c = clazz;
040                                do {
041                                        readers.put(c, new ChainedParamReader(c));
042                                } while (null != (c = c.getSuperclass()));
043                        } catch (IOException e) {
044                                throw new RuntimeException(e);
045                        }
046                }
047        }
048
049        /**
050         * 获取构造函数或方法的参数名
051         * @param reader
052         * @param member 构造函数或方法对象
053         * @return
054         */
055        private final String[] getParameterNames(ChainedParamReader reader, Member member) {
056                String [] parameterNames = null;
057                int paramCount ;
058                if (member instanceof Method){
059                        parameterNames = reader.getParameterNames((Method) member);
060                        paramCount = ((Method) member).getParameterTypes().length;
061                } else if (member instanceof Constructor){
062                        parameterNames = reader.getParameterNames((Constructor<?>) member);
063                        paramCount = ((Constructor<?>) member).getParameterTypes().length;
064                } else {
065                        throw new IllegalArgumentException("member type must be Method or Constructor");
066                }
067                if(this.returnFakeNameIfFail){
068                        if (null == parameterNames) {
069                                parameterNames = new String[paramCount];
070                                for (int i = 0; i < parameterNames.length; i++)
071                                        parameterNames[i] = String.format("arg%d", i);
072                        }
073                }
074                return parameterNames;
075        }
076
077        /**
078         * 获取构造函数或方法的参数名
079         * @param member 构造函数或方法对象
080         * @return
081         * @see #getParameterNames(ChainedParamReader, Member)
082         */
083        public final String[] getParameterNames(Member member) {
084                if(null == clazz){
085                        return null;
086                }
087                Assert.notNull(member, "member");
088                Class<?> declaringClass = member.getDeclaringClass();
089                ChainedParamReader reader;
090                if (null == (reader = readers.get(declaringClass))) {
091                        throw new IllegalArgumentException(String.format("%s is not member of %s", member.toString(),
092                                        declaringClass.getName()));
093                }
094                return getParameterNames(reader, member);
095        }
096        
097        /**
098         * 获取构造函数或方法的参数名<br>
099         * {@code name}为{@code null}时,获取构造函数的参数名
100         * @param name 方法名
101         * @param parameterTypes 构造函数或方法的参数类型
102         * @return
103         * @throws NoSuchMethodException
104         * @see #getParameterNames(String, Class)
105         */
106        public final String[] getParameterNames(String name, Class<?>[] parameterTypes) throws NoSuchMethodException {
107                if(null == clazz){
108                        return null;
109                }
110                try {
111                        Member member = null == name ? clazz.getConstructor(parameterTypes) : clazz.getMethod(name, parameterTypes);
112                        return getParameterNames(member);
113                } catch (SecurityException e) {
114                        throw new IllegalArgumentException(e);
115                }
116        }
117        /**
118         * {@link #getParameterNames(String, Class[])}不显式抛出异常版本
119         * @param name
120         * @param parameterTypes
121         * @return
122         */
123        public final String[] getParameterNamesUnchecked(String name, Class<?>[] parameterTypes)  {
124                try {
125                        return getParameterNames(name, parameterTypes);
126                } catch (NoSuchMethodException e) {
127                        throw new RuntimeException(e);
128                }
129        }
130}