in xbean-reflect/src/main/java/org/apache/xbean/recipe/ObjectRecipe.java [383:536]
private void setProperty(Object instance, Class clazz, Property propertyName, Object propertyValue) {
List<Member> members = new ArrayList<Member>();
try {
if (propertyName instanceof SetterProperty){
List<Method> setters = ReflectionUtil.findAllSetters(clazz, propertyName.name, propertyValue, options, registry);
for (Method setter : setters) {
MethodMember member = new MethodMember(setter);
members.add(member);
}
} else if (propertyName instanceof FieldProperty){
FieldMember member = new FieldMember(ReflectionUtil.findField(clazz, propertyName.name, propertyValue, options, registry));
members.add(member);
} else if (propertyName instanceof AutoMatchProperty){
MissingAccessorException noField = null;
if (options.contains(Option.FIELD_INJECTION)) {
List<Field> fieldsByType = null;
try {
fieldsByType = ReflectionUtil.findAllFieldsByType(clazz, propertyValue, options, registry);
FieldMember member = new FieldMember(fieldsByType.iterator().next());
members.add(member);
} catch (MissingAccessorException e) {
noField = e;
}
// if we got more then one matching field, that is an immidate error
if (fieldsByType != null && fieldsByType.size() > 1) {
List<String> matches = new ArrayList<String>();
for (Field field : fieldsByType) {
matches.add(field.getName());
}
throw new MissingAccessorException("Property of type " + propertyValue.getClass().getName() + " can be mapped to more then one field: " + matches, 0);
}
}
// if we didn't find any fields, try the setters
if (members.isEmpty()) {
List<Method> settersByType;
try {
settersByType = ReflectionUtil.findAllSettersByType(clazz, propertyValue, options, registry);
MethodMember member = new MethodMember(settersByType.iterator().next());
members.add(member);
} catch (MissingAccessorException noSetter) {
throw (noField == null || noSetter.getMatchLevel() > noField.getMatchLevel())? noSetter: noField;
}
// if we got more then one matching field, that is an immidate error
if (settersByType != null && settersByType.size() > 1) {
List<String> matches = new ArrayList<String>();
for (Method setter : settersByType) {
matches.add(setter.getName());
}
throw new MissingAccessorException("Property of type " + propertyValue.getClass().getName() + " can be mapped to more then one setter: " + matches, 0);
}
}
} else if (propertyName instanceof CompoundProperty) {
String[] names = propertyName.name.split("\\.");
for (int i = 0; i < names.length - 1; i++) {
Method getter = ReflectionUtil.findGetter(clazz, names[i], options);
if (getter != null) {
try {
instance = getter.invoke(instance);
clazz = instance.getClass();
} catch (Exception e) {
Throwable t = e;
if (e instanceof InvocationTargetException) {
InvocationTargetException invocationTargetException = (InvocationTargetException) e;
if (invocationTargetException.getCause() != null) {
t = invocationTargetException.getCause();
}
}
throw new ConstructionException("Error setting property: " + names[i], t);
}
} else {
throw new ConstructionException("No getter for " + names[i] + " property");
}
}
List<Method> setters = ReflectionUtil.findAllSetters(clazz, names[names.length - 1], propertyValue, options, registry);
for (Method setter : setters) {
MethodMember member = new MethodMember(setter);
members.add(member);
}
} else {
// add setter members
MissingAccessorException noSetter = null;
try {
List<Method> setters = ReflectionUtil.findAllSetters(clazz, propertyName.name, propertyValue, options, registry);
for (Method setter : setters) {
MethodMember member = new MethodMember(setter);
members.add(member);
}
} catch (MissingAccessorException e) {
noSetter = e;
if (!options.contains(Option.FIELD_INJECTION)) {
throw noSetter;
}
}
if (options.contains(Option.FIELD_INJECTION)) {
try {
FieldMember member = new FieldMember(ReflectionUtil.findField(clazz, propertyName.name, propertyValue, options, registry));
members.add(member);
} catch (MissingAccessorException noField) {
if (members.isEmpty()) {
throw (noSetter == null || noField.getMatchLevel() > noSetter.getMatchLevel())? noField: noSetter;
}
}
}
}
} catch (MissingAccessorException e) {
if (options.contains(Option.IGNORE_MISSING_PROPERTIES)) {
unsetProperties.put(propertyName.name, propertyValue);
return;
}
throw e;
}
ConstructionException conversionException = null;
for (Member member : members) {
// convert the value to type of setter/field
try {
propertyValue = RecipeHelper.convert(member.getType(), propertyValue, false, registry);
} catch (Exception e) {
// save off first conversion exception, in case setting failed
if (conversionException == null) {
String valueType = propertyValue == null ? "null" : propertyValue.getClass().getName();
String memberType = member.getType() instanceof Class ? ((Class) member.getType()).getName() : member.getType().toString();
conversionException = new ConstructionException("Unable to convert property value" +
" from " + valueType +
" to " + memberType +
" for injection " + member, e);
}
continue;
}
try {
// set value
member.setValue(instance, propertyValue);
} catch (Exception e) {
Throwable t = e;
if (e instanceof InvocationTargetException) {
InvocationTargetException invocationTargetException = (InvocationTargetException) e;
if (invocationTargetException.getCause() != null) {
t = invocationTargetException.getCause();
}
}
throw new ConstructionException("Error setting property: " + member, t);
}
// value set successfully
return;
}
throw conversionException;
}