Package com.philip.journal.common

Source Code of com.philip.journal.common.BeanUtils

/**
* @Date: Apr 22, 2010 1:07:12 PM
*/
package com.philip.journal.common;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import com.philip.journal.core.Messages.Error;
import com.philip.journal.core.exception.JournalException;

/**
* Utility class for common bean/Class reflection functionalities. Helper bean
* class for bean manipulation.
*
* @author cry30
*/
public final class BeanUtils {

    /** Class logger. */
    private static final Logger LOGGER = Logger.getLogger(BeanUtils.class);

    /** property first letter start. */
    private static final int IDX_FL_START = 3;
    /** property first letter end. */
    private static final int IDX_FL_END = 4;

    /** Cache to store the array of properties for a given bean type. */
    private static Map<String, String[]> beanPropertyCache;

    /** Cache to store the property type of a bean property. */
    private static Map<String, Class<?>> beanPropTypeCache;

    /** Java wrapper to primitive type mapping. */
    private static Map<Class<?>, Class<?>> primitiveTypeMap;

    static {
        beanPropertyCache = new HashMap<String, String[]>();
        beanPropTypeCache = new HashMap<String, Class<?>>();
        primitiveTypeMap = new HashMap<Class<?>, Class<?>>();
        primitiveTypeMap.put(Integer.class, Integer.TYPE);
        primitiveTypeMap.put(Boolean.class, Boolean.TYPE);
        primitiveTypeMap.put(Long.class, Long.TYPE);
        primitiveTypeMap.put(Character.class, Character.TYPE);
        primitiveTypeMap.put(Short.class, Short.TYPE);
        primitiveTypeMap.put(Double.class, Double.TYPE);
        primitiveTypeMap.put(Float.class, Float.TYPE);
        primitiveTypeMap.put(Byte.class, Byte.TYPE);
    }

    /** Singleton class variable. */
    private static final BeanUtils INSTANCE = new BeanUtils();

    /** Prevent extension of this class. */
    private BeanUtils() {}

    /**
     * Singleton factory method.
     *
     * @return Singleton instance of this class.
     */
    public static BeanUtils getInstance()
    {
        return INSTANCE;
    }

    /**
     * Produces the primitive type given a wrapper Class otherwise the original
     * Class is returned.
     *
     * @param klass The Wrapper classes to derive the primitive type from.
     * @return primitive type equivalent for the given type. Will return the
     *         save Class if no primitive type is found.
     * @exception IllegalArgumentException when the parameter klass is null.
     */
    public static Class<?> getPrimitive(final Class<?> klass)
    {
        if (klass == null) {
            throw new IllegalArgumentException(Error.IAE_NULL);
        }

        final Class<?> retval = primitiveTypeMap.get(klass);
        return retval == null ? klass : retval;
    }

    /**
     * Returns the get accessor method name of the given property name.
     *
     * @param property property name to derive getter method from.
     * @return accessor method name. null if the property parameter is null or
     *         and empty String.
     * @exception IllegalArgumentException when the parameter property is null
     *                or is zero-length.
     */
    public static String getGetterMethodName(final String property)
    {
        if (property == null || property.length() < 1) {
            throw new IllegalArgumentException(Error.IAE_NULLOREMPTY);
        }

        final StringBuilder retval = new StringBuilder("get"
                + property.substring(0, 1).toUpperCase());
        if (property.length() > 1) {
            retval.append(property.substring(1));
        }
        return retval.toString();
    }

    /**
     * Returns the set accessor method name of the given property name.
     *
     * @param property property name to derive setter method from.
     * @return accessor method name. null if the property parameter is null or
     *         and empty String.
     * @exception IllegalArgumentException when the parameter property is null
     *                or is zero-length.
     */
    public static String getSetterMethodName(final String property)
    {
        if (property == null || property.length() < 1) {
            throw new IllegalArgumentException(Error.IAE_NULLOREMPTY);
        }
        final StringBuilder retval = new StringBuilder("set"
                + property.substring(0, 1).toUpperCase());
        if (property.length() > 1) {
            retval.append(property.substring(1));
        }
        return retval.toString();
    }

    /**
     * Returns all properties of a bean available via accessor methods.
     *
     * @param bean - the bean whose properties are to be derived.
     *
     * @return - array of bean fields/properties
     *
     * @throws IllegalArgumentException when the bean is null;
     */
    public static String[] getProperties(final Object bean)
    {
        return getProperties(bean, new String[0]);
    }

    /**
     * TODO: Update Unit Test cases for exclusion of static fields. Returns all
     * properties of a bean available via accessor methods. Will disregard
     * static properties.
     *
     * @param bean - the bean whose properties are to be derived.
     * @param exemptParam - array of properties not will be excluded from list.
     *
     * @return - array of bean fields/properties
     *
     * @throws IllegalArgumentException when the bean parameter is null;
     */
    public static String[] getProperties(final Object bean,
            final String[] exemptParam)
    {
        if (bean == null) {
            throw new IllegalArgumentException(Error.IAE_NULL);
        }

        final String[] exemption = exemptParam == null ? new String[0]
                : exemptParam;
        String[] retval;
        final String exemptionId = Arrays.asList(exemption).toString();

        retval = beanPropertyCache.get(bean.getClass() + exemptionId);
        if (retval == null) {
            final List<String> exemptList = new ArrayList<String>(
                    Arrays.asList(exemption));
            exemptList.add("class");

            final List<String> fields = new ArrayList<String>();
            for (final Field nextField : bean.getClass().getDeclaredFields()) {
                final String property = nextField.getName();
                if (exemptList.contains(property)
                        || java.lang.reflect.Modifier.isStatic(nextField
                                .getModifiers())) {
                    continue;
                }
                fields.add(property);
            }
            retval = fields.toArray(new String[fields.size()]);
            beanPropertyCache.put(bean.getClass() + exemptionId, retval);
        }
        return retval;
    }

    /**
     * Extracts property name from a given getter Method.
     *
     * @param accessorMethod accessor method name.
     *
     * @return derived property name.
     * @exception IllegalArgumentException when the accessorMethod parameter is
     *                null.
     */
    public static String getPropertyName(final Method accessorMethod)
    {
        if (accessorMethod == null) {
            throw new IllegalArgumentException(Error.IAE_NULL);
        }
        return BeanUtils.getPropertyName(accessorMethod.getName());
    }

    /**
     * Converts the accessor method name into bean property name.
     *
     * @param accessorMethName accessor method name.
     * @return property bean property name.
     *
     * @exception IllegalArgumentException when the passed parameter is null or
     *                when the passed parameter is not a valid accessor method
     *                name.
     */
    public static String getPropertyName(final String accessorMethName)
    {
        if (accessorMethName == null) {
            throw new IllegalArgumentException(Error.IAE_GENERIC);
        }

        final int length = accessorMethName.trim().length();

        if (length < IDX_FL_END) {
            throw new IllegalArgumentException(Error.IAE_GENERIC);
        }

        if (!(accessorMethName.startsWith("get") || accessorMethName
                .startsWith("set"))) {
            throw new IllegalArgumentException(Error.IAE_GENERIC + " "
                    + accessorMethName);
        }

        final StringBuilder propName = new StringBuilder(accessorMethName
                .substring(IDX_FL_START, IDX_FL_END).toLowerCase());
        if (length > IDX_FL_END) {
            propName.append(accessorMethName.substring(IDX_FL_END));
        }
        return propName.toString();
    }

    /**
     * Retrieves a property value of the bean. Note: This will work only when a
     * public getter method is available for the property.
     *
     * @param bean instance where we want to get the property value from.
     * @param property property name of the bean we want to get the property
     *            value from.
     * @return null when the property could not be retrieved.
     * @throws IllegalArgumentException when the bean is null or the property is
     *             not valid;
     */
    public static Object getProperty(final Object bean, final String property)
    {
        if (bean == null) {
            throw new IllegalArgumentException(Error.IAE_NULL);
        }
        final String getterMethod = getGetterMethodName(property);

        try {
            return getDeclaredOrInheritedMethod(bean, getterMethod,
                    new Class[0]).invoke(bean, new Object[0]);
            //return bean.getClass().getMethod(getterMethod, new Class[0]).invoke(bean, new Object[0]);
        } catch (final NoSuchMethodException e) {
            throw new IllegalArgumentException(Error.IAE_INVALID_PROP + " "
                    + property); // NOPMD by r39
        } catch (final InvocationTargetException e) {
            throw new RuntimeException(e.getCause()); // NOPMD by r39
        } catch (final Exception e) {
            throw new JournalException(Error.GEN_ERROR, e); // NOPMD by r39
        }
    }

    /**
     * Retrieves the type of the bean property.
     *
     * @param bean bean instance whose property type we are getting.
     * @param property bean property whose type we are getting.
     * @return null when the property cannot be retrieved.
     * @exception IllegalArgumentException when the bean or the property
     *                parameter is null; If any of the following is true:
     *                <ul>
     *                <li>when the object passed is null.
     *                <li>when the property passed is null.
     *                <li>when the property passed is not found.
     *                </ul>
     */
    public static Class<?> getPropertyType(final Object bean,
            final String property)
    {
        if (bean == null || property == null) {
            throw new IllegalArgumentException(Error.IAE_NULLOREMPTY);
        }
        final String key = bean.getClass().getName() + "." + property;
        Class<?> type = beanPropTypeCache.get(key);
        if (type == null) {
            try {
                type = bean.getClass().getDeclaredField(property).getType();
            } catch (final NoSuchFieldException e) {
                throw new IllegalArgumentException(Error.IAE_INVALID_PROP
                        + property); // NOPMD
            }
        }
        beanPropTypeCache.put(key, type);
        return type;
    }

    /**
     * Helper method for calling method on a bean. All Exceptions are ignored
     * except for NoSuchMethodException wherein IllegalArgumentException is
     * thrown in its place. For primitive typed return, the corresponding
     * wrapper method should be called on return Object.
     *
     * Note: Use this method with extreme caution.
     *
     * @param object object instance to invoke the method from.
     * @param method method name.
     * @param types method parameter types.
     * @param args argument passed to the bean via reflection
     * @return null if any exception is encountered.
     * @exception IllegalArgumentException If any of the following is true:
     *                <ul>
     *                <li>when the object passed is null.
     *                <li>when the method parameter passed is null.
     *                <li>when the method parameter passed is not found.
     *                </ul>
     */
    public static Object invokeMethodSilent(final Object object,
            final String method, final Class<?>[] types, final Object[] args)
    {
        if (object == null || method == null) {
            throw new IllegalArgumentException(Error.IAE_GENERIC);
        }

        Object retval = null;
        try {
            retval = invokeMethod(object, method, types, args);
        } catch (final InvocationTargetException ignore) {
            LOGGER.warn(ignore.getMessage(), ignore);
        }
        return retval;
    }

    /**
     * Helper method for calling method on a bean. Exception during target
     * invocation is thrown back to the client code. For primitive typed return,
     * the corresponding wrapper method should be called on return Object.
     *
     * @param object object instance to invoke the method from.
     * @param methodName method name.
     * @param types method parameter types.
     * @param args argument passed to the bean via reflection
     * @return null if any exception is encountered other than the
     *         InvocationTargetException
     * @exception IllegalArgumentException If any of the following is true:
     *                <ul>
     *                <li>when the object passed is null.
     *                <li>when the method parameter passed is null.
     *                <li>when the method parameter passed is not found.
     *                </ul>
     * @throws InvocationTargetException - when an exception is thrown inside
     *             the target object.
     */
    public static Object invokeMethod(final Object object,
            final String methodName, final Class<?>[] types, final Object[] args)
            throws InvocationTargetException
    {
        if (object == null || methodName == null
                || "".equals(methodName.trim())) {
            throw new IllegalArgumentException(Error.IAE_NULLOREMPTY);
        }

        Object retval = null;
        try {
            final Method method = getDeclaredOrInheritedMethod(object,
                    methodName, types);
            retval = method.invoke(object, args);
        } catch (final IllegalArgumentException e) { // NOPMD by r39 on 3/30/11 10:17 AM
            LOGGER.debug(e.getMessage(), e);
        } catch (final SecurityException e) { // NOPMD by r39 on 3/30/11 10:17 AM
            LOGGER.debug(e.getMessage(), e);
        } catch (final IllegalAccessException e) { // NOPMD by r39 on 3/30/11 10:17 AM
            LOGGER.debug(e.getMessage(), e);
        } catch (final NoSuchMethodException e) {
            throw new IllegalArgumentException(Error.IAE_INV_METHOD
                    + methodName); // NOPMD by r39
        }
        return retval;
    }

    /**
     * Will get the accessible method from the class either declared or
     * inherited.
     *
     * @param object - object instance containing the method.
     * @param methName - method name.
     * @param types - argument type for the method.
     * @return the accessible method. null if no accessible method with the
     *         correct signature is found.
     * @throws SecurityException When the object exist but the calling class do
     *             not have access to the method.
     * @throws NoSuchMethodException when the method was not found in the passed
     *             object instance.
     */
    static Method getDeclaredOrInheritedMethod(final Object object,
            final String methName, final Class<?>[] types)
            throws NoSuchMethodException
    {
        Method retval = null;
        try {
            retval = object.getClass().getMethod(methName, types);
        } catch (final NoSuchMethodException nsm) {
            retval = object.getClass().getDeclaredMethod(methName, types);
        }
        return retval;
    }

    /**
     * Converts a java bean object to a name value pair Map.
     *
     * @param javaBean the java bean object to convert to map.
     * @param excludedProps optional array of properties not to be included in
     *            the resulting Map.
     * @return null when the javaBean passed is null.
     */
    public static Map<String, Object> convertToMap(final Object javaBean,
            final String[] excludedProps)
    {
        Map<String, Object> retval = null;
        if (javaBean != null) {
            retval = new HashMap<String, Object>();
            final String[] properties = getProperties(javaBean, excludedProps);
            for (final String property : properties) {
                retval.put(property, getProperty(javaBean, property));
            }
        }
        return retval;
    }

}
TOP

Related Classes of com.philip.journal.common.BeanUtils

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.