private Object fireValueEvents( final FieldBinding binding, final Object parent, final XmlRpcListener listener, EventCallback before, EventCallback after) throws XmlRpcException { final Class<?> parentCls = parent.getClass(); try { final Field field = findField(binding, parentCls); field.setAccessible(true); Object value = field.get(parent); if (isSuppressedNull(field, parentCls, value)) { return null; } final ValueType type = typeOf(value, binding); if (before != null) { if (!before.call(value, type)) { return null; } } Converter converter = field.getAnnotation(Converter.class); if (converter == null) { Class<?> fieldType = field.getType(); converter = fieldType.getAnnotation(Converter.class); } if (converter != null) { final ValueBinder vc = XBRBinderInstantiator.newValueUnbinder(converter); vc.generate(listener, value, recipesByClass); } else if (recipesByClass.containsKey(binding.getFieldType())) { if (type == ValueType.ARRAY) { value = fireArrayEvents(binding.getFieldType(), value, listener); } else if (type == ValueType.STRUCT) { value = fireStructEvents(binding.getFieldType(), value, listener); } else { throw new BindException( "Unknown recipe reference type: " + binding.getFieldType() + "\nField: " + binding.getFieldName() + "\nClass: " + parentCls.getName()); } listener.value(value, type); } else { final Contains contains = field.getAnnotation(Contains.class); if (Map.class.isAssignableFrom(binding.getFieldType())) { fireMapEvents(value, binding.getFieldName(), contains, listener); } else if (binding.getFieldType().isArray() || Collection.class.isAssignableFrom(binding.getFieldType())) { fireCollectionEvents(value, binding.getFieldName(), contains, listener); } else { ValueCoercion coercion = type.coercion(); if (coercion == null) { throw new XmlRpcException( "Cannot render {} (type: {}) to string. It has no corresponding coercion, and isn't an @ArrayPart or a @StructPart!"); } value = coercion.toString(value); } listener.value(value, type); } if (after != null) { if (!after.call(value, type)) { return null; } } return value; } catch (final IllegalAccessException e) { throw new BindException( "Cannot retrieve field: " + binding.getFieldName() + " in class: " + parentCls.getName() + "\nError: " + e.getMessage(), e); } }