package ${basePackage}.frame.utils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;

/**
 * ClassUtil
 *
 * @author wangbing
 * @version 0.0.1
 * @since 2017-01-01
 */
public class ClassUtil {

    /**
     * 获取模板类所有字段
     *
     * @param clazz       模板对象
     * @param parentFirst 是否关注父类的字段
     * @return
     */
    public static Field[] getFields(Class clazz, boolean parentFirst) {
        Field[] fields = clazz.getDeclaredFields();

        if (parentFirst) {
            Field[] parentFields = getParentFields(clazz.getSuperclass());
            return concat(fields, parentFields);
        }
        return fields;
    }

    /**
     * 判断是不是集合的实现类
     *
     * @param clazz
     * @return
     */
    public static boolean isCollection(Class<?> clazz) {
        return Collection.class.isAssignableFrom(clazz);
    }

    /**
     * 获取GET方法
     *
     * @param name      成员变量名
     * @param pojoClass POJO对象
     * @return 方法
     */
    public static Method getMethod(String name, Class<?> pojoClass) {
        String getMethodName = "get" + StringUtil.upperFirstWord(name);
        try {
            return pojoClass.getMethod(getMethodName);
        } catch (Exception e) {
            getMethodName = "is" + StringUtil.upperFirstWord(name);
            try {
                return pojoClass.getMethod(getMethodName);
            } catch (NoSuchMethodException e1) {
                throw new RuntimeException("can not find[" + name + "]method");
            }
        }
    }

    /**
     * 获取SET方法
     *
     * @param name      成员变量名
     * @param pojoClass POJO对象
     * @return 方法
     */
    public static Method setMethod(String name, Class<?> pojoClass, Class<?> type) {
        String setMethodName = "set" + StringUtil.upperFirstWord(name);
        try {
            return pojoClass.getMethod(setMethodName, type);
        } catch (Exception e) {
            throw new RuntimeException("can not find[" + name + "]method");
        }
    }

    public static boolean isJavaClass(Field field) {
        Class<?> fieldType = field.getType();
        boolean isBaseClass = false;
        if (fieldType.isArray()) {
            isBaseClass = false;
        } else if (fieldType.isPrimitive() || fieldType.getPackage() == null
                || fieldType.getPackage().getName().equals("java.lang")
                || fieldType.getPackage().getName().equals("java.math")
                || fieldType.getPackage().getName().equals("java.sql")
                || fieldType.getPackage().getName().equals("java.util")) {
            isBaseClass = true;
        }
        return isBaseClass;
    }

    public static Field[] getFields(Class clazz) {
        return getFields(clazz, false);
    }

    private static Field[] getParentFields(Class parentClazz) {
        if (parentClazz != null) {
            Field[] fields = parentClazz.getDeclaredFields();
            Field[] parentFields = getParentFields(parentClazz.getSuperclass());
            return concat(fields, parentFields);
        }
        return new Field[0];
    }

    private static Field[] concat(Field[] f1, Field[] f2) {
        Field[] fields = new Field[f1.length + f2.length];
        System.arraycopy(f1, 0, fields, 0, f1.length);
        System.arraycopy(f2, 0, fields, f1.length, f2.length);
        return fields;
    }
}
