in xbean-reflect/src/main/java/org/apache/xbean/recipe/ReflectionUtil.java [73:170]
public static Field findField(Class typeClass, String propertyName, Object propertyValue, Set<Option> options,
PropertyEditorRegistry registry) {
if (typeClass == null) throw new NullPointerException("typeClass is null");
if (propertyName == null) throw new NullPointerException("name is null");
if (propertyName.length() == 0) throw new IllegalArgumentException("name is an empty string");
if (options == null) options = EnumSet.noneOf(Option.class);
int matchLevel = 0;
MissingAccessorException missException = null;
if (propertyName.contains("/")){
String[] strings = propertyName.split("/");
if (strings == null || strings.length != 2) throw new IllegalArgumentException("badly formed <class>/<attribute> property name: " + propertyName);
String className = strings[0];
propertyName = strings[1];
boolean found = false;
while(!typeClass.equals(Object.class) && !found){
if (typeClass.getName().equals(className)){
found = true;
break;
} else {
typeClass = typeClass.getSuperclass();
}
}
if (!found) throw new MissingAccessorException("Type not assignable to class: " + className, -1);
}
List<Field> fields = new ArrayList<Field>(Arrays.asList(typeClass.getDeclaredFields()));
Class parent = typeClass.getSuperclass();
while (parent != null){
fields.addAll(Arrays.asList(parent.getDeclaredFields()));
parent = parent.getSuperclass();
}
boolean allowPrivate = options.contains(Option.PRIVATE_PROPERTIES);
boolean allowStatic = options.contains(Option.STATIC_PROPERTIES);
boolean caseInsesnitive = options.contains(Option.CASE_INSENSITIVE_PROPERTIES);
for (Field field : fields) {
if (field.getName().equals(propertyName) || (caseInsesnitive && field.getName().equalsIgnoreCase(propertyName))) {
if (!allowPrivate && !Modifier.isPublic(field.getModifiers())) {
if (matchLevel < 4) {
matchLevel = 4;
missException = new MissingAccessorException("Field is not public: " + field, matchLevel);
}
continue;
}
if (!allowStatic && Modifier.isStatic(field.getModifiers())) {
if (matchLevel < 4) {
matchLevel = 4;
missException = new MissingAccessorException("Field is static: " + field, matchLevel);
}
continue;
}
Class fieldType = field.getType();
if (fieldType.isPrimitive() && propertyValue == null) {
if (matchLevel < 6) {
matchLevel = 6;
missException = new MissingAccessorException("Null can not be assigned to " +
fieldType.getName() + ": " + field, matchLevel);
}
continue;
}
if (!RecipeHelper.isInstance(fieldType, propertyValue) && !RecipeHelper.isConvertable(fieldType, propertyValue, registry)) {
if (matchLevel < 5) {
matchLevel = 5;
missException = new MissingAccessorException((propertyValue == null ? "null" : propertyValue.getClass().getName()) + " can not be assigned or converted to " +
fieldType.getName() + ": " + field, matchLevel);
}
continue;
}
if (allowPrivate && !Modifier.isPublic(field.getModifiers())) {
setAccessible(field);
}
return field;
}
}
if (missException != null) {
throw missException;
} else {
StringBuffer buffer = new StringBuffer("Unable to find a valid field: ");
buffer.append("public ").append(" ").append(propertyValue == null ? "null" : propertyValue.getClass().getName());
buffer.append(" ").append(propertyName).append(";");
throw new MissingAccessorException(buffer.toString(), -1);
}
}