From 4085c975934aa2df85717e3010b90f9630e1692c Mon Sep 17 00:00:00 2001 From: Looly Date: Tue, 5 Jul 2022 21:27:51 +0800 Subject: [PATCH] add methods --- CHANGELOG.md | 4 +- .../copier/provider/BeanValueProvider.java | 97 +++++++++++++++++++ 2 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 hutool-core/src/main/java/cn/hutool/core/bean/copier/provider/BeanValueProvider.java diff --git a/CHANGELOG.md b/CHANGELOG.md index f923c679d..8d597b6df 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,11 +3,13 @@ ------------------------------------------------------------------------------------------------------------- -# 5.8.5.M1 (2022-06-30) +# 5.8.5.M1 (2022-07-05) ### 🐣新特性 * 【core 】 NumberUtil新增isIn方法(pr#669@Gitee) * 【core 】 修复注解工具类getAnnotations的NPE问题,注解扫描器添新功能(pr#671@Gitee) +* 【core 】 合成注解SyntheticAnnotation提取为接口,并为实现类添加注解选择器和属性处理器(pr#678@Gitee) +* 【core 】 增加BeanValueProvider(issue#I5FBHV@Gitee) * ### 🐞Bug修复 diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/copier/provider/BeanValueProvider.java b/hutool-core/src/main/java/cn/hutool/core/bean/copier/provider/BeanValueProvider.java new file mode 100644 index 000000000..9b0d6e956 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/bean/copier/provider/BeanValueProvider.java @@ -0,0 +1,97 @@ +package cn.hutool.core.bean.copier.provider; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.bean.PropDesc; +import cn.hutool.core.bean.copier.ValueProvider; +import cn.hutool.core.lang.Editor; +import cn.hutool.core.map.FuncKeyMap; +import cn.hutool.core.util.StrUtil; + +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.Map; + +/** + * Bean的值提供者 + * + * @author looly + */ +public class BeanValueProvider implements ValueProvider { + + private final Object source; + private final boolean ignoreError; + final Map sourcePdMap; + + /** + * 构造 + * + * @param bean Bean + * @param ignoreCase 是否忽略字段大小写 + * @param ignoreError 是否忽略字段值读取错误 + */ + public BeanValueProvider(Object bean, boolean ignoreCase, boolean ignoreError) { + this(bean, ignoreCase, ignoreError, null); + } + + /** + * 构造 + * + * @param bean Bean + * @param ignoreCase 是否忽略字段大小写 + * @param ignoreError 是否忽略字段值读取错误 + * @param keyEditor 键编辑器 + */ + public BeanValueProvider(Object bean, boolean ignoreCase, boolean ignoreError, Editor keyEditor) { + this.source = bean; + this.ignoreError = ignoreError; + final Map sourcePdMap = BeanUtil.getBeanDesc(source.getClass()).getPropMap(ignoreCase); + // issue#2202@Github + // 如果用户定义了键编辑器,则提供的map中的数据必须全部转换key + this.sourcePdMap = new FuncKeyMap<>(new HashMap<>(sourcePdMap.size(), 1), (key) -> { + if (ignoreCase && key instanceof CharSequence) { + key = key.toString().toLowerCase(); + } + if (null != keyEditor) { + key = keyEditor.edit(key.toString()); + } + return key.toString(); + }); + this.sourcePdMap.putAll(sourcePdMap); + } + + @Override + public Object value(String key, Type valueType) { + final PropDesc sourcePd = getPropDesc(key, valueType); + + Object result = null; + if (null != sourcePd) { + result = sourcePd.getValue(this.source, valueType, this.ignoreError); + } + return result; + } + + @Override + public boolean containsKey(String key) { + final PropDesc sourcePd = getPropDesc(key, null); + + // 字段描述不存在或忽略读的情况下,表示不存在 + return null != sourcePd && sourcePd.isReadable(false); + } + + /** + * 获得属性描述 + * + * @param key 字段名 + * @param valueType 值类型,用于判断是否为Boolean,可以为null + * @return 属性描述 + */ + private PropDesc getPropDesc(String key, Type valueType) { + PropDesc sourcePd = sourcePdMap.get(key); + if (null == sourcePd && (null == valueType || Boolean.class == valueType || boolean.class == valueType)) { + //boolean类型字段字段名支持两种方式 + sourcePd = sourcePdMap.get(StrUtil.upperFirstAndAddPre(key, "is")); + } + + return sourcePd; + } +}