in xbean-reflect/src/main/java/org/apache/xbean/recipe/ReflectionUtil.java [487:577]
public static List<Method> findAllSettersByType(Class typeClass, Object propertyValue, Set<Option> options,
PropertyEditorRegistry registry) {
if (typeClass == null) throw new NullPointerException("typeClass is null");
if (options == null) options = EnumSet.noneOf(Option.class);
int matchLevel = 0;
MissingAccessorException missException = null;
boolean allowPrivate = options.contains(Option.PRIVATE_PROPERTIES);
boolean allowStatic = options.contains(Option.STATIC_PROPERTIES);
LinkedList<Method> validSetters = new LinkedList<Method>();
List<Method> methods = new ArrayList<Method>(Arrays.asList(typeClass.getMethods()));
methods.addAll(Arrays.asList(typeClass.getDeclaredMethods()));
for (Method method : methods) {
if (method.getName().startsWith("set") && method.getParameterTypes().length == 1 && (RecipeHelper.isInstance(method.getParameterTypes()[0], propertyValue) || RecipeHelper.isConvertable(method.getParameterTypes()[0], propertyValue, registry))) {
if (method.getReturnType() != Void.TYPE) {
if (matchLevel < 2) {
matchLevel = 2;
missException = new MissingAccessorException("Setter returns a value: " + method, matchLevel);
}
continue;
}
if (Modifier.isAbstract(method.getModifiers())) {
if (matchLevel < 3) {
matchLevel = 3;
missException = new MissingAccessorException("Setter is abstract: " + method, matchLevel);
}
continue;
}
if (!allowPrivate && !Modifier.isPublic(method.getModifiers())) {
if (matchLevel < 4) {
matchLevel = 4;
missException = new MissingAccessorException("Setter is not public: " + method, matchLevel);
}
continue;
}
Class methodParameterType = method.getParameterTypes()[0];
if (methodParameterType.isPrimitive() && propertyValue == null) {
if (matchLevel < 6) {
matchLevel = 6;
missException = new MissingAccessorException("Null can not be assigned to " +
methodParameterType.getName() + ": " + method, matchLevel);
}
continue;
}
if (!allowStatic && Modifier.isStatic(method.getModifiers())) {
if (matchLevel < 4) {
matchLevel = 4;
missException = new MissingAccessorException("Setter is static: " + method, matchLevel);
}
continue;
}
if (allowPrivate && !Modifier.isPublic(method.getModifiers())) {
setAccessible(method);
}
if (RecipeHelper.isInstance(methodParameterType, propertyValue)) {
// This setter requires no conversion, which means there can not be a conversion error.
// Therefore this setter is perferred and put a the head of the list
validSetters.addFirst(method);
} else {
validSetters.add(method);
}
}
}
if (!validSetters.isEmpty()) {
// remove duplicate methods (can happen with inheritance)
return new ArrayList<Method>(new LinkedHashSet<Method>(validSetters));
}
if (missException != null) {
throw missException;
} else {
StringBuffer buffer = new StringBuffer("Unable to find a valid setter ");
if (propertyValue instanceof Recipe) {
buffer.append("for ").append(propertyValue == null ? "null" : propertyValue);
} else {
buffer.append("of type ").append(propertyValue == null ? "null" : propertyValue.getClass().getName());
}
buffer.append(" in class ").append(typeClass.getName());
throw new MissingAccessorException(buffer.toString(), -1);
}
}