wwutil.sys.ReflectUtil.java Source code

Java tutorial

Introduction

Here is the source code for wwutil.sys.ReflectUtil.java

Source

/******************************************************************************
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0.  If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/.
 * 
 * Software distributed under the License is distributed on an "AS IS" basis, 
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for 
 * the specific language governing rights and limitations under the License.
 *
 * The Original Code is: Jsoda
 * The Initial Developer of the Original Code is: William Wong (williamw520@gmail.com)
 * Portions created by William Wong are Copyright (C) 2012 William Wong, All Rights Reserved.
 *
 ******************************************************************************/

package wwutil.sys;

import java.util.*;
import java.lang.annotation.*;
import java.lang.reflect.*;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.lang.builder.ToStringStyle;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;

@SuppressWarnings("unchecked")
public class ReflectUtil {

    private ReflectUtil() {
        // disable
    }

    /** Return the list of fields declared at all level of class hierachy, include super private fields.
     */
    public static List<Field> getAllFields(Class clazz) {
        return getAllFields(clazz, new ArrayList<Field>());
    }

    private static List<Field> getAllFields(Class clazz, List<Field> list) {
        for (Field field : clazz.getDeclaredFields()) {
            // Filter out compiler synthesized fields and static fields.
            if (!field.isSynthetic() && !Modifier.isStatic(field.getModifiers()))
                list.add(field);
        }
        Class superClazz = clazz.getSuperclass();
        if (superClazz != null)
            getAllFields(superClazz, list);
        return list;
    }

    public static List<Method> getAllMethods(Class clazz) {
        return getAllMethods(clazz, new ArrayList<Method>());
    }

    public static List<Method> getAllMethods(Class clazz, List<Method> list) {
        for (Method method : clazz.getDeclaredMethods()) {
            if (!method.isSynthetic() && !Modifier.isStatic(method.getModifiers()))
                list.add(method);
        }
        Class superClazz = clazz.getSuperclass();
        if (superClazz != null)
            getAllMethods(superClazz, list);
        return list;
    }

    public static List<Class> getAllInterfaces(Class clazz) {
        return getAllInterfaces(clazz, new ArrayList<Class>());
    }

    private static List<Class> getAllInterfaces(Class clazz, List<Class> list) {
        for (Class intf : clazz.getInterfaces()) {
            list.add(intf);
        }
        Class superClazz = clazz.getSuperclass();
        if (superClazz != null)
            getAllInterfaces(superClazz, list);
        return list;
    }

    public static String[] getFieldNames(Class clazz) {
        List<Field> fields = getAllFields(clazz);
        String[] names = new String[fields.size()];

        for (int i = 0; i < fields.size(); i++) {
            try {
                names[i] = fields.get(i).getName();
            } catch (Exception ignored) {
            }
        }
        return names;
    }

    public static Map<String, Field> getFieldMap(Class clazz) {
        List<Field> fields = getAllFields(clazz);
        Map<String, Field> map = new HashMap<String, Field>();

        for (Field field : fields) {
            try {
                map.put(field.getName(), field);
            } catch (Exception ignored) {
            }
        }
        return map;
    }

    /** Get the parameterized type of a generic type GenericType<ParameterizedType>
     * For method, call method.getGenericParameterTypes() or method.getGenericReturnType() for the parameterizedType.
     * For field, call field.getGenericType() for the parameterizedType.
     * e.g.  List<String> field1 ==> getGenericParamType1(field11.getGenericType()) => String
     * Return null for none found.
     */
    public static Class getGenericParamType1(Type parameterizedType) {
        if (parameterizedType instanceof ParameterizedType) {
            ParameterizedType type = (ParameterizedType) parameterizedType;
            Type[] typeArguments = type.getActualTypeArguments();
            if (typeArguments.length > 0)
                return (Class) typeArguments[0];
        }
        return null;
    }

    public static Map<String, Object> objToMap(Object obj) {
        Map<String, Object> map = new HashMap<String, Object>();

        for (Field field : getAllFields(obj.getClass())) {
            try {
                map.put(field.getName(), field.get(obj));
            } catch (Exception ignored) {
            }
        }
        return map;
    }

    public static String mapToStr(Map<String, ?> map) {
        StringBuilder sb = new StringBuilder();
        boolean isFirst = true;

        sb.append("{");

        for (Map.Entry<String, ?> entry : map.entrySet()) {
            if (isFirst)
                isFirst = false;
            else
                sb.append(",");
            String valueStr = "" + entry.getValue();
            sb.append(entry.getKey()).append("=").append(valueStr);
        }

        sb.append("}");
        return sb.toString();
    }

    public static String dumpObj(Object obj) {
        if (obj == null)
            return "null";

        return ReflectionToStringBuilder.toString(obj, MyStyle.instance);
    }

    public static String dumpToStr(Object obj) {
        if (obj == null)
            return "null";
        Map<String, Object> map = objToMap(obj);
        return mapToStr(map);
    }

    public static String dumpToStr(List list, String delimiter) {
        if (list == null)
            return "";

        StringBuilder sb = new StringBuilder();

        for (Object obj : list) {
            if (sb.length() > 0)
                sb.append(delimiter);
            sb.append(obj);
        }
        return sb.toString();
    }

    public static Object run(Object obj, String methodName, Object[] params) throws Exception {
        Class[] prototypeParams = null;

        if (params != null) {
            prototypeParams = new Class[params.length];
            for (int i = 0; i < params.length; i++) {
                prototypeParams[i] = params[i].getClass();
            }
        }

        Method method = obj.getClass().getMethod(methodName, prototypeParams);
        if (method == null)
            return null;
        return method.invoke(obj, params);
    }

    public static Object run(Object obj, String methodName) throws Exception {
        return run(obj, methodName, null);
    }

    public static Object run(Object obj, String methodName, Object param1) throws Exception {
        return run(obj, methodName, new Object[] { param1 });
    }

    public static Object run(Object obj, String methodName, Object param1, Object param2) throws Exception {
        return run(obj, methodName, new Object[] { param1, param2 });
    }

    public static Object run(Object obj, String methodName, Object param1, Object param2, Object param3)
            throws Exception {
        return run(obj, methodName, new Object[] { param1, param2, param3 });
    }

    public static Object getFieldValue(Object entity, String fieldName) throws Exception {
        Field field = entity.getClass().getField(fieldName);
        if (field != null)
            return field.get(entity);
        return null;
    }

    /** Convert str value to Object */
    public static Object strToObj(String valueStr, Class valueType) {
        return ConvertUtils.convert(valueStr, valueType);
    }

    /** Initialize the fields of an object with the value object
     *  Use with MapUtil.toMap() for initializing an object.
     *  e.g. setFieldStrs(obj, MapUtil.toMap("field1", 123, "field2", 234, "myfield3", new Date() ));
     */
    public static <T> T initObj(T obj, Map<String, Object> fieldValues) throws Exception {
        if (obj != null && fieldValues != null) {
            for (Field field : getAllFields(obj.getClass())) {
                field.set(obj, fieldValues.get(field.getName()));
            }
        }
        return obj;
    }

    /** Initialize the fields of an object with the value object, converted from string.
     *  Use with MapUtil.toMap() for initializing an object.
     */
    public static <T> T initObjStrs(T obj, Map<String, String> fieldStrValues) throws Exception {
        if (obj != null && fieldStrValues != null) {
            for (Field field : getAllFields(obj.getClass())) {
                Object value = ConvertUtils.convert(fieldStrValues.get(field.getName()), field.getType());
                field.set(obj, value);
            }
        }
        return obj;
    }

    public static boolean hasAnnotation(Class objClass, Class annClass) {
        return (objClass.getAnnotation(annClass) != null);
    }

    public static boolean hasAnnotation(Field field, Class annClass) {
        return (field.getAnnotation(annClass) != null);
    }

    public static boolean hasAnnotation(Method method, Class annClass) {
        return (method.getAnnotation(annClass) != null);
    }

    public static String getAnnoValue(Annotation annObj, String valueMethod, String defaultValue) {
        try {
            if (annObj != null)
                return (String) ReflectUtil.run(annObj, valueMethod);
        } catch (Exception ignored) {
        }
        return defaultValue;
    }

    public static int getAnnoValue(Annotation annObj, String valueMethod, int defaultValue) {
        try {
            if (annObj != null)
                return (int) (Integer) ReflectUtil.run(annObj, valueMethod);
        } catch (Exception ignored) {
        }
        return defaultValue;
    }

    public static char getAnnoValue(Annotation annObj, String valueMethod, char defaultValue) {
        try {
            if (annObj != null)
                return (char) (Character) ReflectUtil.run(annObj, valueMethod);
        } catch (Exception ignored) {
        }
        return defaultValue;
    }

    public static boolean getAnnoValue(Annotation annObj, String valueMethod, boolean defaultValue) {
        try {
            if (annObj != null)
                return (boolean) (Boolean) ReflectUtil.run(annObj, valueMethod);
        } catch (Exception ignored) {
        }
        return defaultValue;
    }

    public static Object getAnnoValue(Annotation annObj, String valueMethod, Object defaultValue) {
        try {
            if (annObj != null)
                return ReflectUtil.run(annObj, valueMethod);
        } catch (Exception ignored) {
        }
        return defaultValue;
    }

    /** Get the value of a class annotation via its method.
     * e.g.   getAnnotationValue(clazz, EPlacemark.class, "latitude", String.class, (String)null);
     */
    public static <T> T getAnnotationValue(Class objClass, Class annClass, String valueMethod, Class<T> valueClass,
            T defaultValue) throws Exception {
        Object annObj = objClass.getAnnotation(annClass);
        if (annObj != null)
            return (T) ReflectUtil.run(annObj, valueMethod);
        else
            return defaultValue;
    }

    /** Get the value of a class annotation via its method.  Use defaultValue for all exceptions.
     * e.g.   getAnnotationValueEx(clazz, EPlacemark.class, "latitude", Double.class, (Double)0.0);
     */
    public static <T> T getAnnotationValueEx(Class objClass, Class annClass, String valueMethod,
            Class<T> valueClass, T defaultValue) {
        try {
            Object annObj = objClass.getAnnotation(annClass);
            if (annObj != null)
                return (T) ReflectUtil.run(annObj, valueMethod);
        } catch (Exception ignored) {
        }
        return defaultValue;
    }

    /** Get the String value of a class annotation via its method.  Return default if value is "" or null.
     * e.g.   getAnnotationValue(clazz, Table.class, "name", "abc");
     */
    public static String getAnnotationValue(Class objClass, Class annClass, String valueMethod,
            String defaultValue) {
        String value = getAnnotationValueEx(objClass, annClass, valueMethod, String.class, defaultValue);
        return (value == null || value.length() == 0) ? defaultValue : value;
    }

    /** Get the value of a field annotation via its method.
     * e.g.   getAnnotationValue(field, Column.class, "name", String.class, (String)null);
     */
    public static <T> T getAnnotationValue(Field field, Class annClass, String valueMethod, Class<T> valueClass,
            T defaultValue) throws Exception {
        Object annObj = field.getAnnotation(annClass);
        if (annObj != null)
            return (T) ReflectUtil.run(annObj, valueMethod);
        else
            return defaultValue;
    }

    /** Get the value of a field annotation via its method.  Use defaultValue for all exceptions.
     * e.g.   getAnnotationValue(field, Column.class, "name", String.class, (String)null);
     */
    public static <T> T getAnnotationValueEx(Field field, Class annClass, String valueMethod, Class<T> valueClass,
            T defaultValue) {
        try {
            Object annObj = field.getAnnotation(annClass);
            if (annObj != null)
                return (T) ReflectUtil.run(annObj, valueMethod);
        } catch (Exception ignored) {
        }
        return defaultValue;
    }

    /** Get the String value of a field annotation via its method.  Return default if value is "" or null.
     * e.g.   getAnnotationValue(field, Column.class, "name", "abc");
     */
    public static String getAnnotationValue(Field field, Class annClass, String valueMethod, String defaultValue) {
        String value = getAnnotationValueEx(field, annClass, valueMethod, String.class, defaultValue);
        return (value == null || value.length() == 0) ? defaultValue : value;
    }

    /** Find the field of the class having the annotation defined on it.
     */
    public static Field findAnnotatedField(Class clazz, Class fieldAnnClass) {
        for (Field field : clazz.getFields()) {
            Object annObj = field.getAnnotation(fieldAnnClass);
            if (annObj != null)
                return field;
        }
        return null;
    }

    public static void incrementField(Object dataObj, Field field, int incrementAmount) throws Exception {
        if (field.getType() == Integer.class || field.getType() == int.class) {
            Integer value = (Integer) field.get(dataObj);
            value = value == null ? new Integer(1) : new Integer(value.intValue() + 1);
            field.set(dataObj, value);
        } else if (field.getType() == Long.class || field.getType() == long.class) {
            Long value = (Long) field.get(dataObj);
            value = value == null ? new Long(1) : new Long(value.longValue() + 1);
            field.set(dataObj, value);
        } else {
            throw new IllegalArgumentException("Cannot increment non-integer field " + field);
        }
    }

    static class MyStyle extends ToStringStyle {
        final static ToStringStyle instance = new MyStyle();

        public MyStyle() {
            setArrayContentDetail(true);
            setUseShortClassName(true);
            setUseClassName(false);
            setUseIdentityHashCode(false);
            setFieldSeparator(", ");
        }

        @Override
        public void appendDetail(StringBuffer buffer, String fieldName, Object value) {
            if (!value.getClass().getName().startsWith("java")) {
                buffer.append(ReflectionToStringBuilder.toString(value, instance));
            } else {
                super.appendDetail(buffer, fieldName, value);
            }
        }

        @Override
        public void appendDetail(StringBuffer buffer, String fieldName, Collection value) {
            appendDetail(buffer, fieldName, value.toArray());
        }

    }

}