/** * Return the value of property from a target object. * @param propertyName the name of the property. It may be a nested property. It is left to the clients to validate for * {@code null} or empty. * @param target the given object * @param clazz type of property * @return a the values of the given property name * @throws IntrospectionError if the given target does not have a property with a matching name. */ public <T> T propertyValue(String propertyName, Class<T> clazz, Object target) { PropertyDescriptor descriptor = getProperty(propertyName, target); try { return clazz.cast(javaBeanDescriptor.invokeReadMethod(descriptor, target)); } catch (ClassCastException e) { String msg = format("Unable to obtain the value of the property <'%s'> from <%s> - wrong property type specified <%s>", propertyName, target, clazz); throw new IntrospectionError(msg, e); } catch (Throwable unexpected) { String msg = format("Unable to obtain the value of the property <'%s'> from <%s>", propertyName, target); throw new IntrospectionError(msg, unexpected); } }
private static Method findGetter(String propertyName, Object target) { String capitalized = propertyName.substring(0, 1).toUpperCase(ENGLISH) + propertyName.substring(1); // try to find getProperty Method getter = findMethod("get" + capitalized, target); if (getter != null) { return getter; } // try to find isProperty for boolean properties return findMethod("is" + capitalized, target); }
private static String propertyNotFoundErrorMessage(String propertyName, Object target) { String targetTypeName = target.getClass().getName(); String property = quote(propertyName); Method getter = findGetter(propertyName, target); if (getter == null) { return format("No getter for property %s in %s", property, targetTypeName); } if (!isPublic(getter.getModifiers())) { return format("No public getter for property %s in %s", property, targetTypeName); } return format("Unable to find property %s in %s", property, targetTypeName); }
/** * Returns a {@link PropertyDescriptor} for a property matching the given name in the given object. * * @param propertyName the given property name. * @param target the given object. * @return a {@code PropertyDescriptor} for a property matching the given name in the given object. * @throws NullPointerException if the given property name is {@code null}. * @throws IllegalArgumentException if the given property name is empty. * @throws NullPointerException if the given object is {@code null}. * @throws IntrospectionError if a matching property cannot be found or accessed. */ public static PropertyDescriptor getProperty(String propertyName, Object target) { checkNotNullOrEmpty(propertyName); checkNotNull(target); BeanInfo beanInfo = null; Class<?> type = target.getClass(); try { beanInfo = Introspector.getBeanInfo(type); } catch (Throwable t) { throw new IntrospectionError(format("Unable to get BeanInfo for type %s", type.getName()), t); } for (PropertyDescriptor descriptor : beanInfo.getPropertyDescriptors()) { if (propertyName.equals(descriptor.getName())) { return descriptor; } } throw new IntrospectionError(propertyNotFoundErrorMessage(propertyName, target)); }