package org.test4j.tools.reflector; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import org.test4j.tools.commons.ArrayHelper; import org.test4j.tools.commons.ClazzHelper; import org.test4j.tools.commons.FieldHelper; import org.test4j.tools.commons.ListHelper; import org.test4j.tools.commons.StringHelper; import org.test4j.tools.exception.NoSuchFieldRuntimeException; /** * POJO属性值或Map访问 * * @author darui.wudr * */ @SuppressWarnings({ "unchecked", "rawtypes" }) public class PropertyAccessor { public static Object getPropertyByOgnl(final Object target, String ognl) { Object o = getPropertyByOgnl(target, ognl, true); return o; } /** * 获得单值对象(非集合或数组,但包含Map)的单个属性值<br> * 先访问get方法(is方法),如果没有get方法再直接访问属性值 * * @param object * @param ognlExpression * @param throwException * @return */ public static Object getPropertyByOgnl(final Object object, String ognl, boolean throwNoProperty) { String[] expressions = ognl.split("\\."); try { Object target = object; String key = ""; for (String prop : expressions) { if (target == null && throwNoProperty == false) { return null; } else if (target instanceof Map) { Map map = (Map) target; key = key.equals("") ? prop : key + "." + prop; if (map.containsKey(key)) { target = map.get(key); key = ""; } } else { target = getProperty(target, prop); } } if (key.equals("") == false) { throw new NoSuchFieldRuntimeException(); } else { return target; } } catch (NoSuchFieldRuntimeException e) { if (throwNoProperty) { String clazname = object == null ? "null" : object.getClass().getName(); throw new NoSuchFieldRuntimeException("can't find property[" + ognl + "] in object[" + clazname + "]", e); } else { return object; } } } /** * * o 先根据get方法访问对象的属性,如果存在则返回<br> * o 再根据is方法方法对象的属性,且方法值是bool型,返回<br> * o 否则,直接方法对象的字段<br> * o 如果对象是Map,则根据key值取 * * @param o * @param prop * @return */ public static Object getProperty(final Object o, String prop) { if (o == null) { throw new RuntimeException("can't get the property value from a null object."); } if (o instanceof Map) { Map map = (Map) o; if (map.containsKey(prop)) { return map.get(prop); } else { throw new NoSuchFieldRuntimeException("no key[" + prop + "] value in map."); } } Object target = ClazzHelper.getProxiedObject(o); try { String method = StringHelper.camel("get", prop); MethodAccessor accessor = new MethodAccessor(target, method); return accessor.invoke(target, new Object[] {}); } catch (Throwable e) { try { String method = StringHelper.camel("is", prop); MethodAccessor accessor = new MethodAccessor(target, method); Object b = accessor.invoke(target, new Object[] {}); if (b instanceof Boolean) { return b; } throw new RuntimeException(); } catch (Throwable e1) { Object o2 = FieldHelper.getFieldValue(target, prop); return o2; } } } /** * 获得单值对象(非集合或数组,但包含Map)的多个属性值 * * @param object * @param ognl * @param throwException * @return */ public static Object[] getPropertyValue(Object object, String[] ognls, boolean throwException) { List<Object> os = new ArrayList<Object>(); for (String ognl : ognls) { Object value = getPropertyByOgnl(object, ognl, throwException); os.add(value); } return os.toArray(new Object[0]); } /** * 获得数组(集合)中各个对象的属性值列表<br> * * @param arr * 数组或集合,如果是单值(或Map)转为size=1的集合处理 * @param property * @return */ public static List<?> getArrayItemProperty(Object arr, String property) { Collection coll = ListHelper.toList(arr); List values = new ArrayList(); for (Object o : coll) { Object value = PropertyAccessor.getPropertyByOgnl(o, property, false); values.add(value); } return values; } /** * 获得对象的属性列表<br> * o 如果对象是集合或数组,返回集合对象的属性值的列表<br> * o 如果对象是单值,且属性是集合或数组,直接返回单值对象的属性值<br> * o 如果对象是单值,且属性是非集合和数组类型,构造包含这个属性值的列表 * * @param item * @param property * @return */ public static Collection getArrayOrItemProperty(Object item, String property) { Collection values = null; if (ArrayHelper.isCollOrArray(item)) { values = PropertyAccessor.getArrayItemProperty(item, property); } else { Object o = PropertyAccessor.getProperty(item, property); values = ListHelper.toList(o); } return values; } /** * 获得数组(集合)中各个对象的多个属性值 * * @param arr * 数组或集合,如果是单值(或Map)转为size=1的集合处理 * @param properties * @return */ public static Object[][] getArrayItemProperties(Object arr, String[] properties) { Collection coll = ListHelper.toList(arr); List values = new ArrayList(); for (Object o : coll) { Object[] props = PropertyAccessor.getPropertyValue(o, properties, false); values.add(props); } return (Object[][]) values.toArray(new Object[0][0]); } // ========================== /** * 获得集合列表中对象的属性值列表 * * @param list * @param properties * @param throwNoProperty * @return */ public static List<List> getPropertiesOfList(List list, String[] properties, boolean throwNoProperty) { List<List> result = new ArrayList<List>(); for (Object target : list) { List items = new ArrayList(); if (ArrayHelper.isCollOrArray(target) && throwNoProperty == false) { List value = ListHelper.toList(target); result.add(value); continue; } for (String ognl : properties) { Object value = PropertyAccessor.getPropertyByOgnl(target, ognl, throwNoProperty); items.add(value); } result.add(items); } return result; } /** * 获得属性值列表的集合 * * @param list * @param properties * @param throwNoProperty * @return */ public static List<List> getPropertySetsOfList(List list, String[] properties, boolean throwNoProperty) { List<List> result = new ArrayList<List>(); for (String ognl : properties) { List items = new ArrayList(); for (Object target : list) { if (ArrayHelper.isCollOrArray(target)) { List _target = ListHelper.toList(target); List values = getPropertyOfList(_target, ognl, throwNoProperty); items.add(values); } else { Object value = getPropertyByOgnl(target, ognl, throwNoProperty); items.add(value); } } result.add(items); } return result; } public static List getPropertyOfList(List list, String ognl, boolean throwNoProperty) { List result = new ArrayList(); for (Object target : list) { Object value = PropertyAccessor.getPropertyByOgnl(target, ognl, throwNoProperty); result.add(value); } return result; } /** * 获得PoJo对象或Map对象的属性值列表 * * @param target * @param properties * @param throwNoProperty * @return */ public static List getPropertiesOfPoJo(Object target, String[] properties, boolean throwNoProperty) { List result = new ArrayList(); for (String ognl : properties) { Object value = PropertyAccessor.getPropertyByOgnl(target, ognl, throwNoProperty); result.add(value); } return result; } }