/** * Returns a <code>{@link List}</code> containing the values of the given property name, from the elements of the given * <code>{@link Iterable}</code>. If the given {@code Iterable} is empty or {@code null}, this method will return an empty * {@code List}. This method supports nested properties (e.g. "address.street.number"). * @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 {@code Iterable}. * @return an {@code Iterable} containing the values of the given property name, from the elements of the given {@code Iterable}. * @throws IntrospectionError if an element in the given {@code Iterable} does not have a property with a matching name. */ public <T> Iterable<T> propertyValues(String propertyName, Class<T> clazz, Iterable<?> target) { // ignore null elements as we can't extract a property from a null object Iterable<?> cleanedUp = nonNullElementsIn(target); if (isNullOrEmpty(cleanedUp)) { return emptyList(); } if (isNestedProperty(propertyName)) { String firstPropertyName = popPropertyNameFrom(propertyName); Iterable<Object> propertyValues = propertyValues(firstPropertyName, Object.class, cleanedUp); // extract next sub-property values until reaching the last sub-property return propertyValues(nextPropertyNameFrom(propertyName), clazz, propertyValues); } return simplePropertyValues(propertyName, clazz, cleanedUp); }