Invokes a getter for a property, or gets the matching field, no matter what. - Java Reflection

Java examples for Reflection:Getter

Description

Invokes a getter for a property, or gets the matching field, no matter what.

Demo Code

/*//ww  w  .  j a  v  a  2 s. c om
 * Copyright (c) 2012 Data Harmonisation Panel
 * 
 * All rights reserved. This program and the accompanying materials are made
 * available under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the License,
 * or (at your option) any later version.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this distribution. If not, see <http://www.gnu.org/licenses/>.
 * 
 * Contributors:
 *     HUMBOLDT EU Integrated Project #030962
 *     Data Harmonisation Panel <http://www.dhpanel.eu>
 */
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.JarURLConnection;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.zip.ZipException;

public class Main{
    /**
     * Invokes a getter for a property, or gets the matching field, no matter
     * what.
     * 
     * @param bean the object to invoke the getter on
     * @param propertyName the name of the property to retrieve
     * @param valueClass the class of the property or field
     * @return the property's value
     * @throws IllegalArgumentException if the argument's type is invalid
     * @throws InvocationTargetException if the getter throws an exception
     * @throws IllegalStateException is the field could be found or accessed
     */
    @SuppressWarnings("unchecked")
    public static <T> T getDeepPropertyOrField(Object bean,
            String propertyName, Class<T> valueClass)
            throws IllegalArgumentException, InvocationTargetException {
        try {
            return ReflectionHelper.getDeepProperty(bean, propertyName);
        } catch (NoSuchMethodException e) {/* ignore */
        } catch (IllegalAccessException e) {/* ignore */
        }

        // there is no getter for the property. try to get the field directly
        Field f = findDeepField(bean.getClass(), propertyName, valueClass);
        if (f == null) {
            throw new IllegalStateException("Could not find "
                    + "field for property " + propertyName + " in class "
                    + bean.getClass().getCanonicalName());
        }

        boolean access = f.isAccessible();
        f.setAccessible(true);
        try {
            return (T) f.get(bean);
        } catch (Exception e) {
            throw new IllegalStateException("Could not get "
                    + "field for property " + propertyName + "in class "
                    + bean.getClass().getCanonicalName(), e);
        } finally {
            f.setAccessible(access);
        }
    }
    /**
     * Invokes a getter for a property, no matter if the getter is visible or
     * hidden or if it is declared in the given class or in a superclass or
     * implemented interface.
     * 
     * @param <T> the result type
     * @param bean the object to invoke the getter on
     * @param propertyName the name of the property to retrieve
     * @return the property's value
     * @throws IllegalArgumentException if the argument's type is invalid
     * @throws IllegalAccessException if the setter is not accessible
     * @throws InvocationTargetException if the setter throws an exception
     * @throws NoSuchMethodException if there is no setter for this property
     */
    public static <T> T getDeepProperty(Object bean, String propertyName)
            throws IllegalArgumentException, IllegalAccessException,
            InvocationTargetException, NoSuchMethodException {
        Method getter = findDeepGetter(bean.getClass(), propertyName, null);
        if (getter == null) {
            throw new NoSuchMethodException("There is " + //$NON-NLS-1$
                    "no getter for property " + propertyName); //$NON-NLS-1$
        }

        return ReflectionHelper.<T> invokeGetter(bean, getter);
    }
    /**
     * Returns a field for a given property, no matter if the field is visible
     * or hidden or if it is declared in the given class or in a superclass.
     * 
     * @param c the class which would contain the field
     * @param property the property
     * @param propertyType the property's type
     * @return the field or null if there is no field for this property
     */
    public static Field findDeepField(Class<?> c, String property,
            Class<?> propertyType) {
        if (c == Object.class || c == null) {
            return null;
        }

        Field result = null;
        // search visible and hidden fields in this class
        Field[] fields = c.getDeclaredFields();
        for (Field f : fields) {
            String fn = f.getName();
            if (fn.charAt(0) == '_') {
                // handle code style
                fn = fn.substring(1);
            }
            if (fn.equals(property)
                    && (propertyType == null || f.getType()
                            .isAssignableFrom(propertyType))) {
                result = f;
                break;
            }
        }

        // search superclass
        if (result == null) {
            result = findDeepField(c.getSuperclass(), property,
                    propertyType);
        }

        return result;
    }
    /**
     * Returns a getter method for a given property, no matter if the method is
     * visible or hidden or if it is declared in the given class or in a
     * superclass or implemented interface.
     * 
     * @param c the class which would contain the getter method
     * @param property the property
     * @param propertyType the property's type (can be null if the type does not
     *            matter)
     * @return the getter or null if there is no getter for this property
     */
    public static Method findDeepGetter(Class<?> c, String property,
            Class<?> propertyType) {
        if (c == Object.class || c == null) {
            return null;
        }

        char[] propertyNameArr = property.toCharArray();
        propertyNameArr[0] = Character.toUpperCase(propertyNameArr[0]);
        String getterName = "get" + new String(propertyNameArr); //$NON-NLS-1$

        Method result = null;
        // search visible and hidden methods in this class
        Method[] methods = c.getDeclaredMethods();
        for (Method m : methods) {
            if (m.getName().equals(getterName)
                    && m.getParameterTypes().length == 0
                    && (propertyType == null || propertyType
                            .isAssignableFrom(m.getReturnType()))) {
                result = m;
                break;
            }
        }

        // search superclass and interfaces
        if (result == null) {
            result = findDeepGetter(c.getSuperclass(), property,
                    propertyType);
            if (result == null) {
                Class<?>[] interfaces = c.getInterfaces();
                for (Class<?> inter : interfaces) {
                    result = findDeepGetter(inter, property, propertyType);
                    if (result != null) {
                        break;
                    }
                }
            }
        }

        return result;
    }
    /**
     * Invokes a getter method on a given bean
     * 
     * @param <T> the result type
     * @param bean the object to invoke the getter on
     * @param getter the getter method
     * @return the property's value
     * @throws IllegalArgumentException if the argument's type is invalid
     * @throws IllegalAccessException if the getter is not accessible
     * @throws InvocationTargetException if the getter throws an exception
     */
    @SuppressWarnings("unchecked")
    private static <T> T invokeGetter(Object bean, Method getter)
            throws IllegalArgumentException, IllegalAccessException,
            InvocationTargetException {
        boolean accessible = getter.isAccessible();
        getter.setAccessible(true);
        T result = null;
        try {
            result = (T) getter.invoke(bean);
        } finally {
            getter.setAccessible(accessible);
        }

        return result;
    }
}

Related Tutorials