All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.nuiton.util.beans.BeanUtil Maven / Gradle / Ivy

There is a newer version: 3.1
Show newest version
/*
 * #%L
 * Nuiton Utils
 * %%
 * Copyright (C) 2004 - 2010 CodeLutin
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it 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.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public 
 * License along with this program.  If not, see
 * .
 * #L%
 */
package org.nuiton.util.beans;

import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import org.apache.commons.beanutils.MethodUtils;
import org.apache.commons.beanutils.PropertyUtils;

import java.beans.PropertyChangeListener;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

/**
 * Usefull methods around the {@link PropertyChangeListener}.
 *
 * @author Tony Chemit - [email protected]
 * @since 1.4.1
 */
public class BeanUtil {

    public static final String ADD_PROPERTY_CHANGE_LISTENER =
            "addPropertyChangeListener";

    public static final String REMOVE_PROPERTY_CHANGE_LISTENER =
            "removePropertyChangeListener";

    protected BeanUtil() {
        // no instance
    }

    /**
     * Is a property is readable ?
     *
     * @since 2.5.11
     */
    public static final Predicate IS_READ_DESCRIPTOR = new Predicate() {
        @Override
        public boolean apply(PropertyDescriptor input) {
            return input.getReadMethod() != null;
        }
    };

    /**
     * Is a property is writable ?
     *
     * @since 2.5.11
     */
    public static final Predicate IS_WRITE_DESCRIPTOR = new Predicate() {
        @Override
        public boolean apply(PropertyDescriptor input) {
            return input.getWriteMethod() != null;
        }
    };

    /**
     * Is a property is readable and writable ?
     *
     * @since 2.5.11
     */
    public static final Predicate IS_READ_AND_WRITE_DESCRIPTOR = Predicates.and(
            IS_READ_DESCRIPTOR,
            IS_WRITE_DESCRIPTOR
    );

    /**
     * Test if the given type is JavaBean compiliant, says that it has two
     * public methods :
     * 
    *
  • {@code addPropertyChangeListener}
  • *
  • {@code removePropertyChangeListener}
  • *
* * @param type type to test * @return {@code true} if type is Javabean compiliant, {@code false} * otherwise * @since 2.0 */ public static boolean isJavaBeanCompiliant(Class type) { try { type.getMethod(ADD_PROPERTY_CHANGE_LISTENER, PropertyChangeListener.class); } catch (NoSuchMethodException e) { // no add method return false; } try { type.getMethod(REMOVE_PROPERTY_CHANGE_LISTENER, PropertyChangeListener.class); } catch (NoSuchMethodException e) { // no add method return false; } return true; } /** * Add the given {@code listener} to the given {@code bean} using the * normalized method named {@code addPropertyChangeListener}. * * @param listener the listener to add * @param bean the bean on which the listener is added * @throws InvocationTargetException if could not invoke the method * {@code addPropertyChangeListener} * @throws NoSuchMethodException if method * {@code addPropertyChangeListener} * does not exist on given bean * @throws IllegalAccessException if an illegal access occurs when * invoking the method * {@code addPropertyChangeListener} */ public static void addPropertyChangeListener(PropertyChangeListener listener, Object bean) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException { MethodUtils.invokeExactMethod(bean, ADD_PROPERTY_CHANGE_LISTENER, new Object[]{listener}, new Class[]{PropertyChangeListener.class} ); } /** * Remove the given {@code listener} from the given {@code bean} using the * normalized method named {@code removePropertyChangeListener}. * * @param listener the listener to remove * @param bean the bean on which the listener is removed * @throws InvocationTargetException if could not invoke the method * {@code removePropertyChangeListener} * @throws NoSuchMethodException if method * {@code removePropertyChangeListener} * does not exist on given bean * @throws IllegalAccessException if an illegal access occurs when * invoking the method * {@code removePropertyChangeListener} */ public static void removePropertyChangeListener(PropertyChangeListener listener, Object bean) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException { MethodUtils.invokeExactMethod(bean, REMOVE_PROPERTY_CHANGE_LISTENER, new Object[]{listener}, new Class[]{PropertyChangeListener.class} ); } /** * Obtains all readable properties from a given type. * * @param beanType the type to seek * @return the set of all readable properties for the given type * @since 2.0 */ public static Set getReadableProperties(Class beanType) { Set> exploredTypes = new HashSet>(); Set result = new HashSet(); // get properties for the class getReadableProperties(beanType, result, exploredTypes); // the special getClass will never be a JavaBean property... result.remove("class"); return result; } /** * Obtains all writeable properties from a given type. * * @param beanType the type to seek * @return the set of all writeable properties for the given type * @since 2.0 */ public static Set getWriteableProperties(Class beanType) { Set> exploredTypes = new HashSet>(); Set result = new HashSet(); // get properties for the class getWriteableProperties(beanType, result, exploredTypes); return result; } /** * Obtains all readable properties from a given type. * * @param beanType the type to seek * @param propertyName FIXME * @return the set of all readable properties for the given type * @since 2.0 */ public static boolean isNestedReadableProperty(Class beanType, String propertyName) { boolean result = propertyName.contains("."); if (result) { int dotIndex = propertyName.indexOf("."); String firstLevelProperty = propertyName.substring(0, dotIndex); Class nestedType = getReadableType(beanType, firstLevelProperty); if (nestedType == null) { result = false; } else { String rest = propertyName.substring(dotIndex + 1); result = isNestedReadableProperty(nestedType, rest); } } else { // not a nested property check it directly Class nestedType = getReadableType(beanType, propertyName); result = nestedType != null; } return result; } public static Class getReadableType(Class beanType, String propertyName) { PropertyDescriptor[] descriptors = PropertyUtils.getPropertyDescriptors(beanType); Class result = null; for (PropertyDescriptor descriptor : descriptors) { String name = descriptor.getName(); if (descriptor.getReadMethod() != null && propertyName.equals(name)) { result = descriptor.getReadMethod().getReturnType(); break; } } if (result == null) { // try with super-class if (beanType.getSuperclass() != null) { // get properties fro super-class result = getReadableType(beanType.getSuperclass(), propertyName); } } if (result == null) { // try it with interfaces Class[] interfaces = beanType.getInterfaces(); for (Class anInterface : interfaces) { result = getReadableType(anInterface, propertyName); if (result != null) { // found it break; } } } return result; } /** * Scan the given type and obtain {@link PropertyDescriptor} * given the (optional) predicate (except the {@code class} property of * any java object). * * Note: If no predicate is given, then all descriptors * are returned. * * @param beanType the bean type to scan * @param predicate the optional predicate to keep descriptor * @return set of all matching descriptors * @since 2.6.11 */ public static Set getDescriptors(Class beanType, Predicate predicate) { if (predicate == null) { predicate = Predicates.alwaysTrue(); } Set> exploredTypes = new HashSet>(); Map result = new TreeMap(); getDescriptors(beanType, predicate, result, exploredTypes); // the special getClass will never be a JavaBean property... result.remove("class"); return new HashSet(result.values()); } public static Method getMutator(Object bean, String property) { Method mutator = null; if (bean == null) { throw new NullPointerException("could not find bean"); } if (property == null) { throw new NullPointerException("could not find property"); } try { PropertyDescriptor descriptor = PropertyUtils.getPropertyDescriptor(bean, property); if (descriptor != null) { mutator = descriptor.getWriteMethod(); } } catch (Exception e) { throw new RuntimeException(e); } return mutator; } protected static void getDescriptors(Class beanType, Predicate predicate, Map result, Set> exploredTypes) { if (exploredTypes.contains(beanType)) { // already explored return; } exploredTypes.add(beanType); PropertyDescriptor[] descriptors = PropertyUtils.getPropertyDescriptors(beanType); for (PropertyDescriptor descriptor : descriptors) { String name = descriptor.getName(); if (!result.containsKey(name) && predicate.apply(descriptor)) { result.put(name, descriptor); } } if (beanType.getSuperclass() != null) { // get properties fro super-class getDescriptors(beanType.getSuperclass(), predicate, result, exploredTypes); } Class[] interfaces = beanType.getInterfaces(); for (Class anInterface : interfaces) { // get properties fro super-class getDescriptors(anInterface, predicate, result, exploredTypes); } } protected static void getReadableProperties(Class beanType, Set result, Set> exploredTypes) { if (exploredTypes.contains(beanType)) { // already explored return; } exploredTypes.add(beanType); // get properties for the class getReadableProperties(beanType, result); if (beanType.getSuperclass() != null) { // get properties fro super-class getReadableProperties(beanType.getSuperclass(), result, exploredTypes); } Class[] interfaces = beanType.getInterfaces(); for (Class anInterface : interfaces) { // get properties fro super-class getReadableProperties(anInterface, result, exploredTypes); } } protected static void getReadableProperties(Class beanType, Set result) { PropertyDescriptor[] descriptors = PropertyUtils.getPropertyDescriptors(beanType); for (PropertyDescriptor descriptor : descriptors) { String name = descriptor.getName(); if (descriptor.getReadMethod() != null) { result.add(name); } } } protected static void getWriteableProperties(Class beanType, Set result, Set> exploredTypes) { if (exploredTypes.contains(beanType)) { // already explored return; } exploredTypes.add(beanType); // get properties for the class getWriteableProperties(beanType, result); if (beanType.getSuperclass() != null) { // get properties fro super-class getWriteableProperties(beanType.getSuperclass(), result, exploredTypes); } Class[] interfaces = beanType.getInterfaces(); for (Class anInterface : interfaces) { // get properties fro super-class getWriteableProperties(anInterface, result, exploredTypes); } } protected static void getWriteableProperties(Class beanType, Set result) { PropertyDescriptor[] descriptors = PropertyUtils.getPropertyDescriptors(beanType); for (PropertyDescriptor descriptor : descriptors) { String name = descriptor.getName(); if (descriptor.getReadMethod() != null) { result.add(name); } } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy