package org.theonefx.wcframework.ioc;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import org.theonefx.wcframework.core.TypeConverter;
import org.theonefx.wcframework.core.exception.BeansException;
import org.theonefx.wcframework.core.propertyeditor.PropertyEditorRegistrySupport;
import org.theonefx.wcframework.ioc.exception.InvalidPropertyException;
import org.theonefx.wcframework.ioc.exception.NotWritablePropertyException;
import org.theonefx.wcframework.ioc.exception.NullValueInNestedPathException;
import org.theonefx.wcframework.ioc.exception.PropertyAccessException;
import org.theonefx.wcframework.ioc.exception.PropertyBatchUpdateException;
import org.theonefx.wcframework.ioc.exception.TypeMismatchException;
import org.theonefx.wcframework.ioc.val.MutablePropertyValues;
/**
* 接口{@link PropertyAccessor}的抽象实现.
* 提供所有转换方法的基本能实现.
* 实际的属性访问的实现留给子类.
*/
public abstract class AbstractPropertyAccessor extends PropertyEditorRegistrySupport implements PropertyAccessor, TypeConverter {
public void setPropertyValue(PropertyValue pv) throws BeansException {
setPropertyValue(pv.getName(), pv.getValue());
}
public void setPropertyValues(PropertyValues pvs) throws BeansException {
setPropertyValues(pvs, false, false);
}
public void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid)
throws BeansException {
List<PropertyAccessException> propertyAccessExceptions = null;
List<PropertyValue> propertyValues = (pvs instanceof MutablePropertyValues ? ((MutablePropertyValues) pvs).getPropertyValueList() : Arrays.asList(pvs.getPropertyValues()));
for (PropertyValue pv : propertyValues) {
try {
// This method may throw any BeansException,
// which won't be caught here,
// if there is a critical failure such as no matching field.
// We can attempt to deal only with less serious exceptions.
setPropertyValue(pv);
} catch (NotWritablePropertyException ex) {
if (!ignoreUnknown) {
throw ex;
} else {
// 否则忽略并继续...
}
} catch (NullValueInNestedPathException ex) {
if (!ignoreInvalid) {
throw ex;
} else {
// 否则忽略并继续...
}
} catch (PropertyAccessException ex) {
ex.printStackTrace();
if (propertyAccessExceptions == null) {
propertyAccessExceptions = new LinkedList<PropertyAccessException>();
}
propertyAccessExceptions.add(ex);
}
}
// If we encountered individual exceptions, throw the composite exception.
if (propertyAccessExceptions != null) {
PropertyAccessException[] paeArray = propertyAccessExceptions.toArray(new PropertyAccessException[propertyAccessExceptions.size()]);
throw new PropertyBatchUpdateException(paeArray);
}
}
public <T> T convertIfNecessary(Object value, Class<T> requiredType) throws TypeMismatchException {
return convertIfNecessary(value, requiredType, null);
}
/**
* 获取属性值的真正实现在子类中进行.
* @param propertyName 需要被获取值的属性的名称
* @return 目标属性的值
* @throws InvalidPropertyException 如果找不到该属性或者该属性不可读
* @throws PropertyAccessException 如果该属性是有效的,但是对该属性的访问却失败了
*/
public abstract Object getPropertyValue(String propertyName) throws BeansException;
/**
* 设置属性值的真正实现在子类中进行.
* @param propertyName 需要被设置值的属性的名称
* @param value 属性的新的值
* @throws InvalidPropertyException 如果找不到该属性或者该属性不可写
* @throws PropertyAccessException 该属性本身是有效的,但是调用访问方法时失败或者新的值类型不匹配
*/
public abstract void setPropertyValue(String propertyName, Object value) throws BeansException;
}