Package org.nutz.lang

Source Code of org.nutz.lang.Mirror

package org.nutz.lang;

import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.nutz.castor.Castors;
import org.nutz.castor.FailToCastObjectException;
import org.nutz.lang.born.BornContext;
import org.nutz.lang.born.Borning;
import org.nutz.lang.born.BorningException;
import org.nutz.lang.born.Borns;
import org.nutz.lang.eject.EjectByField;
import org.nutz.lang.eject.EjectByGetter;
import org.nutz.lang.eject.Ejecting;
import org.nutz.lang.inject.InjectByField;
import org.nutz.lang.inject.InjectBySetter;
import org.nutz.lang.inject.Injecting;
import org.nutz.lang.util.Callback;
import org.nutz.lang.util.Callback3;

/**
* 包裹了 Class<?>, 提供了更多的反射方法
*
* @author zozoh(zozohtnt@gmail.com)
*
* @param <T>
*/
public class Mirror<T> {

    private static class DefaultTypeExtractor implements TypeExtractor {

        public Class<?>[] extract(Mirror<?> mirror) {
            Class<?> theType = mirror.getType();
            List<Class<?>> re = new ArrayList<Class<?>>(5);

            // 原生类型,增加其外覆类
            if (theType.isPrimitive()) {
                re.add(mirror.getWrapperClass());
                // 数字
                if (theType != boolean.class && theType != char.class) {
                    re.add(Number.class);
                }
            }
            // 日历
            else if (mirror.isOf(Calendar.class)) {
                re.add(Calendar.class);
            }
            // 其他类型,直接增加,并试图判断其抽象类
            else {
                re.add(theType);
                // 枚举
                if (mirror.klass.isEnum()) {
                    re.add(Enum.class);
                }
                // 数组
                else if (mirror.klass.isArray()) {
                    re.add(Array.class);
                }
                // 字符串
                else if (mirror.isStringLike())
                    re.add(CharSequence.class);
                // 数字
                else if (mirror.isNumber()) {
                    re.add(Number.class);
                }
                // Map
                else if (mirror.isOf(Map.class)) {
                    re.add(Map.class);
                }
                // 列表
                else if (mirror.isOf(List.class)) {
                    re.add(List.class);
                    re.add(Collection.class);
                }
                // 集合
                else if (mirror.isOf(Collection.class)) {
                    re.add(Collection.class);
                }
            }
            // 最后确保 Object 一定被加上了
            if (theType != Object.class)
                re.add(Object.class);

            return re.toArray(new Class<?>[re.size()]);
        }

    }

    private final static DefaultTypeExtractor defaultTypeExtractor = new DefaultTypeExtractor();

    /**
     * 包裹一个类
     *
     * @param classOfT
     *            类
     * @return Mirror
     */
    public static <T> Mirror<T> me(Class<T> classOfT) {
        return null == classOfT ? null
                               : new Mirror<T>(classOfT).setTypeExtractor(defaultTypeExtractor);
    }

    /**
     * 生成一个对象的 Mirror
     *
     * @param obj
     *            对象。
     * @return Mirror, 如果 对象 null,则返回 null
     */
    @SuppressWarnings("unchecked")
    public static <T> Mirror<T> me(T obj) {
        if (obj == null)
            return null;
        if (obj instanceof Class<?>)
            return (Mirror<T>) me((Class<?>) obj);
        return (Mirror<T>) me(obj.getClass());
    }

    /**
     * 包裹一个类,并设置自定义的类型提炼逻辑
     *
     * @param classOfT
     * @param typeExtractor
     * @return Mirror
     * @see org.nutz.lang.TypeExtractor
     */
    public static <T> Mirror<T> me(Class<T> classOfT, TypeExtractor typeExtractor) {
        return null == classOfT ? null
                               : new Mirror<T>(classOfT).setTypeExtractor(typeExtractor == null ? defaultTypeExtractor
                                                                                               : typeExtractor);
    }

    /**
     * 根据Type生成Mirror, 如果type是 {@link ParameterizedType} 类型的对象<br>
     * 可以使用 getGenericsTypes() 方法取得它的泛型数组
     */
    @SuppressWarnings({"unchecked"})
    public static <T> Mirror<T> me(Type type) {
        if (null == type) {
            return null;
        }
        Mirror<T> mir = (Mirror<T>) Mirror.me(Lang.getTypeClass(type));
        mir.type = type;
        return mir;
    }

    private Class<T> klass;

    private Type type;

    private TypeExtractor typeExtractor;

    /**
     * 设置自己的类型提炼逻辑
     *
     * @param typeExtractor
     * @return Mirror
     * @see org.nutz.lang.TypeExtractor
     */
    public Mirror<T> setTypeExtractor(TypeExtractor typeExtractor) {
        this.typeExtractor = typeExtractor;
        return this;
    }

    private Mirror(Class<T> classOfT) {
        klass = classOfT;
    }

    /**
     * 根据名称获取一个 Getter。
     * <p>
     * 比如,你想获取 abc 的 getter ,那么优先查找 getAbc(),如果没有则查找isAbc(),最后才是查找 abc()。
     *
     * @param fieldName
     * @return 方法
     * @throws NoSuchMethodException
     *             没有找到 Getter
     */
    public Method getGetter(String fieldName) throws NoSuchMethodException {
        String fn = Strings.upperFirst(fieldName);
        String _get = "get" + fn;
        String _is = "is" + fn;
        for (Method method : klass.getMethods()) {
            if (method.getParameterTypes().length != 0)
                continue;
            if (!method.isAccessible()) // 有些时候,即使是public的方法,也不一定能访问
                method.setAccessible(true);
            if (_get.equals(method.getName()))
                return method;
            if (_is.equals(method.getName())) {
                if (!Mirror.me(method.getReturnType()).isBoolean())
                    throw new NoSuchMethodException();
                return method;
            }
            if (fieldName.equals(method.getName()))
                return method;
        }
        throw Lang.makeThrow(NoSuchMethodException.class,
                             "Fail to find getter for [%s]->[%s]",
                             klass.getName(),
                             fieldName);
    }

    /**
     * 根据字段获取一个 Getter。
     * <p>
     * 比如,你想获取 abc 的 getter ,那么优先查找 getAbc(),如果 没有,则查找 abc()。
     *
     * @param field
     * @return 方法
     * @throws NoSuchMethodException
     *             没有找到 Getter
     */
    public Method getGetter(Field field) throws NoSuchMethodException {
        return getGetter(field.getName());
    }

    /**
     * 根据给定的一个方法,判断其是 Getter 还是 Setter
     * <p>
     * 对于回调会接受三个参数
     *
     * <pre>
     * callback(虚字段名, getter, setter)
     * </pre>
     *
     * 回调都会给一个参数,表示这个方法对应的虚拟字段名。所谓"虚拟字段",就比如
     * <ul>
     * <li>如果是 setAbc : 那么就是 "abc"
     * <li>如果是 getAbc : 那么就是 "abc"
     * <li>如果是 isAbc : 那么就是 "abc"
     * </ul>
     * 而 getter 或者 setter 参数如果为 null,则表示本函数未发现对应的 getter|setter
     *
     * @param method
     *            方法对象
     * @param callback
     *            回调, 如果为 null,则无视
     * @param whenError
     *            如果本方法即不是 Getter 也不是 Setter 的回调, 如果为 null,则无视
     */
    public static void evalGetterSetter(Method method,
                                        Callback3<String, Method, Method> callback,
                                        Callback<Method> whenError) {
        String name = method.getName();
        Method getter = null;
        Method setter = null;

        // 是 getter
        if (name.startsWith("get") && method.getParameterTypes().length == 0) {
            name = Strings.lowerFirst(name.substring(3));
            getter = method;
            // 寻找 setter
            try {
                setter = method.getDeclaringClass().getMethod("set" + Strings.upperFirst(name),
                                                              method.getReturnType());
            }
            catch (Exception e) {}

        }
        // 布尔的 getter
        else if (name.startsWith("is")
                 && Mirror.me(method.getReturnType()).isBoolean()
                 && method.getParameterTypes().length == 0) {
            name = Strings.lowerFirst(name.substring(2));
            getter = method;
            // 寻找 setter
            try {
                setter = method.getDeclaringClass().getMethod("set" + Strings.upperFirst(name),
                                                              method.getReturnType());
            }
            catch (Exception e) {}
        }
        // 是 setter
        else if (name.startsWith("set") && method.getParameterTypes().length == 1) {
            name = Strings.lowerFirst(name.substring(3));
            setter = method;
            // 寻找 getter
            try {
                getter = method.getDeclaringClass().getMethod("get" + Strings.upperFirst(name));
            }
            catch (Exception e) {}

        }
        // 虾米都不是,错!
        else {
            if (null != whenError)
                whenError.invoke(method);
            return;
        }
        // 最后调用回调
        if (null != callback)
            callback.invoke(name, getter, setter);
    }

    /**
     * 根据给定的一个方法,判断其是 Getter 还是 Setter,根据情况不同,调用不同的回调。
     *
     * @param method
     *            方法对象
     * @param errmsgFormat
     *            如果本方法即不是 Getter 也不是 Setter 的回调, 则根据这个消息模板抛出一个运行时异常。 这个字符串格式是个
     *            Java 的字符串模板,接受两个参数,第一个是方法名,第二个是所在类名
     * @param callback
     *            回调, 如果为 null,则无视
     */
    public static void evalGetterSetter(final Method method,
                                        final String errmsgFormat,
                                        Callback3<String, Method, Method> callback) {
        evalGetterSetter(method, callback, new Callback<Method>() {
            public void invoke(Method method) {
                throw Lang.makeThrow(errmsgFormat, method.getName(), method.getDeclaringClass()
                                                                           .getName());
            }
        });
    }

    /**
     * 根据一个字段获取 Setter
     * <p>
     * 比如,你想获取 abc 的 setter ,那么优先查找 setAbc(T abc),如果 没有,则查找 abc(T abc)。
     *
     * @param field
     *            字段
     * @return 方法
     * @throws NoSuchMethodException
     *             没找到 Setter
     */
    public Method getSetter(Field field) throws NoSuchMethodException {
        return getSetter(field.getName(), field.getType());
    }

    /**
     * 根据一个字段名和字段类型获取 Setter
     *
     * @param fieldName
     *            字段名
     * @param paramType
     *            字段类型
     * @return 方法
     * @throws NoSuchMethodException
     *             没找到 Setter
     */
    public Method getSetter(String fieldName, Class<?> paramType) throws NoSuchMethodException {
        try {
            String setterName = "set" + Strings.upperFirst(fieldName);
            try {
                return klass.getMethod(setterName, paramType);
            }
            catch (Throwable e) {
                try {
                    return klass.getMethod(fieldName, paramType);
                }
                catch (Throwable e1) {
                    Mirror<?> type = Mirror.me(paramType);
                    for (Method method : klass.getMethods()) {
                        if (method.getParameterTypes().length == 1)
                            if (method.getName().equals(setterName)
                                || method.getName().equals(fieldName)) {
                                if (null == paramType
                                    || type.canCastToDirectly(method.getParameterTypes()[0]))
                                    return method;
                            }
                    }
                    // 还是没有? 会不会是包装类型啊?
                    if (!paramType.isPrimitive()) {
                        Class<?> p = unWrapper();
                        if (null != p)
                            return getSetter(fieldName, p);
                    }
                    throw new RuntimeException();
                }
            }
        }
        catch (Throwable e) {
            throw Lang.makeThrow(NoSuchMethodException.class,
                                 "Fail to find setter for [%s]->[%s(%s)]",
                                 klass.getName(),
                                 fieldName,
                                 paramType.getName());
        }
    }

    /**
     * 根据一个字段名,获取一组有可能成为 Setter 函数
     *
     * @param fieldName
     * @return 函数数组
     */
    public Method[] findSetters(String fieldName) {
        String mName = "set" + Strings.upperFirst(fieldName);
        List<Method> ms = new ArrayList<Method>();
        for (Method m : this.klass.getMethods()) {
            if (!Modifier.isStatic(m.getModifiers())
                && m.getParameterTypes().length == 1
                && m.getName().equals(mName))
                ms.add(m);
        }
        return ms.toArray(new Method[ms.size()]);
    }

    /**
     * 获取一个字段。这个字段可以是当前类型或者其父类的私有字段。
     *
     * @param name
     *            字段名
     * @return 字段
     * @throws NoSuchFieldException
     */
    public Field getField(String name) throws NoSuchFieldException {
        Class<?> cc = klass;
        while (null != cc && cc != Object.class) {
            try {
                return cc.getDeclaredField(name);
            }
            catch (NoSuchFieldException e) {
                cc = cc.getSuperclass();
            }
        }
        throw new NoSuchFieldException(String.format("Can NOT find field [%s] in class [%s] and it's parents classes",
                                                     name,
                                                     klass.getName()));
    }

    /**
     * 获取一个字段。这个字段必须声明特殊的注解,第一遇到的对象会被返回
     *
     * @param ann
     *            注解
     * @return 字段
     * @throws NoSuchFieldException
     */
    public <AT extends Annotation> Field getField(Class<AT> ann) throws NoSuchFieldException {
        for (Field field : this.getFields()) {
            if (field.isAnnotationPresent(ann))
                return field;
        }
        throw new NoSuchFieldException(String.format("Can NOT find field [@%s] in class [%s] and it's parents classes",
                                                     ann.getName(),
                                                     klass.getName()));
    }

    /**
     * 获取一组声明了特殊注解的字段
     *
     * @param ann
     *            注解类型
     * @return 字段数组
     */
    public <AT extends Annotation> Field[] getFields(Class<AT> ann) {
        List<Field> fields = new LinkedList<Field>();
        for (Field f : this.getFields()) {
            if (f.isAnnotationPresent(ann))
                fields.add(f);
        }
        return fields.toArray(new Field[fields.size()]);
    }

    /**
     * 获得当前类以及所有父类的所有的属性,包括私有属性。 <br>
     * 但是父类不包括 Object 类,并且,如果子类的属性如果与父类重名,将会将其覆盖
     *
     * @return 属性列表
     */
    public Field[] getFields() {
        return _getFields(true, false, true, true);
    }

    /**
     * 获得所有的静态变量属性
     *
     * @param noFinal
     *            是否包括 final 修饰符的字段
     *
     * @return 字段列表
     */
    public Field[] getStaticField(boolean noFinal) {
        return _getFields(false, true, noFinal, true);
    }

    private Field[] _getFields(boolean noStatic, boolean noMember, boolean noFinal, boolean noInner) {
        Class<?> cc = klass;
        Map<String, Field> map = new LinkedHashMap<String, Field>();
        while (null != cc && cc != Object.class) {
            Field[] fs = cc.getDeclaredFields();
            for (int i = 0; i < fs.length; i++) {
                Field f = fs[i];
                int m = f.getModifiers();
                if (noStatic && Modifier.isStatic(m))
                    continue;
                if (noFinal && Modifier.isFinal(m))
                    continue;
                if (noInner && f.getName().startsWith("this$"))
                    continue;
                if (noMember && !Modifier.isStatic(m))
                    continue;
                if (map.containsKey(fs[i].getName()))
                    continue;

                map.put(fs[i].getName(), fs[i]);
            }
            cc = cc.getSuperclass();
        }
        return map.values().toArray(new Field[map.size()]);
    }

    /**
     * 向父类递归查找某一个运行时注解
     *
     * @param <A>
     *            注解类型参数
     * @param annType
     *            注解类型
     * @return 注解
     */
    public <A extends Annotation> A getAnnotation(Class<A> annType) {
        Class<?> cc = klass;
        A ann;
        do {
            ann = cc.getAnnotation(annType);
            cc = cc.getSuperclass();
        } while (null == ann && cc != Object.class);
        return ann;
    }

    /**
     * 取得当前类型的泛型数组
     */
    public Type[] getGenericsTypes() {
        if (type instanceof ParameterizedType) {
            return Lang.getGenericsTypes(type);
        }
        return null;
    }

    /**
     * 取得当前类型的指定泛型
     */
    public Type getGenericsType(int index) {
        Type[] ts = getGenericsTypes();
        return ts == null ? null : (ts.length <= index ? null : ts[index]);
    }

    /**
     * 获取本类型所有的方法,包括私有方法。不包括 Object 的方法
     */
    public Method[] getMethods() {
        Class<?> cc = klass;
        List<Method> list = new LinkedList<Method>();
        while (null != cc && cc != Object.class) {
            Method[] ms = cc.getDeclaredMethods();
            for (int i = 0; i < ms.length; i++) {
                list.add(ms[i]);
            }
            cc = cc.getSuperclass();
        }
        return list.toArray(new Method[list.size()]);
    }

    /**
     * 获取当前对象,所有的方法,包括私有方法。递归查找至自己某一个父类为止 。
     * <p>
     * 并且这个按照名称,消除重复的方法。子类方法优先
     *
     * @param top
     *            截至的父类
     * @return 方法数组
     */
    public Method[] getAllDeclaredMethods(Class<?> top) {
        Class<?> cc = klass;
        Map<String, Method> map = new LinkedHashMap<String, Method>();
        while (null != cc && cc != Object.class) {
            Method[] fs = cc.getDeclaredMethods();
            for (int i = 0; i < fs.length; i++) {
                String key = fs[i].getName() + Mirror.getParamDescriptor(fs[i].getParameterTypes());
                if (!map.containsKey(key))
                    map.put(key, fs[i]);
            }
            cc = cc.getSuperclass() == top ? null : cc.getSuperclass();
        }
        return map.values().toArray(new Method[map.size()]);
    }

    /**
     * 相当于 getAllDeclaredMethods(Object.class)
     *
     * @return 方法数组
     */
    public Method[] getAllDeclaredMethodsWithoutTop() {
        return getAllDeclaredMethods(Object.class);
    }

    /**
     * @return 所有静态方法
     */
    public Method[] getStaticMethods() {
        List<Method> list = new LinkedList<Method>();
        for (Method m : klass.getMethods()) {
            if (Modifier.isStatic(m.getModifiers()) && Modifier.isPublic(m.getModifiers()))
                list.add(m);
        }
        return list.toArray(new Method[list.size()]);
    }

    private static RuntimeException makeSetValueException(Class<?> type,
                                                          String name,
                                                          Object value,
                                                          Exception e) {
        if (e instanceof FailToSetValueException) {
            return (FailToSetValueException) e;
        }
        return new FailToSetValueException(String.format("Fail to set value [%s] to [%s]->[%s] because '%s'",
                                                         value,
                                                         type.getName(),
                                                         name,
                                                         e.getMessage()),
                                           e);
    }

    /**
     * 为对象的一个字段设值。 优先调用对象的 setter,如果没有,直接设置字段的值
     *
     * @param obj
     *            对象
     * @param field
     *            字段
     * @param value
     *            值。如果为 null,字符和数字字段,都会设成 0
     * @throws FailToSetValueException
     */
    public void setValue(Object obj, Field field, Object value) throws FailToSetValueException {
        if (!field.isAccessible())
            field.setAccessible(true);
        Class<?> ft = field.getType();
        // 非 null 值,进行转换
        if (null != value) {
            if (!field.getType().isAssignableFrom(value.getClass()))
                try {
                    value = Castors.me().castTo(value, field.getType());
                }
                catch (FailToCastObjectException e) {
                    throw makeSetValueException(obj.getClass(), field.getName(), value, e);
                }
        }
        // 如果是原生类型,转换成默认值
        else if (ft.isPrimitive()) {
            if (boolean.class == ft) {
                value = false;
            } else if (char.class == ft) {
                value = (char) 0;
            } else {
                value = (byte) 0;
            }
        }
        try {
            this.getSetter(field).invoke(obj, value);
        }
        catch (Exception e1) {
            try {
                field.set(obj, value);
            }
            catch (Exception e) {
                throw makeSetValueException(obj.getClass(), field.getName(), value, e);
            }
        }
    }

    /**
     * 为对象的一个字段设值。优先调用 setter 方法。
     *
     * @param obj
     *            对象
     * @param fieldName
     *            字段名
     * @param value
     *            值
     * @throws FailToSetValueException
     */
    public void setValue(Object obj, String fieldName, Object value) throws FailToSetValueException {
        if (null == value) {
            try {
                setValue(obj, this.getField(fieldName), null);
            }
            catch (Exception e1) {
                throw makeSetValueException(obj.getClass(), fieldName, null, e1);
            }
        } else {
            try {
                this.getSetter(fieldName, value.getClass()).invoke(obj, value);
            }
            catch (Exception e) {
                try {
                    setValue(obj, this.getField(fieldName), value);
                }
                catch (Exception e1) {
                    throw makeSetValueException(obj.getClass(), fieldName, value, e1);
                }
            }
        }
    }

    private static RuntimeException makeGetValueException(Class<?> type, String name, Throwable e) {
        return new FailToGetValueException(String.format("Fail to get value for [%s]->[%s]",
                                                         type.getName(),
                                                         name), e);
    }

    /**
     * 不调用 getter,直接获得字段的值
     *
     * @param obj
     *            对象
     * @param f
     *            字段
     * @return 字段的值。
     * @throws FailToGetValueException
     */
    public Object getValue(Object obj, Field f) throws FailToGetValueException {
        if (!f.isAccessible())
            f.setAccessible(true);
        try {
            return f.get(obj);
        }
        catch (Exception e) {
            throw makeGetValueException(obj.getClass(), f.getName(), e);
        }
    }

    /**
     * 优先通过 getter 获取字段值,如果没有,则直接获取字段值
     *
     * @param obj
     *            对象
     * @param name
     *            字段名
     * @return 字段值
     * @throws FailToGetValueException
     *             既没发现 getter,又没有字段
     */
    public Object getValue(Object obj, String name) throws FailToGetValueException {
        try {
            return this.getGetter(name).invoke(obj);
        }
        catch (Exception e) {
            try {
                return getValue(obj, getField(name));
            }
            catch (NoSuchFieldException e1) {
                if (obj != null && obj.getClass().isArray() && "length".equals(name)) {
                    return Lang.length(obj);
                }
                throw makeGetValueException(obj.getClass(), name, e);
            }
        }
    }

    /**
     * @return 对象类型
     */
    public Class<T> getType() {
        return klass;
    }

    private String _type_id;

    /**
     * @return 本类型的唯一标识名称
     */
    public String getTypeId() {
        if (null == _type_id) {
            if (null != type && type instanceof ParameterizedType) {
                ParameterizedType pmType = (ParameterizedType) type;
                List<Type> list = new ArrayList<Type>(pmType.getActualTypeArguments().length);
                for (Type pmA : pmType.getActualTypeArguments()) {
                    list.add(pmA);
                }
                _type_id = String.format("%s<%s>", klass.getName(), Lang.concat(",", list));
            }
            // TODO 这里应该作一些更多的判断
            else {
                _type_id = klass.getName();
            }
            _type_id += "_" + klass.getClassLoader();
        }
        return _type_id;
    }

    /**
     * @return 本类型真实的类型(保留了范型信息)
     */
    public Type getActuallyType() {
        return type == null ? klass : type;
    }

    /**
     * @return 对象提炼类型数组。从对象自身的类型到 Object,中间的继承关系中最有特点的几个类型
     */
    public Class<?>[] extractTypes() {
        return typeExtractor.extract(this);
    }

    /**
     * @return 获得外覆类
     *
     * @throws RuntimeException
     *             如果当前类型不是原生类型,则抛出
     */
    public Class<?> getWrapperClass() {
        if (!klass.isPrimitive()) {
            if (this.isPrimitiveNumber() || this.is(Boolean.class) || this.is(Character.class))
                return klass;
            throw Lang.makeThrow("Class '%s' should be a primitive class", klass.getName());
        }
        // TODO 用散列能快一点
        if (is(int.class))
            return Integer.class;
        if (is(char.class))
            return Character.class;
        if (is(boolean.class))
            return Boolean.class;
        if (is(long.class))
            return Long.class;
        if (is(float.class))
            return Float.class;
        if (is(byte.class))
            return Byte.class;
        if (is(short.class))
            return Short.class;
        if (is(double.class))
            return Double.class;

        throw Lang.makeThrow("Class [%s] has no wrapper class!", klass.getName());
    }

    /**
     * @return 获得外覆类,如果没有外覆类,则返回自身的类型
     */
    public Class<?> getWrapper() {
        if (klass.isPrimitive())
            return getWrapperClass();
        return klass;
    }

    /**
     * @return 如果当前类为内部类,则返回其外部类。否则返回 null
     */
    public Class<?> getOuterClass() {
        if (Modifier.isStatic(klass.getModifiers()))
            return null;
        String name = klass.getName();
        int pos = name.lastIndexOf('$');
        if (pos == -1)
            return null;
        name = name.substring(0, pos);
        try {
            return Lang.loadClass(name);
        }
        catch (ClassNotFoundException e) {
            return null;
        }
    }

    /**
     * 获取对象构建器
     *
     * @param args
     *            构造函数参数
     * @return 当前对象的构建方式。
     *
     * @throws BorningException
     *             当没有发现合适的 Borning 时抛出
     *
     * @see org.nutz.lang.born.Borning
     */
    public Borning<T> getBorning(Object... args) throws BorningException {
        BornContext<T> bc = Borns.eval(klass, args);
        if (null == bc)
            throw new BorningException(klass, args);

        return bc.getBorning();
    }

    /**
     * 获取对象构建器
     *
     * @param argTypes
     *            构造函数参数类型数组
     * @return 当前对象构建方式
     *
     * @throws BorningException
     *             当没有发现合适的 Borning 时抛出
     * @throws NullPointerException
     *             when args is null
     */
    public Borning<T> getBorningByArgTypes(Class<?>... argTypes) throws BorningException {
        BornContext<T> bc = Borns.evalByArgTypes(klass, argTypes);
        if (null == bc)
            throw new BorningException(klass, argTypes);
        return bc.getBorning();
    }

    /**
     * 根据构造函数参数,创建一个对象。
     *
     * @param args
     *            构造函数参数
     * @return 新对象
     */
    public T born(Object... args) {
        BornContext<T> bc = Borns.eval(klass, args);
        if (null == bc)
            throw new BorningException(klass, args);

        return bc.doBorn();
    }

    private static boolean doMatchMethodParamsType(Class<?>[] paramTypes, Class<?>[] methodArgTypes) {
        if (paramTypes.length == 0 && methodArgTypes.length == 0)
            return true;
        if (paramTypes.length == methodArgTypes.length) {
            for (int i = 0; i < paramTypes.length; i++)
                if (!Mirror.me(paramTypes[i]).canCastToDirectly((methodArgTypes[i])))
                    return false;
            return true;
        } else if (paramTypes.length + 1 == methodArgTypes.length) {
            if (!methodArgTypes[paramTypes.length].isArray())
                return false;
            for (int i = 0; i < paramTypes.length; i++)
                if (!Mirror.me(paramTypes[i]).canCastToDirectly((methodArgTypes[i])))
                    return false;
            return true;
        }
        return false;
    }

    /**
     * 根据函数名称和参数,返回一个函数调用方式
     *
     * @param methodName
     *            函数名
     * @param args
     *            参数
     * @return 函数调用方式
     */
    public Invoking getInvoking(String methodName, Object... args) {
        return new Invoking(klass, methodName, args);
    }

    /**
     * 根据字段名,得出一个字段注入方式。优先用 Setter
     *
     * @param fieldName
     *            字段名
     * @return 注入方式。
     */
    public Injecting getInjecting(String fieldName) {
        Method[] sss = this.findSetters(fieldName);
        if (sss.length == 1)
            return new InjectBySetter(sss[0]);
        else
            try {
                Field field = this.getField(fieldName);
                try {
                    return new InjectBySetter(this.getSetter(field));
                }
                catch (NoSuchMethodException e) {
                    return new InjectByField(field);
                }
            }
            catch (NoSuchFieldException e) {
                throw Lang.wrapThrow(e);
            }
    }

    /**
     * 根据字段名获得一个字段输入方式。优先用 Getter
     *
     * @param fieldName
     *            字段名
     * @return 输出方式
     */
    public Ejecting getEjecting(String fieldName) {
        try {
            return new EjectByGetter(getGetter(fieldName));
        }
        catch (NoSuchMethodException e) {
            try {
                Field field = this.getField(fieldName);
                try {
                    return new EjectByGetter(getGetter(field));
                }
                catch (NoSuchMethodException e1) {
                    return new EjectByField(field);
                }
            }
            catch (NoSuchFieldException e1) {
                throw Lang.wrapThrow(e1);
            }
        }

    }

    /**
     * 调用对象的一个方法
     *
     * @param obj
     *            对象
     * @param methodName
     *            方法名
     * @param args
     *            参数
     * @return 调用结果
     */
    public Object invoke(Object obj, String methodName, Object... args) {
        return getInvoking(methodName, args).invoke(obj);
    }

    /**
     * 根据一组参数样例,获取一个合理的调用方法
     *
     * @param name
     *            方法名
     * @param args
     *            参数样例
     * @return
     */
    public Method findMethod(String name, Object[] args) throws NoSuchMethodException {
        if (null == args || args.length == 0)
            return findMethod(name);
        Class<?>[] paramTypes = new Class<?>[args.length];
        for (int i = 0; i < args.length; i++)
            paramTypes[i] = args[i].getClass();
        return findMethod(name, paramTypes);
    }

    /**
     * 查找一个方法。匹配的很宽泛
     *
     * @param name
     *            方法名
     * @param paramTypes
     *            参数类型列表
     * @return 方法
     * @throws NoSuchMethodException
     */
    public Method findMethod(String name, Class<?>... paramTypes) throws NoSuchMethodException {
        try {
            return klass.getMethod(name, paramTypes);
        }
        catch (NoSuchMethodException e) {
            for (Method m : klass.getMethods()) {
                if (m.getName().equals(name))
                    if (doMatchMethodParamsType(paramTypes, m.getParameterTypes()))
                        return m;
            }
        }
        throw new NoSuchMethodException(String.format("Fail to find Method %s->%s with params:\n%s",
                                                      klass.getName(),
                                                      name,
                                                      Castors.me().castToString(paramTypes)));
    }

    /**
     * 根据名称和参数个数,查找一组方法
     *
     * @param name
     *            方法名
     * @param argNumber
     *            参数个数
     * @return 方法数组
     */
    public Method[] findMethods(String name, int argNumber) {
        List<Method> methods = new LinkedList<Method>();
        for (Method m : klass.getMethods())
            if (m.getName().equals(name))
                if (argNumber < 0)
                    methods.add(m);
                else if (m.getParameterTypes().length == argNumber)
                    methods.add(m);
        return methods.toArray(new Method[methods.size()]);
    }

    /**
     * 根据返回值类型,以及参数类型,查找第一个匹配的方法
     *
     * @param returnType
     *            返回值类型
     * @param paramTypes
     *            参数个数
     * @return 方法
     * @throws NoSuchMethodException
     */
    public Method findMethod(Class<?> returnType, Class<?>... paramTypes)
            throws NoSuchMethodException {
        for (Method m : klass.getMethods()) {
            if (returnType == m.getReturnType())
                if (paramTypes.length == m.getParameterTypes().length) {
                    boolean noThisOne = false;
                    for (int i = 0; i < paramTypes.length; i++) {
                        if (paramTypes[i] != m.getParameterTypes()[i]) {
                            noThisOne = true;
                            break;
                        }
                    }
                    if (!noThisOne)
                        return m;
                }
        }
        throw new NoSuchMethodException(String.format("Can not find method in [%s] with return type '%s' and arguemtns \n'%s'!",
                                                      klass.getName(),
                                                      returnType.getName(),
                                                      Castors.me().castToString(paramTypes)));

    }

    /**
     * 一个方法的参数类型同一个给定的参数数组是否可以匹配
     *
     * @param methodParamTypes
     *            参数类型列表
     * @param args
     *            参数
     * @return 匹配类型
     *
     * @see org.nutz.lang.MatchType
     */
    public static MatchType matchParamTypes(Class<?>[] methodParamTypes, Object... args) {
        return matchParamTypes(methodParamTypes, evalToTypes(args));
    }

    /**
     * 将一组对象,变成一组类型
     *
     * @param args
     *            对象数组
     * @return 类型数组
     */
    public static Class<?>[] evalToTypes(Object... args) {
        Class<?>[] types = new Class[args.length];
        int i = 0;
        for (Object arg : args)
            types[i++] = null == arg ? Object.class : arg.getClass();
        return types;
    }

    public static Object evalArgToSameTypeRealArray(Object... args) {
        Object array = evalArgToRealArray(args);
        return array == args ? null : array;
    }

    /**
     * 将一个 Object[] 数组,变成一个真正的数组 T[]
     *
     * @param args
     *            数组
     * @return 新数组,如果数组中包括了 null,或者数组的类型不一致,则返回旧数组
     */
    public static Object evalArgToRealArray(Object... args) {
        if (null == args || args.length == 0 || null == args[0])
            return null;
        Object re = null;
        /*
         * Check inside the arguments list, to see if all element is in same
         * type
         */
        Class<?> type = null;
        for (Object arg : args) {
            if (null == arg)
                break;
            if (null == type) {
                type = arg.getClass();
                continue;
            }
            if (arg.getClass() != type) {
                type = null;
                break;
            }
        }
        /*
         * If all argument elements in same type, make a new Array by the Type
         */
        if (type != null) {
            re = Array.newInstance(type, args.length);
            for (int i = 0; i < args.length; i++) {
                Array.set(re, i, args[i]);
            }
            return re;
        }
        return args;

    }

    /**
     * 匹配一个函数声明的参数类型数组和一个调用参数数组
     *
     * @param paramTypes
     *            函数声明参数数组
     * @param argTypes
     *            调用参数数组
     * @return 匹配类型
     *
     * @see org.nutz.lang.MatchType
     */
    public static MatchType matchParamTypes(Class<?>[] paramTypes, Class<?>[] argTypes) {
        int len = argTypes == null ? 0 : argTypes.length;
        if (len == 0 && paramTypes.length == 0)
            return MatchType.YES;
        if (paramTypes.length == len) {
            for (int i = 0; i < len; i++)
                if (!Mirror.me(argTypes[i]).canCastToDirectly((paramTypes[i])))
                    return MatchType.NO;
            return MatchType.YES;
        } else if (len + 1 == paramTypes.length) {
            if (!paramTypes[len].isArray())
                return MatchType.NO;
            for (int i = 0; i < len; i++)
                if (!Mirror.me(argTypes[i]).canCastToDirectly((paramTypes[i])))
                    return MatchType.NO;
            return MatchType.LACK;
        }
        return MatchType.NO;
    }

    /**
     * 判断当前对象是否为一个类型。精确匹配,即使是父类和接口,也不相等
     *
     * @param type
     *            类型
     * @return 是否相等
     */
    public boolean is(Class<?> type) {
        return null != type && klass == type;
    }

    /**
     * 判断当前对象是否为一个类型。精确匹配,即使是父类和接口,也不相等
     *
     * @param className
     *            类型名称
     * @return 是否相等
     */
    public boolean is(String className) {
        return klass.getName().equals(className);
    }

    /**
     * @param type
     *            类型或接口名
     * @return 当前对象是否为一个类型的子类,或者一个接口的实现类
     */
    public boolean isOf(Class<?> type) {
        return type.isAssignableFrom(klass);
    }

    /**
     * @return 当前对象是否为字符串
     */
    public boolean isString() {
        return is(String.class);
    }

    /**
     * @return 当前对象是否为CharSequence的子类
     */
    public boolean isStringLike() {
        return CharSequence.class.isAssignableFrom(klass);
    }

    /**
     * @return 当前对象是否简单的数值,比如字符串,布尔,字符,数字,日期时间等
     */
    public boolean isSimple() {
        return isStringLike() || isBoolean() || isChar() || isNumber() || isDateTimeLike();
    }

    /**
     * @return 当前对象是否为字符
     */
    public boolean isChar() {
        return is(char.class) || is(Character.class);
    }

    /**
     * @return 当前对象是否为枚举
     */
    public boolean isEnum() {
        return klass.isEnum();
    }

    /**
     * @return 当前对象是否为布尔
     */
    public boolean isBoolean() {
        return is(boolean.class) || is(Boolean.class);
    }

    /**
     * @return 当前对象是否为浮点
     */
    public boolean isFloat() {
        return is(float.class) || is(Float.class);
    }

    /**
     * @return 当前对象是否为双精度浮点
     */
    public boolean isDouble() {
        return is(double.class) || is(Double.class);
    }

    /**
     * @return 当前对象是否为整型
     */
    public boolean isInt() {
        return is(int.class) || is(Integer.class);
    }

    /**
     * @return 当前对象是否为整数(包括 int, long, short, byte)
     */
    public boolean isIntLike() {
        return isInt() || isLong() || isShort() || isByte() || is(BigDecimal.class);
    }

    /**
     * @return 当前类型是不是接口
     */
    public boolean isInterface() {
        return klass.isInterface();
    }

    /**
     * @return 当前对象是否为小数 (float, dobule)
     */
    public boolean isDecimal() {
        return isFloat() || isDouble();
    }

    /**
     * @return 当前对象是否为长整型
     */
    public boolean isLong() {
        return is(long.class) || is(Long.class);
    }

    /**
     * @return 当前对象是否为短整型
     */
    public boolean isShort() {
        return is(short.class) || is(Short.class);
    }

    /**
     * @return 当前对象是否为字节型
     */
    public boolean isByte() {
        return is(byte.class) || is(Byte.class);
    }

    /**
     * @param type
     *            类型
     * @return 否为一个对象的外覆类
     */
    public boolean isWrapperOf(Class<?> type) {
        try {
            return Mirror.me(type).getWrapperClass() == klass;
        }
        catch (Exception e) {}
        return false;
    }

    /**
     * @param type
     *            目标类型
     * @return 判断当前对象是否能直接转换到目标类型,而不产生异常
     */
    public boolean canCastToDirectly(Class<?> type) {
        if (klass == type || type.isAssignableFrom(klass))
            return true;
        if (klass.isPrimitive() && type.isPrimitive()) {
            if (this.isPrimitiveNumber() && Mirror.me(type).isPrimitiveNumber())
                return true;
        }
        try {
            return Mirror.me(type).getWrapperClass() == this.getWrapperClass();
        }
        catch (Exception e) {}
        return false;
    }

    /**
     * @return 当前对象是否为原生的数字类型 (即不包括 boolean 和 char)
     */
    public boolean isPrimitiveNumber() {
        return isInt() || isLong() || isFloat() || isDouble() || isByte() || isShort();
    }

    /**
     * 如果不是容器,也不是 POJO,那么它必然是个 Obj
     *
     * @return true or false
     */
    public boolean isObj() {
        return isContainer() || isPojo();
    }

    /**
     * 判断当前类型是否为POJO。 除了下面的类型,其他均为 POJO
     * <ul>
     * <li>原生以及所有包裹类
     * <li>类字符串
     * <li>类日期
     * <li>非容器
     * </ul>
     *
     * @return true or false
     */
    public boolean isPojo() {
        if (this.klass.isPrimitive() || this.isEnum())
            return false;

        if (this.isStringLike() || this.isDateTimeLike())
            return false;

        if (this.isPrimitiveNumber() || this.isBoolean() || this.isChar())
            return false;

        return !isContainer();
    }

    /**
     * 判断当前类型是否为容器,包括 Map,Collection, 以及数组
     *
     * @return true of false
     */
    public boolean isContainer() {
        return isColl() || isMap();
    }

    /**
     * 判断当前类型是否为数组
     *
     * @return true of false
     */
    public boolean isArray() {
        return klass.isArray();
    }

    /**
     * 判断当前类型是否为 Collection
     *
     * @return true of false
     */
    public boolean isCollection() {
        return isOf(Collection.class);
    }

    /**
     * @return 当前类型是否是数组或者集合
     */
    public boolean isColl() {
        return isArray() || isCollection();
    }

    /**
     * 判断当前类型是否为 Map
     *
     * @return true of false
     */
    public boolean isMap() {
        return isOf(Map.class);
    }

    /**
     * @return 当前对象是否为数字
     */
    public boolean isNumber() {
        return Number.class.isAssignableFrom(klass)
               || klass.isPrimitive()
               && !is(boolean.class)
               && !is(char.class);
    }

    /**
     * @return 当前对象是否在表示日期或时间
     */
    public boolean isDateTimeLike() {
        return Calendar.class.isAssignableFrom(klass)
               || java.util.Date.class.isAssignableFrom(klass)
               || java.sql.Date.class.isAssignableFrom(klass)
               || java.sql.Time.class.isAssignableFrom(klass);
    }

    public String toString() {
        return klass.getName();
    }

    /**
     * 根据函数参数类型数组的最后一个类型(一定是数组,表示变参),为最后一个变参生成一个空数组
     *
     * @param pts
     *            函数参数类型列表
     * @return 变参空数组
     */
    public static Object blankArrayArg(Class<?>[] pts) {
        return Array.newInstance(pts[pts.length - 1].getComponentType(), 0);
    }

    /**
     * 获取一个类的泛型参数数组,如果这个类没有泛型参数,返回 null
     */
    public static Type[] getTypeParams(Class<?> klass) {
        // TODO 这个实现会导致泛型丢失,只能取得申明类型
        if (klass == null || "java.lang.Object".equals(klass.getName()))
            return null;
        // 看看父类
        Type superclass = klass.getGenericSuperclass();
        if (null != superclass && superclass instanceof ParameterizedType)
            return ((ParameterizedType) superclass).getActualTypeArguments();

        // 看看接口
        Type[] interfaces = klass.getGenericInterfaces();
        for (Type inf : interfaces) {
            if (inf instanceof ParameterizedType) {
                return ((ParameterizedType) inf).getActualTypeArguments();
            }
        }
        return getTypeParams(klass.getSuperclass());
    }

    private static final Pattern PTN = Pattern.compile("(<)(.+)(>)");

    /**
     * 获取一个字段的泛型参数数组,如果这个字段没有泛型,返回空数组
     *
     * @param f
     *            字段
     * @return 泛型参数数组
     */
    public static Class<?>[] getGenericTypes(Field f) {
        String gts = f.toGenericString();
        Matcher m = PTN.matcher(gts);
        if (m.find()) {
            String s = m.group(2);
            String[] ss = Strings.splitIgnoreBlank(s);
            if (ss.length > 0) {
                Class<?>[] re = new Class<?>[ss.length];
                try {
                    for (int i = 0; i < ss.length; i++) {
                        String className = ss[i];
                        if (className.length() > 0 && className.charAt(0) == '?')
                            re[i] = Object.class;
                        else {
                            int pos = className.indexOf('<');
                            if (pos < 0)
                                re[i] = Lang.loadClass(className);
                            else
                                re[i] = Lang.loadClass(className.substring(0, pos));
                        }
                    }
                    return re;
                }
                catch (ClassNotFoundException e) {
                    throw Lang.wrapThrow(e);
                }
            }
        }
        return new Class<?>[0];
    }

    /**
     * 获取一个字段的某一个泛型参数,如果没有,返回 null
     *
     * @param f
     *            字段
     * @return 泛型参数数
     */
    public static Class<?> getGenericTypes(Field f, int index) {
        Class<?>[] types = getGenericTypes(f);
        if (null == types || types.length <= index)
            return null;
        return types[index];
    }

    /**
     * 获取一个类的某个一个泛型参数
     *
     * @param klass
     *            类
     * @param index
     *            参数下标 (从 0 开始)
     * @return 泛型参数类型
     */
    @SuppressWarnings("unchecked")
    public static <T> Class<T> getTypeParam(Class<?> klass, int index) {
        Type[] types = getTypeParams(klass);
        if (index >= 0 && index < types.length) {
            Type t = types[index];
            Class<T> clazz = (Class<T>) Lang.getTypeClass(t);
            if (clazz == null)
                throw Lang.makeThrow("Type '%s' is not a Class", t.toString());
            return clazz;
        }
        throw Lang.makeThrow("Class type param out of range %d/%d", index, types.length);
    }

    /**
     * @param klass
     *            类型
     * @return 一个类型的包路径
     */
    public static String getPath(Class<?> klass) {
        return klass.getName().replace('.', '/');
    }

    /**
     * @param parameterTypes
     *            函数的参数类型数组
     * @return 参数的描述符
     */
    public static String getParamDescriptor(Class<?>[] parameterTypes) {
        StringBuilder sb = new StringBuilder();
        sb.append('(');
        for (Class<?> pt : parameterTypes)
            sb.append(getTypeDescriptor(pt));
        sb.append(')');
        String s = sb.toString();
        return s;
    }

    /**
     * @param method
     *            方法
     * @return 这个方法的描述符
     */
    public static String getMethodDescriptor(Method method) {
        return getParamDescriptor(method.getParameterTypes())
               + getTypeDescriptor(method.getReturnType());
    }

    /**
     * @param c
     *            构造函数
     * @return 构造函数的描述符
     */
    public static String getConstructorDescriptor(Constructor<?> c) {
        return getParamDescriptor(c.getParameterTypes()) + "V";
    }

    /**
     * @param klass
     *            类型
     * @return 获得一个类型的描述符
     */
    public static String getTypeDescriptor(Class<?> klass) {
        if (klass.isPrimitive()) {
            if (klass == void.class)
                return "V";
            else if (klass == int.class)
                return "I";
            else if (klass == long.class)
                return "J";
            else if (klass == byte.class)
                return "B";
            else if (klass == short.class)
                return "S";
            else if (klass == float.class)
                return "F";
            else if (klass == double.class)
                return "D";
            else if (klass == char.class)
                return "C";
            else
                /* if(klass == boolean.class) */
                return "Z";
        }
        StringBuilder sb = new StringBuilder();
        if (klass.isArray()) {
            return sb.append('[').append(getTypeDescriptor(klass.getComponentType())).toString();
        }
        return sb.append('L').append(Mirror.getPath(klass)).append(';').toString();
    }

    /**
     * 查找包含某一个特殊注解的字段
     *
     * @param type
     *            类型
     * @param ann
     *            注解类型
     * @return 字段,null 表示没有找到
     */
    public static Field findField(Class<?> type, Class<? extends Annotation> ann) {
        Mirror<?> mirror = Mirror.me(type);
        for (Field f : mirror.getFields())
            if (f.isAnnotationPresent(ann))
                return f;
        return null;
    }

    public Class<?> unWrapper() {
        return TypeMapping2.get(klass);
    }

    private static final Map<Class<?>, Class<?>> TypeMapping2 = new HashMap<Class<?>, Class<?>>();
    static {

        TypeMapping2.put(Short.class, short.class);
        TypeMapping2.put(Integer.class, int.class);
        TypeMapping2.put(Long.class, long.class);
        TypeMapping2.put(Double.class, double.class);
        TypeMapping2.put(Float.class, float.class);
        TypeMapping2.put(Byte.class, byte.class);
        TypeMapping2.put(Character.class, char.class);
        TypeMapping2.put(Boolean.class, boolean.class);
    }

    /**
     *
     *
     * @param clzInterface
     *            接口clz
     * @return 判断是否实现某个接口
     */
    public boolean hasInterface(Class<?> clzInterface) {
        Class<?>[] interfaces = klass.getInterfaces();
        for (int i = 0; i < interfaces.length; i++) {
            if (clzInterface.equals(interfaces[i])) {
                return true;
            }
        }
        return false;
    }
}
TOP

Related Classes of org.nutz.lang.Mirror

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.