package com.artfess.base.util; import com.artfess.base.model.Tree; import com.artfess.base.util.time.TimeUtil; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.TextNode; import org.apache.commons.beanutils.BeanUtilsBean; import org.apache.commons.beanutils.ConvertUtilsBean; import org.apache.commons.beanutils.DynaBean; import org.apache.commons.beanutils.DynaProperty; import org.apache.commons.beanutils.PropertyUtilsBean; import org.apache.commons.beanutils.converters.DateConverter; import org.apache.commons.beanutils.converters.LongConverter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternResolver; import org.springframework.core.type.classreading.CachingMetadataReaderFactory; import org.springframework.core.type.classreading.MetadataReader; import org.springframework.core.type.classreading.MetadataReaderFactory; import org.springframework.util.ReflectionUtils; import java.beans.PropertyDescriptor; import java.io.IOException; import java.io.Serializable; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.text.DecimalFormat; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; /** * BeanUtils的等价类,只是将check exception改为uncheck exception * * @author heyifan * @company 阿特菲斯信息技术有限公司 * @email heyf@jee-soft.cn * @date 2018年4月19日 */ public class BeanUtils { private static Logger logger = LoggerFactory.getLogger(BeanUtils.class); /** * BeanUtil类型转换器 */ public static ConvertUtilsBean convertUtilsBean = new ConvertUtilsBean(); private static BeanUtilsBean beanUtilsBean = new BeanUtilsBean( convertUtilsBean, new PropertyUtilsBean()); static { convertUtilsBean.register(new DateConverter(), Date.class); convertUtilsBean.register(new LongConverter(null), Long.class); } /** * 可以用于判断 Map,Collection,String,Array,Long是否为空 * * @param o java.lang.Object. * @return boolean. */ public static boolean isEmpty(Object o) { if (o == null) return true; if (o instanceof String) { if (((String) o).trim().length() == 0) return true; } else if (o instanceof Collection) { if (((Collection) o).size() == 0) return true; } else if (o.getClass().isArray()) { if (((Object[]) o).length == 0) return true; } else if (o instanceof Map) { if (((Map) o).size() == 0) return true; } else if (o instanceof ArrayNode) { ArrayNode an = (ArrayNode) o; return an.isEmpty(null); } else if (o instanceof Serializable) { return ((Serializable) o).toString().trim().length() == 0; } return false; } /** * 可以用于判断 Map,Collection,String,Array是否不为空 * * @param o * @return */ public static boolean isNotEmpty(Object o) { return !isEmpty(o); } /** * 判断对象是否为数字 * * @param o * @return */ public static boolean isNumber(Object o) { if (o == null) return false; if (o instanceof Number) return true; if (o instanceof String) { try { Double.parseDouble((String) o); return true; } catch (NumberFormatException e) { return false; } } return false; } /** * 根据指定的类名判定指定的类是否存在。 * * @param className * @return */ public static boolean validClass(String className) { try { Class.forName(className); return true; } catch (ClassNotFoundException e) { return false; } } /** * 判定类是否继承自父类 * * @param cls 子类 * @param parentClass 父类 * @return */ @SuppressWarnings({"unchecked", "rawtypes"}) public static boolean isInherit(Class cls, Class parentClass) { return parentClass.isAssignableFrom(cls); } /** * 输入基类包名,扫描其下的类,返回类的全路径 * * @param basePackages 如:com.artfess * @return * @throws IllegalArgumentException */ @SuppressWarnings("all") public static List scanPackages(String basePackages) throws IllegalArgumentException { ResourcePatternResolver rl = new PathMatchingResourcePatternResolver(); MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory( rl); List result = new ArrayList(); String[] arrayPackages = basePackages.split(","); try { for (int j = 0; j < arrayPackages.length; j++) { String packageToScan = arrayPackages[j]; String packagePart = packageToScan.replace('.', '/'); String classPattern = "classpath*:/" + packagePart + "/**/*.class"; Resource[] resources = rl.getResources(classPattern); for (int i = 0; i < resources.length; i++) { Resource resource = resources[i]; MetadataReader metadataReader = metadataReaderFactory .getMetadataReader(resource); String className = metadataReader.getClassMetadata() .getClassName(); result.add(className); } } } catch (Exception e) { new IllegalArgumentException("scan pakcage class error,pakcages:" + basePackages); } return result; } /** * java反射访问私有成员变量的值。 * * @param instance * @param fieldName * @return * @throws IllegalAccessException * @throws NoSuchFieldException Object */ public static Object getValue(Object instance, String fieldName) throws IllegalAccessException, NoSuchFieldException { Field field = getField(instance.getClass(), fieldName); // 参数值为true,禁用访问控制检查 field.setAccessible(true); return field.get(instance); } /** * 将字符串数据按照指定的类型进行转换。 * * @param typeName 实际的数据类型 * @param value 字符串值。 * @return Object */ public static Object convertByActType(String typeName, String value) { Object o = null; if (typeName.equals("int")) { o = Integer.parseInt(value); } else if (typeName.equals("short")) { o = Short.parseShort(value); } else if (typeName.equals("long")) { o = Long.parseLong(value); } else if (typeName.equals("float")) { o = Float.parseFloat(value); } else if (typeName.equals("double")) { o = Double.parseDouble(value); } else if (typeName.equals("boolean")) { o = Boolean.parseBoolean(value); } else if (typeName.equals("java.lang.String")) { o = value; } else { o = value; } return o; } /** * 根据类和成员变量名称获取成员变量。 * * @param thisClass * @param fieldName * @return * @throws NoSuchFieldException Field */ public static Field getField(Class thisClass, String fieldName) throws NoSuchFieldException { if (fieldName == null) { throw new NoSuchFieldException("Error field !"); } Field field = thisClass.getDeclaredField(fieldName); return field; } /** * 合并两个对象。 * * @param srcObj * @param desObj void */ public static void mergeObject(Object srcObj, Object desObj) { if (srcObj == null || desObj == null) return; Field[] fs1 = srcObj.getClass().getDeclaredFields(); Field[] fs2 = desObj.getClass().getDeclaredFields(); for (int i = 0; i < fs1.length; i++) { try { fs1[i].setAccessible(true); Object value = fs1[i].get(srcObj); fs1[i].setAccessible(false); if (null != value) { fs2[i].setAccessible(true); fs2[i].set(desObj, value); fs2[i].setAccessible(false); } } catch (Exception e) { logger.error("mergeObject" + e.getMessage()); } } } /** * 数据列表去重 * * @param list */ @SuppressWarnings({"rawtypes", "unchecked"}) public static void removeDuplicate(List list) { HashSet h = new HashSet(list); list.clear(); list.addAll(h); } /** * @描述 list数据转Tree,大多使用在前台json中。 * @说明 实现接口 Tree即可 * @扩展 可通过反射获取id, pid,目前只提供Tree接口排序的实现 * @author miao */ @SuppressWarnings("unchecked") public static List listToTree(List list) { Map tempMap = new LinkedHashMap(); if (BeanUtils.isEmpty(list)) return Collections.emptyList(); if (!(list.get(0) instanceof Tree)) { throw new RuntimeException("树形转换出现异常。数据必须实现Tree接口!"); } List returnList = new ArrayList(); for (Tree tree : (List) list) { tree.setIsParent("false"); tempMap.put(tree.getId(), tree); } for (Tree obj : (List) list) { String parentId = obj.getParentId(); if (tempMap.containsKey(parentId) && !obj.getId().equals(parentId)) { if (tempMap.get(parentId).getChildren() == null) { tempMap.get(parentId).setChildren(new ArrayList<>()); } tempMap.get(parentId).getChildren().add(obj); tempMap.get(parentId).setIsParent("true"); } else { returnList.add((T) obj); } } return returnList; } /** * 获取某个父节点下面的所有子节点 * * @param list * @param pid * @param result * @return */ @SuppressWarnings("unchecked") public static void listByPid(List list, String pid, List result) { for (Tree t : (List) list) { //遍历出父id等于参数的id,add进子节点集合 if (BeanUtils.isNotEmpty(t) && pid.equals(t.getParentId())) { //递归遍历下一级 listByPid(list, t.getId(), result); result.add((T) t); } } } /** * 拷贝一个bean中的非空属性于另一个bean中 * * @param dest 目标对象 * @param orig 源对象 * @throws IllegalAccessException * @throws InvocationTargetException */ public static void copyNotNullProperties(Object dest, Object orig) throws IllegalAccessException, InvocationTargetException { // Validate existence of the specified beans if (dest == null) { logger.error("No destination bean specified"); return; } if (orig == null) { logger.error("No origin bean specified"); return; } // Copy the properties, converting as necessary if (orig instanceof DynaBean) { DynaProperty[] origDescriptors = ((DynaBean) orig) .getDynaClass().getDynaProperties(); for (int i = 0; i < origDescriptors.length; i++) { String name = origDescriptors[i].getName(); if (beanUtilsBean.getPropertyUtils().isReadable(orig, name) && beanUtilsBean.getPropertyUtils().isWriteable( dest, name)) { Object value = ((DynaBean) orig).get(name); beanUtilsBean.copyProperty(dest, name, value); } } } else if (orig instanceof Map) { Iterator entries = ((Map) orig).entrySet().iterator(); while (entries.hasNext()) { @SuppressWarnings("rawtypes") Map.Entry entry = (Map.Entry) entries.next(); String name = (String) entry.getKey(); if (beanUtilsBean.getPropertyUtils() .isWriteable(dest, name)) { beanUtilsBean .copyProperty(dest, name, entry.getValue()); } } } else /* if (orig is a standard JavaBean) */ { PropertyDescriptor[] origDescriptors = beanUtilsBean .getPropertyUtils().getPropertyDescriptors(orig); for (int i = 0; i < origDescriptors.length; i++) { String name = origDescriptors[i].getName(); if ("class".equals(name)) { continue; // No point in trying to set an object's class } if (beanUtilsBean.getPropertyUtils().isReadable(orig, name) && beanUtilsBean.getPropertyUtils().isWriteable( dest, name)) { try { Object value = beanUtilsBean.getPropertyUtils() .getSimpleProperty(orig, name); if (value != null) { beanUtilsBean.copyProperty(dest, name, value); } } catch (NoSuchMethodException e) { e.printStackTrace(); } } } } } /** * 克隆对象 * * @param bean * @return * @throws NoSuchMethodException * @throws InvocationTargetException * @throws InstantiationException * @throws IllegalAccessException */ public static Object cloneBean(Object bean) throws Exception { return beanUtilsBean.cloneBean(bean); } /** * 通过反射设置对象的值。 * * @param bean * @param name * @param value void */ public static void setProperty(Object bean, String name, Object value) { try { beanUtilsBean.setProperty(bean, name, value); } catch (Exception e) { handleReflectionException(e); } } private static void handleReflectionException(Exception e) { ReflectionUtils.handleReflectionException(e); } public static boolean isEquals(Object newVal, Object oldVal) { if (newVal == oldVal || (isEmpty(newVal) && isEmpty(oldVal))) { return true; } else if ((isEmpty(newVal) && isNotEmpty(oldVal)) || (isNotEmpty(newVal) && isEmpty(oldVal))) { return false; } else if (!ObjectToString(newVal).equals(ObjectToString(oldVal))) { return false; } return true; } public static String ObjectToString(Object val) { if (BeanUtils.isEmpty(val)) { return ""; } else if (val instanceof String) { return (String) val; } else if (isNumber(val)) { DecimalFormat decimalFormat = new DecimalFormat("###################.###########"); return decimalFormat.format(val); } else if ((val instanceof LocalDateTime)) { return TimeUtil.getDateTimeString((LocalDateTime) val); } else if ((val instanceof LocalDate)) { LocalDate date = (LocalDate) val; return TimeUtil.getDateString(date.atTime(0, 0, 0)); } else if ((val instanceof TextNode)) { return ((TextNode) val).asText(); } else { try { return JsonUtil.toJson(val); } catch (IOException e) { e.printStackTrace(); } return val.toString(); } } /** * 对象转Map * @param object * @return * @throws IllegalAccessException */ public static Map beanToMap(Object object) { Map map = new HashMap(); try { Field[] fields = object.getClass().getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); map.put(field.getName(), field.get(object)); } } catch (Exception e) { e.printStackTrace(); } return map; } // public static JSONArray processChildren(JSONArray array) { // for (Object o : array) { // JSONObject jsonObject = (JSONObject) o; // JSONArray childrenList = JSONArray.parseArray(JSON.toJSONString(jsonObject.get("children"))); // if (null == childrenList || childrenList.size() < 1) { // jsonObject.remove("children"); // } else { // jsonObject.put("children", processChildren(childrenList)); // } // } // return array; // } }