javabean property copy BeanUtil

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.FatalBeanException;

/**
 * Bean attribute copy tool class
 */
public class BeanUtil {

    private static final Log logger = LogFactory.getLog(BeanUtil.class);

    /** bean nesting */
    private static final String NESTED = ".";

    /**
     * Copy bean properties (support nested properties, separated by dots)
     *
     * @param source
     * Source object to copy properties
     *
     * @param dest
     * Destination object to copy properties
     *
     * @param includeProperties
     * List of copied properties
     *
     * @author yang_qiao
     *
     * @throws InvocationTargetException
     *
     * @throws IllegalAccessException
     *
     * @throws IllegalArgumentException
     *
     * @throws InstantiationException
     *
     * @throws IntrospectionException
     *
     * @date 2013-12-18
     */
    public static final void copyIncludeProperties(final Object source,
            Object dest, final String[] includeProperties)
            throws IllegalArgumentException, IllegalAccessException,
            InvocationTargetException, InstantiationException,
            IntrospectionException {
        if (includeProperties == null || includeProperties.length == 0) {
            throw new IllegalArgumentException("The list of attributes to be copied was not passed in");
        }
        if (source == null) {
            throw new IllegalArgumentException("The source object to be copied is empty");
        }
        if (dest == null) {
            throw new IllegalArgumentException("The destination object to be copied is empty");
        }
        // log information
        if (logger.isTraceEnabled()) {
            logger.trace("[source bean: " + source.getClass().getName() + " ]");
            logger.trace("[destination bean: " + dest.getClass().getName()
                    + " ]");
        }
        // copy
        for (String property : includeProperties) {
            PropertyDescriptor sourcePropertyDescriptor = null;
            PropertyDescriptor destPropertyDescriptor = null;
            if (isSimpleProperty(property)) { // simple property
                sourcePropertyDescriptor = getProperty(property, source);
                destPropertyDescriptor = getProperty(property, dest);
                if (sourcePropertyDescriptor == null) {
                    throw new IllegalArgumentException("The source object to be copied does not have this attribute");
                }
                if (destPropertyDescriptor == null) {
                    throw new IllegalArgumentException("The target object to be copied does not have this attribute");
                }
                copyProperty (property, source, dest);
            } else { // nested bean properties
                Object target = dest;
                Object realSource = source;
                String[] nestedProperty = getNestedProperty(property);
                if (nestedProperty != null && nestedProperty.length > 1) {
                    for (int i = 0; i < nestedProperty.length - 1; i++) {
                        sourcePropertyDescriptor = getProperty(
                                nestedProperty[i], realSource);
                        destPropertyDescriptor = getProperty(nestedProperty[i],
                                target);
                        if (sourcePropertyDescriptor == null) {
                            throw new IllegalArgumentException("The source object to be copied does not have this attribute");
                        }
                        if (destPropertyDescriptor == null) {
                            throw new IllegalArgumentException(
                                    "This property does not exist in the target object to be copied to");
                        }
                        Method readMethod = sourcePropertyDescriptor
                                .getReadMethod();
                        realSource = readMethod.invoke(realSource);
                        readMethod = destPropertyDescriptor.getReadMethod();
                        Method writeMethod = destPropertyDescriptor
                                .getWriteMethod ();
                        Object value = readMethod.invoke(target);
                        if (value == null) {
                            value = destPropertyDescriptor.getPropertyType()
                                    .newInstance();
                            writeMethod.invoke(target, value);
                        }
                        target = value;
                    }
                    final String prop = nestedProperty[nestedProperty.length - 1];
                    sourcePropertyDescriptor = getProperty(prop, realSource);
                    destPropertyDescriptor = getProperty(prop, target);
                    if (sourcePropertyDescriptor == null) {
                        throw new IllegalArgumentException("The source object to be copied does not have this attribute");
                    }
                    if (destPropertyDescriptor == null) {
                        throw new IllegalArgumentException("The target object to be copied does not have this attribute");
                    }
                    copyProperty(prop, realSource, target);
                }
            }
        }
    }

    /**
     * Copy bean properties (support nested properties, separated by dots)
     *
     * @param source
     * Source object to copy properties
     *
     * @param dest
     * Destination object to copy properties
     *
     * @param includeProperties
     * List of copied properties
     *
     * @throws IntrospectionException
     *
     * @throws InvocationTargetException
     *
     * @throws IllegalAccessException
     *
     * @throws IllegalArgumentException
     *
     * @throws InstantiationException
     *
     * @throws ClassNotFoundException
     *
     * @throws IOException
     *
     */
    public static void copyProperties(final Object source, final Object dest,
            final String... excludeProperties) throws IntrospectionException,
            IllegalArgumentException, IllegalAccessException,
            InvocationTargetException, InstantiationException, IOException,
            ClassNotFoundException {
        final Object backupSource = clone(dest);
        if (source == null) {
            throw new IllegalArgumentException("The source object to be copied is empty");
        }
        if (dest == null) {
            throw new IllegalArgumentException("The destination object to be copied is empty");
        }
        org.apache.commons.beanutils.BeanUtils.copyProperties (dest, source);
        // restore excluded property values
        revertProperties(backupSource, dest, excludeProperties);
    }

    /**
     * Restore properties from backup object
     *
     * @param backup
     * Backup beans
     *
     * @param target
     * target bean
     *
     * @param properties
     * property list
     *
     * @throws InvocationTargetException
     *
     * @throws IllegalAccessException
     *
     * @throws IllegalArgumentException
     *
     * @throws IntrospectionException
     *
     * @throws InstantiationException
     */
    private static void revertProperties(final Object backup, Object target,
            final String... properties) throws IllegalArgumentException,
            IllegalAccessException, InvocationTargetException,
            IntrospectionException, InstantiationException {
        if (properties == null || properties.length == 0) {
            return;
        }
        if (backup == null) {
            throw new IllegalArgumentException("Backup object is empty");
        }
        if (target == null) {
            throw new IllegalArgumentException("The destination object is empty");
        }
        // log information
        if (logger.isTraceEnabled()) {
            logger.trace("[source bean: " + backup.getClass().getName() + " ]");
            logger.trace("[destination bean: " + target.getClass().getName()
                    + " ]");
        }
        // copy
        for (String property : properties) {
            PropertyDescriptor sourcePropertyDescriptor = null;
            PropertyDescriptor destPropertyDescriptor = null;
            if (isSimpleProperty(property)) { // simple property
                sourcePropertyDescriptor = getProperty(property, backup);
                destPropertyDescriptor = getProperty(property, target);
                if (sourcePropertyDescriptor == null) {
                    throw new IllegalArgumentException("The source object to be copied does not have this attribute");
                }
                if (destPropertyDescriptor == null) {
                    throw new IllegalArgumentException("The target object to be copied does not have this attribute");
                }
                copyProperty(property, backup, target);
            } else { // nested bean properties
                Object targetObj = target;
                Object realBackup = backup;
                String[] nestedProperty = getNestedProperty(property);
                if (nestedProperty != null && nestedProperty.length > 1) {
                    for (int i = 0; i < nestedProperty.length - 1; i++) {
                        sourcePropertyDescriptor = getProperty(
                                nestedProperty[i], realBackup);
                        destPropertyDescriptor = getProperty(nestedProperty[i],
                                targetObj);
                        if (sourcePropertyDescriptor == null) {
                            throw new IllegalArgumentException("The source object to be copied does not have this attribute");
                        }
                        if (destPropertyDescriptor == null) {
                            throw new IllegalArgumentException(
                                    "This property does not exist in the target object to be copied to");
                        }
                        Method readMethod = sourcePropertyDescriptor
                                .getReadMethod();
                        realBackup = readMethod.invoke(realBackup);
                        if (realBackup == null) { // Determine whether the nested property of the backup object is empty
                            realBackup = sourcePropertyDescriptor
                                    .getPropertyType().newInstance();
                        }
                        Method writeMethod = destPropertyDescriptor
                                .getWriteMethod ();
                        readMethod = destPropertyDescriptor.getReadMethod();
                        Object value = readMethod.invoke(targetObj);
                        if (value == null) {
                            value = destPropertyDescriptor.getPropertyType()
                                    .newInstance();
                            writeMethod.invoke(targetObj, value);
                        }
                        targetObj = value;
                    }
                    final String prop = nestedProperty[nestedProperty.length - 1];
                    sourcePropertyDescriptor = getProperty(prop, realBackup);
                    destPropertyDescriptor = getProperty(prop, targetObj);
                    if (sourcePropertyDescriptor == null) {
                        throw new IllegalArgumentException("The source object to be copied does not have this attribute");
                    }
                    if (destPropertyDescriptor == null) {
                        throw new IllegalArgumentException("The target object to be copied does not have this attribute");
                    }
                    copyProperty (prop, realBackup, targetObj);
                }
            }
        }
    }

    /**
     * Object clone
     */
    private static Object clone(final Object value) throws IOException,
            ClassNotFoundException {
        // Byte array output stream, temporarily stored in memory
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        // Serialization
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(value);
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        // deserialize
        return ois.readObject();
    }

    /**
     * Determine whether it is a simple property, yes, return true
     *
     * @author yang_qiao
     *
     * @date 2013-12-18
     */
    private static boolean isSimpleProperty(final String property) {
        return !property.contains(NESTED);
    }

    /**
     * Get the properties of the target bean
     */
    private static PropertyDescriptor getProperty(final String propertyName,
            final Object target) {
        if (target == null) {
            new IllegalArgumentException("The object of the query property is empty");
        }
        if (propertyName == null || "".equals(propertyName)) {
            new IllegalArgumentException("The query attribute cannot be null");
        }
        PropertyDescriptor propertyDescriptor = null;
        try {
            propertyDescriptor = new PropertyDescriptor(propertyName,
                    target.getClass());
        } catch (IntrospectionException e) {
            logger.info("The property does not exist");
            return null;
        }
        return propertyDescriptor;
    }

    /**
     * Single attribute copy--the original data source and destination data source must have this attribute
     *
     * @throws InvocationTargetException
     *
     * @throws IllegalAccessException
     *
     * @throws IllegalArgumentException
     *
     * @throws IntrospectionException
     */
    public static void copyProperty(final String propertyName,
            final Object source, Object dest) throws IllegalArgumentException,
            IllegalAccessException, InvocationTargetException,
            IntrospectionException {
        PropertyDescriptor property;
        property = new PropertyDescriptor(propertyName, source.getClass());
        Method getMethod = property.getReadMethod();
        Object value = getMethod.invoke(source);
        property = new PropertyDescriptor(propertyName, dest.getClass());
        Method setMethod = property.getWriteMethod();
        setMethod.invoke(dest, value);
    }

    /**
     * Get properties of nested beans
     *
     * @author yang_qiao
     *
     * @date 2013-12-18
     */
    public static String[] getNestedProperty(final String nestedProperty) {
        if (nestedProperty == null || "".equals(nestedProperty)) {
            new IllegalArgumentException("Argument is null");
        }
        return nestedProperty.split("\\" + NESTED);
    }

    /**
     * Ignore null copy property values
     * @param source
     * @param target
     * @throws BeansException
     */
    public static void copyProperties(Object source, Object target) throws BeansException {
    	 if (source == null) {
             throw new IllegalArgumentException("The source object to be copied is empty");
         }
         if (target == null) {
             throw new IllegalArgumentException("The destination object to be copied is empty");
         }
        Class<?> actualEditable = target.getClass();
        PropertyDescriptor[] targetPds = org.springframework.beans.BeanUtils.getPropertyDescriptors(actualEditable);
        for (PropertyDescriptor targetPd : targetPds) {
            if (targetPd.getWriteMethod() != null) {
                PropertyDescriptor sourcePd = org.springframework.beans.BeanUtils.getPropertyDescriptor(source.getClass(), targetPd.getName());
                if (sourcePd != null && sourcePd.getReadMethod() != null) {
                    try {
                        Method readMethod = sourcePd.getReadMethod();
                        if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
                            readMethod.setAccessible(true);
                        }
                        Object value = readMethod.invoke(source);
                        // Here it is judged whether the following value is empty. Of course, some special requirements can also be processed here, such as format conversion during binding, etc.
                        if (value != null) {
                            Method writeMethod = targetPd.getWriteMethod ();
                            if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
                                writeMethod.setAccessible(true);
                            }
                            writeMethod.invoke(target, value);
                        }
                    } catch (Throwable ex) {
                        throw new FatalBeanException("Could not copy properties from source to target", ex);
                    }
                }
            }
        }
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326394572&siteId=291194637