All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.guerlab.spring.searchparams.FieldHelper Maven / Gradle / Ivy

package net.guerlab.spring.searchparams;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.guerlab.commons.exception.ApplicationException;

/**
 * 类字段助手
 *
 * @author guer
 *
 */
public class FieldHelper {

    private static final Logger LOGGER = LoggerFactory.getLogger(FieldHelper.class);

    private static final Class[] BASE_NUMBER_CLASS_LIST = new Class[] {
            Byte.TYPE, Short.TYPE, Long.TYPE, Long.TYPE, Float.TYPE, Double.TYPE
    };

    private static final Map, List> CACHE = new ConcurrentHashMap<>();

    private static final BaseFilter BASE_FILTER = new BaseFilter();

    private FieldHelper() {
        throw new SecurityException();
    }

    /**
     * 复制对象属性值
     *
     * @param in
     *            源对象
     * @param out
     *            目标对象
     */
    public static void valueCopy(
            final Object in,
            final Object out) {
        if (in == null || out == null) {
            return;
        }

        List inFields = getFiledsWithFilter(in.getClass(), BASE_FILTER);
        List outFields = getFiledsWithFilter(out.getClass(), BASE_FILTER);

        if (inFields.isEmpty() || outFields.isEmpty()) {
            return;
        }

        Map outFieldMap = outFields.stream().collect(Collectors.toMap(Field::getName, field -> field));

        inFields.stream().forEach(e -> valueCopyOnce(e, outFieldMap, in, out));
    }

    private static void valueCopyOnce(
            Field inField,
            Map outFieldMap,
            Object in,
            Object out) {
        if (inField == null) {
            return;
        }

        String name = inField.getName();
        Class inType = inField.getType();
        Field outField = outFieldMap.get(name);
        Class outType = outField == null ? null : outField.getType();

        if (outField == null || !inType.equals(outType)) {
            return;
        }

        try {
            Object object = read(in, name);
            write(out, name, object);
        } catch (Exception e) {
            LOGGER.trace(e.getMessage(), e);
        }
    }

    /**
     * 读取属性值
     *
     * @param object
     *            对象
     * @param name
     *            属性名
     * @return 属性值
     */
    public static Object get(
            Object object,
            String name) {
        try {
            return read(object, name);
        } catch (Exception e) {
            LOGGER.trace(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 读取属性值
     *
     * @param object
     *            对象
     * @param name
     *            属性名
     * @return 属性值
     */
    public static Object read(
            Object object,
            String name) {
        try {
            PropertyDescriptor propertyDescriptor = new PropertyDescriptor(name, object.getClass());
            Method method = propertyDescriptor.getReadMethod();
            return method.invoke(object, new Object[0]);
        } catch (Exception e) {
            throw new ApplicationException(e.getMessage(), e);
        }
    }

    /**
     * 设置属性
     *
     * @param object
     *            对象
     * @param name
     *            属性名
     * @param value
     *            属性值
     * @return 返回值
     */
    public static Object put(
            Object object,
            String name,
            Object value) {
        try {
            return write(object, name, value);
        } catch (Exception e) {
            LOGGER.trace(e.getMessage(), e);
            return null;
        }
    }

    /**
     * 设置属性
     *
     * @param object
     *            对象
     * @param name
     *            属性名
     * @param value
     *            属性值
     * @return 返回值
     */
    public static Object write(
            Object object,
            String name,
            Object value) {
        try {
            PropertyDescriptor propertyDescriptor = new PropertyDescriptor(name, object.getClass());
            Method method = propertyDescriptor.getWriteMethod();
            return method.invoke(object, value);
        } catch (Exception e) {
            throw new ApplicationException(e.getMessage(), e);
        }
    }

    /**
     * 判断某个类型是否为数值类
     *
     * @param fieldType
     *            字段类型
     * @return 是否为数值类型
     */
    public static boolean isNumberClass(
            Class fieldType) {
        if (fieldType == null) {
            return false;
        }

        if (Number.class.isAssignableFrom(fieldType)) {
            return true;
        }

        return Arrays.stream(BASE_NUMBER_CLASS_LIST).anyMatch(element -> element == fieldType);
    }

    /**
     * 根据类对象获取字段列表
     *
     * @param clazz
     *            类对象
     * @return 字段列表
     */
    public static List getFileds(
            Class clazz) {
        if (clazz == null) {
            return Collections.emptyList();
        }

        List allFields = CACHE.get(clazz);

        if (allFields != null) {
            return allFields;
        }

        allFields = new ArrayList<>();

        Deque> classes = new LinkedList<>();

        Class paramsClass = clazz;

        while (true) {
            Class superClass = paramsClass.getSuperclass();

            classes.add(paramsClass);

            if (Object.class.equals(superClass)) {
                break;
            }

            paramsClass = paramsClass.getSuperclass();
        }

        while (!classes.isEmpty()) {
            for (Field field : classes.pollFirst().getDeclaredFields()) {
                allFields.add(field);
            }
        }

        CACHE.put(clazz, allFields);

        return allFields;
    }

    /**
     * 获取过滤后的字段列表
     *
     * @param clazz
     *            类对象
     * @param filters
     *            过滤器列表
     * @return 字段列表
     */
    @SafeVarargs
    public static List getFiledsWithFilter(
            Class clazz,
            Predicate... filters) {

        List list = getFileds(clazz);

        if (list.isEmpty()) {
            return Collections.emptyList();
        }

        Stream stream = list.stream();

        if (filters != null && filters.length > 0) {
            for (Predicate filter : filters) {
                if (filter != null) {
                    stream = stream.filter(filter);
                }
            }
        }

        return stream.collect(Collectors.toList());
    }

    /**
     * 使用默认过滤器过滤后的字段列表
     *
     * @param clazz
     *            类对象
     * @return 字段列表
     */
    public static List getFiledsWithFilter(
            Class clazz) {
        return getFiledsWithFilter(clazz, BASE_FILTER, new CollectionAndArrayFilter());
    }

    /**
     * 字段过滤器,返回过滤后的字段
     *
     * @author guer
     *
     */
    private static class BaseFilter implements Predicate {

        @Override
        public boolean test(
                Field field) {
            if (field == null) {
                return false;
            }

            Class fieldType = field.getType();

            int mod = field.getModifiers();

            /*
             * 过滤静态和不可变量
             */
            if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) {
                return false;
            }

            /*
             * 判断是否为系统自带
             */
            boolean isSys = fieldType.getName().startsWith("java") || fieldType.isPrimitive();
            /*
             * 判断是否为枚举
             */
            boolean isEnum = fieldType.isEnum();

            return isSys || isEnum;
        }
    }

    /**
     * 集合类型字段过滤器
     *
     * @author guer
     *
     */
    private static class CollectionAndArrayFilter implements Predicate {

        @Override
        public boolean test(
                Field field) {
            return field != null && !Collection.class.isAssignableFrom(field.getType()) && !field.getType().isArray();
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy