com.kangdainfo.common.util.BeanUtil.java Source code

Java tutorial

Introduction

Here is the source code for com.kangdainfo.common.util.BeanUtil.java

Source

/*
 * Copyright 15/06/2004 - <a href="http://www.liber.ufpe.br">Liber - UFPE</a>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
package com.kangdainfo.common.util;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.springframework.beans.BeanWrapperImpl;

/**
 * Classe com metodos uteis para o tratamento de beans ou Strings.
 *
 * @author <a href="mailto:jackganzha@dev.java.net">Marcos Silva Pereira</a>
 *
 * @since 15/06/2004
 * @version $Id: BeanUtil.java,v 1.3 2005/01/24 22:54:15 jackganzha Exp $
 */
public final class BeanUtil {

    /**
     *
     */
    public static final Class[] IS_NOT_FROM = new Class[] { Class.class, Collection.class, Map.class, String.class,
            Calendar.class, Date.class, StringBuffer.class, Number.class, Boolean.class, Character.class,
            Collection.class, Map.class };

    private BeanUtil() {

        // avoid instantiation...
    }

    /**
     * @param attributes
     * @param obj
     *
     * @return Object with the properties in attributes
     *
     * @see org.springframework.beans.BeanWrapper
     * @see BeanWrapperImpl
     * @see org.springframework.beans.BeanWrapper#setPropertyValues(
     *     java.util.Map)
     */
    public static Object populate(Map attributes, Object obj) {

        new BeanWrapperImpl(obj).setPropertyValues(attributes);

        return obj;

    }

    /**
     * @param attributes
     * @param clazz
     *
     * @return
     *
     * @see BeanUtil#populate(Map, Object)
     */
    public static Object populate(Map attributes, Class clazz) {

        try {

            Object instance = clazz.newInstance();

            return BeanUtil.populate(attributes, instance);

        } catch (InstantiationException e) {

            StringBuffer buffer = new StringBuffer();
            buffer.append("Could not populate a bean from class ");
            buffer.append(clazz.getName()).append(". ");
            buffer.append("This have a public empty contructor?");

            throw new RuntimeException(buffer.toString(), e);

        } catch (IllegalAccessException e) {

            StringBuffer buffer = new StringBuffer();
            buffer.append("Could not populate a bean from class ");
            buffer.append(clazz.getName()).append(". ");
            buffer.append("This class have a public contructor?");

            throw new RuntimeException(buffer.toString(), e);

        }

    }

    /**
     *
     * @param attributes
     * @param className
     *
     * @return
     *
     * @see BeanUtil#populate(Map, Class)
     */
    public static Object populate(Map attributes, String className) {

        Class clazz;

        try {

            clazz = Class.forName(className);

            return BeanUtil.populate(attributes, clazz);

        } catch (ClassNotFoundException ex) {

            throw new RuntimeException(ex);

        }

    }

    /**
     *
     * @param propertyName
     * @param propertyValue
     * @param beanTarget
     *
     * @return
     *
     * @see org.springframework.beans.BeanWrapper
     * @see BeanWrapperImpl
     * @see org.springframework.beans.BeanWrapper#setPropertyValue(
     *     java.lang.String, java.lang.Object)
     */
    public static Object setProperty(String propertyName, Object propertyValue, Object beanTarget) {

        new BeanWrapperImpl(beanTarget).setPropertyValue(propertyName, propertyValue);

        return beanTarget;

    }

    /**
     * @param propertyName The property name
     * @param beanSource Bean source for property
     *
     * @return Returns the property to beanSource
     *
     * @see org.springframework.beans.BeanWrapper
     * @see BeanWrapperImpl
     * @see org.springframework.beans.BeanWrapper#setPropertyValue(
     *     java.lang.String, java.lang.Object)
     */
    public static Object getProperty(String propertyName, Object beanSource) {

        return new BeanWrapperImpl(beanSource).getPropertyValue(propertyName);

    }

    /**
     *
     * @param bean
     * @return
     * @throws IntrospectionException
     */
    public static PropertyDescriptor[] getPropertyDescriptors(Object bean) throws IntrospectionException {

        BeanInfo info = Introspector.getBeanInfo(bean.getClass());
        PropertyDescriptor[] descriptors = info.getPropertyDescriptors();

        return descriptors;

    }

    /**
     * This method use reflection to navigate in object and get value from nested
     * properties based on the depth parameter. Use JavaBeans conventions to get
     * properties names and its values. So, if you have classes like the following:
     * <pre>
     * class PlainClass {
     *  private int num;
     *  //sets and gets
     * }
     * 
     * class Composite {
     *  private String name;
     *  private PlainClass plain;
     *  // sets and gets
     * }</pre>
     * 
     * The name of "num" attribute from PlainClass navigating from Composite is
     * "plain.num" and this will be the key in map. The depth parameter points out
     * as far as the method must retrieve properties. In the Composite class, name
     * have depth 1 and num have depth 2 and so on. depth parameter also avoid a 
     * StackOverFlowError if the bean have itself relationship.
     * 
     * @param source object from the properties are retrieved
     * @param depth as far as to retrieve properties.
     * @return
     * @throws IntrospectionException
     */
    public static Map<String, Object> getDeepAttributes(Object source, int depth) throws IntrospectionException {

        Map<String, Object> attributes = new HashMap<String, Object>();
        goingUnder(attributes, source, "", depth);

        return attributes;

    }

    /**
     *
     * @param source
     * @param classes
     *
     * @return Returns <code>true</code> if the source object is a instance from
     *     some class in classes.
     */
    private static boolean isAssignableFromAny(Object source, Class<Object>[] classes) {
        boolean result = false;
        Class sourceClass = source.getClass();
        for (int i = 0; i < classes.length; i++) {
            if (classes[i].isAssignableFrom(sourceClass)) {
                result = true;
                break;
            }
        }
        return result;
    }

    /**
     *
     * @param attributes
     * @param source
     * @param name
     * @param depth
     * @throws IntrospectionException
     */
    private static void goingUnder(Map<String, Object> attributes, Object source, String name, int depth)
            throws IntrospectionException {

        if (depth <= 0) {

            return;
        }

        PropertyDescriptor[] properties = getPropertyDescriptors(source);

        for (int i = 0; i < properties.length; i++) {

            String localName = properties[i].getName();

            Object value = getProperty(localName, source);

            if (value != null) {

                String tempName = dealWithAttributeName(name, localName);

                Class<? extends Object> vClass = value.getClass();

                if (!isAssignableFromAny(value, IS_NOT_FROM)) {

                    goingUnder(attributes, value, tempName, depth - 1);

                }

                if (!vClass.isAssignableFrom(Class.class)) {

                    attributes.put(tempName, value);

                }

            }

        }

    }

    /**
     * @param name
     * @param localName
     *
     * @return name for attribute
     */
    private static String dealWithAttributeName(String name, String localName) {

        String tempName = name;
        tempName = ((tempName != null) && !tempName.equals("")) ? tempName.concat(".").concat(localName)
                : localName;

        return tempName;

    }

    public static void setProperty(Object o, String propertyName, Object value) throws Exception {
        getWriteMethod(o.getClass(), propertyName).invoke(o.getClass(), value);
    }

    public static Object getProperty(Object o, String propertyName) throws Exception {
        return getReadMethod(o.getClass(), propertyName).invoke(o);
    }

    public static String[] getPropertyNames(Object o) throws IntrospectionException {
        PropertyDescriptor[] pds = Introspector.getBeanInfo(o.getClass()).getPropertyDescriptors();
        String[] propertyNames = new String[pds.length];

        for (int i = 0; i < pds.length; i++) {
            propertyNames[i] = pds[i].getName();
        }

        return propertyNames;
    }

    public static Class getPropertyType(Object o, String propertyName) throws Exception {
        PropertyDescriptor[] pds = Introspector.getBeanInfo(o.getClass()).getPropertyDescriptors();

        for (int i = 0; i < pds.length; i++) {
            if (pds[i].getName().equals(propertyName)) {
                return pds[i].getPropertyType();
            }
        }

        throw new Exception("Property not found.");
    }

    public static Method getReadMethod(Class<? extends Object> examineClass, String propertyName) throws Exception {
        PropertyDescriptor[] pds = Introspector.getBeanInfo(examineClass).getPropertyDescriptors();

        for (int i = 0; i < pds.length; i++) {
            if (pds[i].getName().equals(propertyName)) {
                return pds[i].getReadMethod();
            }
        }

        throw new Exception("Property not found.");
    }

    public static Method getWriteMethod(Class<? extends Object> examineClass, String propertyName)
            throws Exception {
        PropertyDescriptor[] pds = Introspector.getBeanInfo(examineClass).getPropertyDescriptors();

        for (int i = 0; i < pds.length; i++) {
            if (pds[i].getName().equals(propertyName)) {
                return pds[i].getWriteMethod();
            }
        }

        throw new Exception("Property not found.");
    }

    /** This method takes a JavaBean and generates a standard toString() type result for it.
     * @param o JavaBean object to stringinate
     * @return STRINGIATION! Stringingating the countryside. Stringinating all the peasants.
     */
    public static String beanToString(Object o) {
        StringBuffer result = new StringBuffer();

        if (o == null) {
            return "--- null";
        }

        result.append("--- begin");
        result.append(o.getClass().getName());
        result.append(" hash: ");
        result.append(o.hashCode());
        result.append("\r\n");

        try {
            PropertyDescriptor[] pds = Introspector.getBeanInfo(o.getClass()).getPropertyDescriptors();

            for (int pdi = 0; pdi < pds.length; pdi++) {
                try {
                    result.append(
                            "Property: " + pds[pdi].getName() + " Value: " + pds[pdi].getReadMethod().invoke(o));
                } catch (IllegalAccessException iae) {
                    result.append("Property: " + pds[pdi].getName() + " (Illegal Access to Value) ");
                } catch (InvocationTargetException iae) {
                    result.append(
                            "Property: " + pds[pdi].getName() + " (InvocationTargetException) " + iae.toString());
                } catch (Exception e) {
                    result.append("Property: " + pds[pdi].getName() + " (Other Exception )" + e.toString());
                }

                result.append("\r\n");
            }
        } catch (IntrospectionException ie) {
            result.append("Introspection Exception: " + ie.toString());
            result.append("\r\n");
        }

        result.append("--- end ");
        result.append(o.getClass().getName());
        result.append(" hash: ");
        result.append(o.hashCode());
        result.append("\n");

        return result.toString();
    }

    /** This method takes 2 JavaBeans of the same type and copies the properties of one bean to the other.
     * Any attempts that have an IllegalAccessException will be ignored. This will also NOT recurse into nested bean
     * results. References to existing beanage will be includes. Try using .clone() for that stuff.
     * @param from Source Bean
     * @param to Desitnation Bean
     */
    public static void copyBeanToBean(Object from, Object to)
            throws InvocationTargetException, IntrospectionException {
        PropertyDescriptor[] pds = Introspector.getBeanInfo(from.getClass()).getPropertyDescriptors();

        for (int i = 0; i < pds.length; i++) {
            try {
                if (pds[i].getName().equals("class")) {
                    continue;
                }
                Object[] value = { pds[i].getReadMethod().invoke(from) };
                if (pds[i].getWriteMethod() != null)
                    pds[i].getWriteMethod().invoke(to, value);
            } catch (IllegalAccessException iae) {
                //Im just going to ignore any properties I don't have access too.
            }
        }
    }

    /**
     * This method takes 2 JavaBeans of the same type and copies the properties of one bean to the other.
     * <br>
     * @param from
     * @param to
     * @param ignoreFields
     * @throws InvocationTargetException
     * @throws IntrospectionException
     */
    public static void copyBeanToBean(Object from, Object to, String[] ignoreFields)
            throws InvocationTargetException, IntrospectionException {
        if (from != null && to != null) {
            PropertyDescriptor[] pds = Introspector.getBeanInfo(from.getClass()).getPropertyDescriptors();
            for (int i = 0; i < pds.length; i++) {
                try {
                    boolean flag = false;
                    if (ignoreFields != null && ignoreFields.length > 0) {
                        for (int j = 0; j < ignoreFields.length; j++) {
                            if (pds[i].getName().equals(ignoreFields[j]))
                                flag = true;
                        }
                    }
                    if (pds[i].getName().equals("class") || flag == true)
                        continue;
                    Object[] value = { pds[i].getReadMethod().invoke(from) };
                    if (pds[i].getWriteMethod() != null)
                        pds[i].getWriteMethod().invoke(to, value);
                } catch (IllegalAccessException iae) {
                    iae.printStackTrace();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /** This method takes a JavaBean reset type.
     * @param o JavaBean object
     */
    public static void beanResetType(Object o) {
        try {
            PropertyDescriptor[] pds = Introspector.getBeanInfo(o.getClass()).getPropertyDescriptors();

            for (int pdi = 0; pdi < pds.length; pdi++) {
                String type = Common.get(pds[pdi].getPropertyType());
                if (type.equals("class java.lang.Integer")) {
                    pds[pdi].setValue(pds[pdi].getName(), Common.getInt(pds[pdi].getValue(pds[pdi].getName())));
                } else if (type.equals("class java.lang.Long")) {
                    pds[pdi].setValue(pds[pdi].getName(), Common.getLong(pds[pdi].getValue(pds[pdi].getName())));
                } else if (type.equals("class java.lang.Double")) {
                    pds[pdi].setValue(pds[pdi].getName(), Common.getNumeric(pds[pdi].getValue(pds[pdi].getName())));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static String getPropertyByBeanUtils(Object bean, String name) {
        try {
            return BeanUtils.getProperty(bean, name);
        } catch (Exception e) {
        }
        return "";
    }

}