From dc04fe2fde4ec3ed8b51049bd092377ef9f75e22 Mon Sep 17 00:00:00 2001 From: aoshiguchen <1052045476@qq.com> Date: Fri, 17 Jun 2022 20:11:41 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=BA=95=E5=B1=82=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E8=BD=AC=E6=8D=A2=E9=80=BB=E8=BE=91=E5=B0=81=E8=A3=85?= =?UTF-8?q?=EF=BC=8C=E6=94=AF=E6=8C=81=E8=87=AA=E5=AE=9A=E4=B9=89=E6=89=A9?= =?UTF-8?q?=E5=B1=95.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 + .../neutrino/core/type/TypeConverter.java | 38 ++ .../TypeDistance.java} | 60 ++-- .../TypeMatchInfo.java} | 42 ++- .../neutrino/core/type/TypeMatchLevel.java | 75 ++++ .../asgc/neutrino/core/type/TypeMatcher.java | 42 +++ .../asgc/neutrino/core/type/TypeMatchers.java | 244 +++++++++++++ .../asgc/neutrino/core/util/ReflectUtil.java | 9 +- .../fun/asgc/neutrino/core/util/TypeUtil.java | 327 +++++++++++------- .../asgc/neutrino/core/util/TypeUtilTest.java | 150 ++++++++ 10 files changed, 813 insertions(+), 176 deletions(-) create mode 100644 neutrino-core/src/main/java/fun/asgc/neutrino/core/type/TypeConverter.java rename neutrino-core/src/main/java/fun/asgc/neutrino/core/{constant/TypeNotMatchingValueConstant.java => type/TypeDistance.java} (66%) rename neutrino-core/src/main/java/fun/asgc/neutrino/core/{util/TypeMatchingInfo.java => type/TypeMatchInfo.java} (65%) create mode 100644 neutrino-core/src/main/java/fun/asgc/neutrino/core/type/TypeMatchLevel.java create mode 100644 neutrino-core/src/main/java/fun/asgc/neutrino/core/type/TypeMatcher.java create mode 100644 neutrino-core/src/main/java/fun/asgc/neutrino/core/type/TypeMatchers.java create mode 100644 neutrino-core/src/test/java/fun/asgc/neutrino/core/util/TypeUtilTest.java diff --git a/.gitignore b/.gitignore index cc3dd4df..3d9eafbd 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,5 @@ # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* + +**/*.iml diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/type/TypeConverter.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/type/TypeConverter.java new file mode 100644 index 00000000..06c55dc9 --- /dev/null +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/type/TypeConverter.java @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2022 aoshiguchen + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package fun.asgc.neutrino.core.type; + +/** + * 类型转换器 + * @author: aoshiguchen + * @date: 2022/6/17 + */ +@FunctionalInterface +public interface TypeConverter { + /** + * 类型转换 + * @param value + * @param targetType + * @return + */ + Object convert(Object value, Class targetType); +} diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/constant/TypeNotMatchingValueConstant.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/type/TypeDistance.java similarity index 66% rename from neutrino-core/src/main/java/fun/asgc/neutrino/core/constant/TypeNotMatchingValueConstant.java rename to neutrino-core/src/main/java/fun/asgc/neutrino/core/type/TypeDistance.java index 8f92d50f..37b2d88c 100644 --- a/neutrino-core/src/main/java/fun/asgc/neutrino/core/constant/TypeNotMatchingValueConstant.java +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/type/TypeDistance.java @@ -20,29 +20,34 @@ * SOFTWARE. */ -package fun.asgc.neutrino.core.constant; +package fun.asgc.neutrino.core.type; /** - * 类型不匹配值(后期计划改为"类型距离") + * 类型距离 * @author: aoshiguchen * @date: 2022/6/16 */ -public interface TypeNotMatchingValueConstant { +public interface TypeDistance { /** * 最小值,表示完全匹配 */ - int MIN = 0; + int MIN = TypeMatchLevel.NULL.getDistanceMin(); /** * 最大值,表示完全不匹配 */ int MAX = Integer.MAX_VALUE; + /** + * 空匹配 + */ + int NULL = MIN; + /** * 完全匹配 */ - int COMPLETE = MIN; + int PERFECT = TypeMatchLevel.PERFECT.getDistanceMin(); /** * 完全不匹配 @@ -52,56 +57,51 @@ public interface TypeNotMatchingValueConstant { /** * 包装匹配 */ - int WRAP = 1; + int PACKING = TypeMatchLevel.PACKING.getDistanceMin(); /** * 解包装匹配 */ - int UNWRAP = 2; + int UNPACKING = TypeMatchLevel.UNPACKING.getDistanceMin(); + + /** + * 类型提升起始值 + */ + int ASCENSION_MIN = TypeMatchLevel.ASCENSION.getDistanceMin(); + + /** + * 类型提升最大值 + */ + int ASCENSION_MAX = TypeMatchLevel.ASCENSION.getDistanceMax(); /** * 超类匹配起始值 * 每增加1层,值加1 */ - int SUPER_CLASS_MIN = 100000; - - /** - * 超类最大层级(假定继承层级不会超过40万) - */ - int SUPER_CLASS_MAX_LEVEL = 400000; + int SUPER_MIN = TypeMatchLevel.SUPER.getDistanceMin(); /** * 超类匹配结束值 */ - int SUPER_CLASS_MAX = SUPER_CLASS_MIN + SUPER_CLASS_MAX_LEVEL - 1; + int SUPER_MAX = TypeMatchLevel.SUPER.getDistanceMax(); /** - * 类型提升起始值 + * 内部扩展起始值 */ - int ASCENSION_MIN = 600000; + int EXTENSION_MIN = TypeMatchLevel.EXTENSION.getDistanceMin(); /** - * 类型提升层级 + * 内部扩展结束值 */ - int ASCENSION_LEVEL = 10000; - - /** - * 类型提升最大值 - */ - int ASCENSION_MAX = ASCENSION_MIN + ASCENSION_LEVEL - 1; + int EXTENSION_MAX = TypeMatchLevel.EXTENSION.getDistanceMax(); /** * 自定义类型转换起始值 */ - int CUSTOM_MIN = 10000000; - - /** - * 自定义类型转换层级 - */ - int CUSTOM_LEVEL = 10000000; + int CUSTOM_MIN = TypeMatchLevel.CUSTOM.getDistanceMin(); /** * 自定义类型转换结束值 */ - int CUSTOM_MAX = CUSTOM_MIN + CUSTOM_LEVEL - 1; + int CUSTOM_MAX = TypeMatchLevel.CUSTOM.getDistanceMax(); } diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/util/TypeMatchingInfo.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/type/TypeMatchInfo.java similarity index 65% rename from neutrino-core/src/main/java/fun/asgc/neutrino/core/util/TypeMatchingInfo.java rename to neutrino-core/src/main/java/fun/asgc/neutrino/core/type/TypeMatchInfo.java index 0e175093..0e4def94 100644 --- a/neutrino-core/src/main/java/fun/asgc/neutrino/core/util/TypeMatchingInfo.java +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/type/TypeMatchInfo.java @@ -20,27 +20,24 @@ * SOFTWARE. */ -package fun.asgc.neutrino.core.util; +package fun.asgc.neutrino.core.type; -import fun.asgc.neutrino.core.constant.TypeNotMatchingValueConstant; -import lombok.AllArgsConstructor; import lombok.Data; -import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; /** * * @author: aoshiguchen * @date: 2022/6/16 */ -@AllArgsConstructor -@NoArgsConstructor +@Accessors(chain = true) @Data -public class TypeMatchingInfo { +public class TypeMatchInfo { /** - * 字段类型 + * 目标类型类型 */ - private Class fieldType; + private Class targetType; /** * 值类型 @@ -48,17 +45,32 @@ public class TypeMatchingInfo { private Class valueType; /** - * 不匹配值 + * 类型距离 */ - private Integer notMatchingValue; + private int typeDistance; - public TypeMatchingInfo(Class fieldType, Class valueType) { - this.fieldType = fieldType; + /** + * 类型匹配器 + */ + private TypeMatcher typeMatcher; + + /** + * 类型转换器 + */ + private TypeConverter typeConverter; + + public TypeMatchInfo(Class valueType, Class targetType, TypeMatcher typeMatcher) { this.valueType = valueType; - this.notMatchingValue = TypeNotMatchingValueConstant.NOT; + this.targetType = targetType; + this.typeMatcher = typeMatcher; + this.typeDistance = TypeDistance.NOT; } public boolean isNotMatch() { - return TypeNotMatchingValueConstant.NOT == notMatchingValue; + return !isMatched(); + } + + public boolean isMatched() { + return TypeMatchLevel.byTypeDistance(this.typeDistance) != null && typeConverter != null; } } diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/type/TypeMatchLevel.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/type/TypeMatchLevel.java new file mode 100644 index 00000000..6eb15cc9 --- /dev/null +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/type/TypeMatchLevel.java @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2022 aoshiguchen + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package fun.asgc.neutrino.core.type; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * 类型匹配等级 + * @author: aoshiguchen + * @date: 2022/6/17 + */ +@Getter +@AllArgsConstructor +public enum TypeMatchLevel { + // 当且仅当匹配类为空(即匹配对象为null没有类型)时 + NULL(0, 0, 0, "空匹配"), + // 当且仅当匹配类与目标类完全相等 + PERFECT(1, 1, 1, "完美匹配"), + // 当且仅当匹配类为严格基本数据类型,且目标类为对应的包装类型 + PACKING(2, 100, 100, "装箱匹配"), + // 当且仅当目标类为严格基本数据类型,且匹配类为对应的包装类型 + UNPACKING(3, 200,200,"拆箱匹配"), + // 当且仅当匹配类和目标类均为一般基本数据类型(非严格),且目标类型的范围更加宽泛时 + ASCENSION(4, 1000, 2000, "类型提升匹配"), + // 超类匹配,当且仅当目标类是匹配类的超类时 + SUPER(5, 1000000, 2000000, "超类匹配"), + // 内置的扩展匹配 + EXTENSION(6, 10000000, 20000000, "扩展匹配"), + // 自定义匹配 + CUSTOM(7, 100000000, 200000000, "自定义匹配"); + private static Map levelMap = Stream.of(TypeMatchLevel.values()).collect(Collectors.toMap(TypeMatchLevel::getLevel, Function.identity())); + + private int level; + private int distanceMin; + private int distanceMax; + private String desc; + + public static TypeMatchLevel byLevel(int level) { + return levelMap.get(level); + } + + public static TypeMatchLevel byTypeDistance(int typeDistance) { + for (TypeMatchLevel item : values()) { + if (typeDistance >= item.getDistanceMin() && typeDistance <= item.getDistanceMax()) { + return item; + } + } + return null; + } +} diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/type/TypeMatcher.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/type/TypeMatcher.java new file mode 100644 index 00000000..3d82ea95 --- /dev/null +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/type/TypeMatcher.java @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2022 aoshiguchen + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package fun.asgc.neutrino.core.type; + +/** + * 值类型匹配器 + * + * @author: aoshiguchen + * @date: 2022/6/17 + */ +@FunctionalInterface +public interface TypeMatcher { + + /** + * 匹配 + * @param clazz + * @param targetClass + * @return + */ + TypeMatchInfo match(Class clazz, Class targetClass); + +} diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/type/TypeMatchers.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/type/TypeMatchers.java new file mode 100644 index 00000000..098b2818 --- /dev/null +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/type/TypeMatchers.java @@ -0,0 +1,244 @@ +/** + * Copyright (C) 2018-2022 Zeyi information technology (Shanghai) Co., Ltd. + *

+ * All right reserved. + *

+ * This software is the confidential and proprietary + * information of Zeyi Company of China. + * ("Confidential Information"). You shall not disclose + * such Confidential Information and shall use it only + * in accordance with the terms of the contract agreement + * you entered into with Zeyi inc. + */ +package fun.asgc.neutrino.core.type; + +import fun.asgc.neutrino.core.util.Assert; +import fun.asgc.neutrino.core.util.TypeUtil; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * + * @author: wen.y + * @date: 2022/6/17 + */ +public class TypeMatchers { + /** + * 默认的基本匹配器列表 + */ + private static List defaultTypeMatcherList = Collections.synchronizedList(new ArrayList<>()); + /** + * 默认内置扩展的匹配器列表 + */ + private static List extensionMatcherList = Collections.synchronizedList(new ArrayList<>()); + /** + * 用户自定义的匹配器列表 + */ + private List customTypeMatcherList = Collections.synchronizedList(new ArrayList<>()); + /** + * 是否启用内置扩展匹配器 + */ + private volatile boolean enableExtensionMatcher = true; + + static { + // 空匹配 + defaultTypeMatcherList.add(new TypeMatcher() { + @Override + public TypeMatchInfo match(Class clazz, Class targetClass) { + TypeMatchInfo matchInfo = new TypeMatchInfo(clazz, targetClass, this); + if (null == clazz) { + matchInfo.setTypeDistance(TypeMatchLevel.NULL.getDistanceMin()); + matchInfo.setTypeConverter((value, type) -> TypeUtil.getDefaultValue(type)); + } + return matchInfo; + } + }); + // 完美匹配 + defaultTypeMatcherList.add(new TypeMatcher() { + @Override + public TypeMatchInfo match(Class clazz, Class targetClass) { + TypeMatchInfo matchInfo = new TypeMatchInfo(clazz, targetClass, this); + if (clazz == targetClass) { + matchInfo.setTypeDistance(TypeMatchLevel.PERFECT.getDistanceMin()); + matchInfo.setTypeConverter((value, type) -> value); + } + return matchInfo; + } + }); + // 装箱匹配 + defaultTypeMatcherList.add(new TypeMatcher() { + @Override + public TypeMatchInfo match(Class clazz, Class targetClass) { + TypeMatchInfo matchInfo = new TypeMatchInfo(clazz, targetClass, this); + if (TypeUtil.isStrictBasicType(clazz) && TypeUtil.getWrapType(clazz) == targetClass) { + matchInfo.setTypeDistance(TypeMatchLevel.PACKING.getDistanceMin()); + matchInfo.setTypeConverter((value, type) -> value); + } + return matchInfo; + } + }); + // 拆箱匹配 + defaultTypeMatcherList.add(new TypeMatcher() { + @Override + public TypeMatchInfo match(Class clazz, Class targetClass) { + TypeMatchInfo matchInfo = new TypeMatchInfo(clazz, targetClass, this); + if (TypeUtil.isStrictBasicType(targetClass) && TypeUtil.getWrapType(targetClass) == clazz) { + matchInfo.setTypeDistance(TypeMatchLevel.UNPACKING.getDistanceMin()); + matchInfo.setTypeConverter((value, type) -> value); + } + return matchInfo; + } + }); + // 类型提升匹配 + defaultTypeMatcherList.add(new TypeMatcher() { + @Override + public TypeMatchInfo match(Class clazz, Class targetClass) { + TypeMatchInfo matchInfo = new TypeMatchInfo(clazz, targetClass, this); + int index1 = TypeUtil.basicTypeList.indexOf(clazz); + int index2 = TypeUtil.basicTypeList.indexOf(targetClass); + if (index2 > index1 && index1 >= 0) { + matchInfo.setTypeDistance(TypeMatchLevel.ASCENSION.getDistanceMin() + (index2 - index1)); + matchInfo.setTypeConverter((value, type) -> { + if (value == type || TypeUtil.getWrapType(value.getClass()) == type) { + return value; + } + if (TypeUtil.isBoolean(value.getClass())) { + return ((boolean)value) ? 1 : 0; + } + if (TypeUtil.isBoolean(type)) { + return TypeUtil.isChar(value.getClass()) ? ((char)value == 0 ? false : true) : + (((Number)value).intValue() == 0 ? false : true); + } + if (TypeUtil.isChar(type)) { + return (char)(int)value; + } + return value; + }); + } + return matchInfo; + } + }); + // 超类匹配 + defaultTypeMatcherList.add(new TypeMatcher() { + @Override + public TypeMatchInfo match(Class clazz, Class targetClass) { + TypeMatchInfo matchInfo = new TypeMatchInfo(clazz, targetClass, this); + if (targetClass.isAssignableFrom(clazz)) { + int level = TypeUtil.getInheritLevel(targetClass, clazz); + matchInfo.setTypeDistance(TypeMatchLevel.SUPER.getDistanceMin() + level); + matchInfo.setTypeConverter((value, type) -> value); + } + return matchInfo; + } + }); + // 内置扩展匹配 -------- + // 字符串 + extensionMatcherList.add(new TypeMatcher() { + @Override + public TypeMatchInfo match(Class clazz, Class targetClass) { + TypeMatchInfo matchInfo = new TypeMatchInfo(clazz, targetClass, this); + if (TypeUtil.isNormalBasicType(clazz) && targetClass == String.class) { + matchInfo.setTypeDistance(TypeMatchLevel.EXTENSION.getDistanceMin() + 10); + matchInfo.setTypeConverter(((value, targetType) -> String.valueOf(value))); + } + return matchInfo; + } + }); + // 日期1 + extensionMatcherList.add(new TypeMatcher() { + @Override + public TypeMatchInfo match(Class clazz, Class targetClass) { + TypeMatchInfo matchInfo = new TypeMatchInfo(clazz, targetClass, this); + if (TypeUtil.isLong(clazz) && TypeUtil.isDate(targetClass)) { + matchInfo.setTypeDistance(TypeMatchLevel.EXTENSION.getDistanceMin() + 20); + matchInfo.setTypeConverter(((value, targetType) -> { + if (targetClass == java.util.Date.class) { + return new java.util.Date((long)value); + } else { + return new java.sql.Date((long)value); + } + })); + } + return matchInfo; + } + }); + // 日期2 + extensionMatcherList.add(new TypeMatcher() { + @Override + public TypeMatchInfo match(Class clazz, Class targetClass) { + TypeMatchInfo matchInfo = new TypeMatchInfo(clazz, targetClass, this); + if (TypeUtil.isLong(targetClass) && TypeUtil.isDate(clazz)) { + matchInfo.setTypeDistance(TypeMatchLevel.EXTENSION.getDistanceMin() + 30); + matchInfo.setTypeConverter(((value, targetType) -> ((java.util.Date)value).getTime())); + } + return matchInfo; + } + }); + } + + /** + * 注册自定义类型匹配器具 + * @param typeMatcher + */ + public void registerCustomTypeMatcher(TypeMatcher typeMatcher) { + customTypeMatcherList.add(typeMatcher); + } + + /** + * 匹配 + * @param clazz + * @param targetClass + * @return + */ + public TypeMatchInfo match(Class clazz, Class targetClass) { + // 先匹配自定义的 + for (TypeMatcher matcher : customTypeMatcherList) { + TypeMatchInfo typeMatchInfo = matcher.match(clazz, targetClass); + if (typeMatchInfo.isMatched()) { + return typeMatchInfo; + } + } + // 再匹配内置默认的 + for (TypeMatcher matcher : defaultTypeMatcherList) { + TypeMatchInfo typeMatchInfo = matcher.match(clazz, targetClass); + if (typeMatchInfo.isMatched()) { + return typeMatchInfo; + } + } + if (enableExtensionMatcher) { + // 再匹配内置扩展的 + for (TypeMatcher matcher : extensionMatcherList) { + TypeMatchInfo typeMatchInfo = matcher.match(clazz, targetClass); + if (typeMatchInfo.isMatched()) { + return typeMatchInfo; + } + } + } + return null; + } + + public boolean isEnableExtensionMatcher() { + return enableExtensionMatcher; + } + + public void setEnableExtensionMatcher(boolean enableExtensionMatcher) { + this.enableExtensionMatcher = enableExtensionMatcher; + } + + /** + * 类型转换 + * @param value + * @param targetType + * @return + */ + public Object conversion(Object value, Class targetType) { + Assert.notNull(targetType, "目标类型不能为空!"); + TypeMatchInfo typeMatchInfo = match(value == null ? null : value.getClass(), targetType); + if (null == typeMatchInfo || typeMatchInfo.isNotMatch()) { + return null; + } + return typeMatchInfo.getTypeConverter().convert(value, targetType); + } +} diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/util/ReflectUtil.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/util/ReflectUtil.java index 1fc437cf..85c2a7ca 100644 --- a/neutrino-core/src/main/java/fun/asgc/neutrino/core/util/ReflectUtil.java +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/util/ReflectUtil.java @@ -25,13 +25,12 @@ package fun.asgc.neutrino.core.util; import com.google.common.collect.Sets; import fun.asgc.neutrino.core.cache.Cache; import fun.asgc.neutrino.core.cache.MemoryCache; -import fun.asgc.neutrino.core.constant.TypeNotMatchingValueConstant; +import fun.asgc.neutrino.core.type.TypeDistance; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.*; import java.util.function.Function; -import java.util.stream.Collectors; import java.util.stream.Stream; /** @@ -208,18 +207,18 @@ public class ReflectUtil { if (methodOptional.isPresent()) { return methodOptional.get(); } - int level = TypeNotMatchingValueConstant.MAX; + int level = TypeDistance.MAX; Method method = null; for (Method m : getMethods(field.getDeclaringClass())) { if (m.getName().equals(setMethodName) && m.getParameters().length == 1) { - int curLevel = TypeUtil.typeMatch(m.getParameterTypes()[0], field.getType()).getNotMatchingValue(); + int curLevel = TypeUtil.typeMatch(m.getParameterTypes()[0], field.getType()).getTypeDistance(); if (curLevel < level) { level = curLevel; method = m; } } } - if (level < TypeNotMatchingValueConstant.MAX && method != null) { + if (level < TypeDistance.MAX && method != null) { return method; } return null; diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/util/TypeUtil.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/util/TypeUtil.java index c32a3134..582c30b1 100644 --- a/neutrino-core/src/main/java/fun/asgc/neutrino/core/util/TypeUtil.java +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/util/TypeUtil.java @@ -23,13 +23,12 @@ package fun.asgc.neutrino.core.util; import com.google.common.collect.Lists; -import com.google.common.collect.Sets; -import fun.asgc.neutrino.core.constant.TypeNotMatchingValueConstant; +import fun.asgc.neutrino.core.type.TypeMatchInfo; +import fun.asgc.neutrino.core.type.TypeMatchers; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.*; -import java.util.stream.Collectors; /** * @@ -53,6 +52,7 @@ public class TypeUtil { this.add(boolean.class); } }; + /** * 一般意义上的基本数据类型 */ @@ -130,6 +130,26 @@ public class TypeUtil { Boolean.class, Byte.class, Short.class, Character.class, Integer.class, Long.class, Float.class, Double.class ); + /** + * 默认值 + */ + private static final Map, Object> defaultValueMap = new HashMap, Object>() { + { + this.put(byte.class, 0); + this.put(short.class, 0); + this.put(int.class, 0); + this.put(long.class, 0); + this.put(float.class, 0); + this.put(double.class, 0); + this.put(char.class, 0); + this.put(boolean.class, false); + } + }; + + /** + * 默认的类型匹配器 + */ + private static final TypeMatchers defaultTypeMatchers = new TypeMatchers(); /** * 获取字段类型 @@ -177,6 +197,15 @@ public class TypeUtil { return normalBasicType.contains(clazz); } + /** + * 是否是数字 + * @param clazz + * @return + */ + public static boolean isNumber(Class clazz) { + return Number.class.isAssignableFrom(clazz); + } + /** * 是否是一般基本类型 * @param field @@ -240,7 +269,15 @@ public class TypeUtil { * @return */ public static boolean isLong(Field field) { - Class clazz = getFieldType(field); + return isLong(getFieldType(field)); + } + + /** + * 是否是long类型 + * @param clazz + * @return + */ + public static boolean isLong(Class clazz) { return clazz == long.class || clazz == Long.class; } @@ -294,6 +331,24 @@ public class TypeUtil { return clazz == String.class; } + /** + * 是否是日期类型 + * @param field + * @return + */ + public static boolean isDate(Field field) { + return isDate(getFieldType(field)); + } + + /** + * 是否是日期类型 + * @param clazz + * @return + */ + public static boolean isDate(Class clazz) { + return clazz == java.util.Date.class || clazz == java.sql.Date.class; + } + /** * 是否是布尔值 * @param clazz @@ -371,8 +426,18 @@ public class TypeUtil { return name.substring(0, 1).toLowerCase() + name.substring(1); } + /** + * 获取默认值 + * @param clazz + * @return + */ + public static Object getDefaultValue(Class clazz) { + return defaultValueMap.get(clazz); + } + /** * 获取继承层级 + * 此处假定继承层级最多为100层,避免计算太过耗时 * @param superClass * @param childClass * @return @@ -383,7 +448,7 @@ public class TypeUtil { } List, Integer>> list = new LinkedList<>(); list.add(Pair.of(childClass, 0)); - while (CollectionUtil.notEmpty(list) && list.get(0).getFirst() != superClass && list.get(0).getSecond() < TypeNotMatchingValueConstant.SUPER_CLASS_MAX) { + while (CollectionUtil.notEmpty(list) && list.get(0).getFirst() != superClass && list.get(0).getSecond() < 100) { Pair, Integer> current = list.remove(0); Class clazz = current.getFirst(); int level = current.getSecond(); @@ -397,9 +462,9 @@ public class TypeUtil { } } if (list.isEmpty()) { - return TypeNotMatchingValueConstant.SUPER_CLASS_MAX; + return 100; } - return Math.min(list.get(0).getSecond(), TypeNotMatchingValueConstant.SUPER_CLASS_MAX); + return Math.min(list.get(0).getSecond(), 100); } /** @@ -408,79 +473,79 @@ public class TypeUtil { * @param valueType * @return */ - public static TypeMatchingInfo typeMatch(Class fieldType, Class valueType) { + public static TypeMatchInfo typeMatch(Class fieldType, Class valueType) { Assert.notNull(fieldType, "字段类型不能为空!"); Assert.notNull(valueType, "值类型不能为空!"); - // 1、完全匹配 - if (fieldType == valueType) { - return new TypeMatchingInfo(fieldType, valueType, TypeNotMatchingValueConstant.COMPLETE); - } - // 2、包装匹配 - if (isStrictBasicType(valueType) && getWrapType(valueType) == fieldType) { - return new TypeMatchingInfo(fieldType, valueType, TypeNotMatchingValueConstant.WRAP); - } - // 3、解包装匹配 - if (isStrictBasicType(fieldType) && getWrapType(fieldType) == valueType) { - return new TypeMatchingInfo(fieldType, valueType, TypeNotMatchingValueConstant.UNWRAP); - } - // 4、超类匹配 - if (fieldType.isAssignableFrom(valueType)) { - int inheritLevel = getInheritLevel(fieldType, valueType); - if (-1 == inheritLevel) { - throw new RuntimeException(String.format("超类匹配异常! fieldType:%s valueType:%s", fieldType.getName(), valueType.getName())); - } - return new TypeMatchingInfo(fieldType, valueType, TypeNotMatchingValueConstant.SUPER_CLASS_MIN + inheritLevel - 1); - } - // 5、类型提升 - if (isNormalBasicType(fieldType) && isNormalBasicType(valueType)) { - int index1 = basicTypeList.indexOf(fieldType); - int index2 = basicTypeList.indexOf(valueType); - if (index1 > index2 && index2 > 0) { - return new TypeMatchingInfo(fieldType, valueType, TypeNotMatchingValueConstant.ASCENSION_MIN + (index1 - index2) - 1); - } - } - // 6、自定义转换 - if (fieldType == Date.class || fieldType == java.sql.Date.class) { - if (valueType == long.class) { - return new TypeMatchingInfo(fieldType, valueType, TypeNotMatchingValueConstant.CUSTOM_MIN); - } else if (valueType == long.class) { - return new TypeMatchingInfo(fieldType, valueType, TypeNotMatchingValueConstant.CUSTOM_MIN + 1); - } - } - if (fieldType == Long.class || fieldType == long.class) { - if (valueType == Date.class) { - return new TypeMatchingInfo(fieldType, valueType, TypeNotMatchingValueConstant.CUSTOM_MIN + 1000); - } else if (valueType == java.sql.Date.class) { - return new TypeMatchingInfo(fieldType, valueType, TypeNotMatchingValueConstant.CUSTOM_MIN + 1001); - } - } - if (fieldType == String.class) { - if (valueType == char.class) { - return new TypeMatchingInfo(fieldType, valueType, TypeNotMatchingValueConstant.CUSTOM_MIN + 2000); - } else if (valueType == Character.class) { - return new TypeMatchingInfo(fieldType, valueType, TypeNotMatchingValueConstant.CUSTOM_MIN + 2001); - } else if (Number.class.isAssignableFrom(valueType)) { - return new TypeMatchingInfo(fieldType, valueType, TypeNotMatchingValueConstant.CUSTOM_MIN + 2002); - } - } - if (Iterable.class.isAssignableFrom(fieldType) && Iterable.class.isAssignableFrom(valueType)) { - return new TypeMatchingInfo(fieldType, valueType, TypeNotMatchingValueConstant.CUSTOM_MIN + 3000); - } - if (Iterable.class.isAssignableFrom(fieldType) && String[].class == valueType) { - return new TypeMatchingInfo(fieldType, valueType, TypeNotMatchingValueConstant.CUSTOM_MIN + 4000); - } - if (Iterable.class.isAssignableFrom(valueType) && String[].class == fieldType) { - return new TypeMatchingInfo(fieldType, valueType, TypeNotMatchingValueConstant.CUSTOM_MIN + 5000); - } - if (Iterable.class.isAssignableFrom(fieldType) && Integer[].class == valueType) { - return new TypeMatchingInfo(fieldType, valueType, TypeNotMatchingValueConstant.CUSTOM_MIN + 6000); - } - if (Iterable.class.isAssignableFrom(valueType) && Integer[].class == fieldType) { - return new TypeMatchingInfo(fieldType, valueType, TypeNotMatchingValueConstant.CUSTOM_MIN + 7000); - } +// // 1、完全匹配 +// if (fieldType == valueType) { +// return new TypeMatchInfo(fieldType, valueType, TypeDistance.PERFECT); +// } +// // 2、包装匹配 +// if (isStrictBasicType(valueType) && getWrapType(valueType) == fieldType) { +// return new TypeMatchInfo(fieldType, valueType, TypeDistance.PACKING); +// } +// // 3、解包装匹配 +// if (isStrictBasicType(fieldType) && getWrapType(fieldType) == valueType) { +// return new TypeMatchInfo(fieldType, valueType, TypeDistance.UNPACKING); +// } +// // 4、类型提升 +// if (isNormalBasicType(fieldType) && isNormalBasicType(valueType)) { +// int index1 = basicTypeList.indexOf(fieldType); +// int index2 = basicTypeList.indexOf(valueType); +// if (index1 > index2 && index2 > 0) { +// return new TypeMatchInfo(fieldType, valueType, TypeDistance.ASCENSION_MIN + (index1 - index2) - 1); +// } +// } +// // 5、超类匹配 +// if (fieldType.isAssignableFrom(valueType)) { +// int inheritLevel = getInheritLevel(fieldType, valueType); +// if (-1 == inheritLevel) { +// throw new RuntimeException(String.format("超类匹配异常! fieldType:%s valueType:%s", fieldType.getName(), valueType.getName())); +// } +// return new TypeMatchInfo(fieldType, valueType, TypeDistance.SUPER_MIN + inheritLevel - 1); +// } +// // 6、自定义转换 +// if (fieldType == Date.class || fieldType == java.sql.Date.class) { +// if (valueType == long.class) { +// return new TypeMatchInfo(fieldType, valueType, TypeDistance.CUSTOM_MIN); +// } else if (valueType == long.class) { +// return new TypeMatchInfo(fieldType, valueType, TypeDistance.CUSTOM_MIN + 1); +// } +// } +// if (fieldType == Long.class || fieldType == long.class) { +// if (valueType == Date.class) { +// return new TypeMatchInfo(fieldType, valueType, TypeDistance.CUSTOM_MIN + 1000); +// } else if (valueType == java.sql.Date.class) { +// return new TypeMatchInfo(fieldType, valueType, TypeDistance.CUSTOM_MIN + 1001); +// } +// } +// if (fieldType == String.class) { +// if (valueType == char.class) { +// return new TypeMatchInfo(fieldType, valueType, TypeDistance.CUSTOM_MIN + 2000); +// } else if (valueType == Character.class) { +// return new TypeMatchInfo(fieldType, valueType, TypeDistance.CUSTOM_MIN + 2001); +// } else if (Number.class.isAssignableFrom(valueType)) { +// return new TypeMatchInfo(fieldType, valueType, TypeDistance.CUSTOM_MIN + 2002); +// } +// } +// if (Iterable.class.isAssignableFrom(fieldType) && Iterable.class.isAssignableFrom(valueType)) { +// return new TypeMatchInfo(fieldType, valueType, TypeDistance.CUSTOM_MIN + 3000); +// } +// if (Iterable.class.isAssignableFrom(fieldType) && String[].class == valueType) { +// return new TypeMatchInfo(fieldType, valueType, TypeDistance.CUSTOM_MIN + 4000); +// } +// if (Iterable.class.isAssignableFrom(valueType) && String[].class == fieldType) { +// return new TypeMatchInfo(fieldType, valueType, TypeDistance.CUSTOM_MIN + 5000); +// } +// if (Iterable.class.isAssignableFrom(fieldType) && Integer[].class == valueType) { +// return new TypeMatchInfo(fieldType, valueType, TypeDistance.CUSTOM_MIN + 6000); +// } +// if (Iterable.class.isAssignableFrom(valueType) && Integer[].class == fieldType) { +// return new TypeMatchInfo(fieldType, valueType, TypeDistance.CUSTOM_MIN + 7000); +// } - return new TypeMatchingInfo(fieldType, valueType); + return new TypeMatchInfo(fieldType, valueType, null); } /** @@ -533,55 +598,65 @@ public class TypeUtil { * @return */ public static Object conversion(Object value, Class targetType) { - Assert.notNull(targetType, "目标类型不能为空!"); - if (null == value) { - return null; - } - Class valueType = value.getClass(); - TypeMatchingInfo matchingInfo = typeMatch(targetType, valueType); - if (matchingInfo.isNotMatch()) { - return null; - } - // 超类 - if (matchingInfo.getNotMatchingValue() <= TypeNotMatchingValueConstant.SUPER_CLASS_MAX) { - return value; - } - // 类型提升 - if (matchingInfo.getNotMatchingValue() <= TypeNotMatchingValueConstant.ASCENSION_MAX) { - return TypeUtil.ascensionType(value, targetType); - } - if (matchingInfo.getNotMatchingValue() >= TypeNotMatchingValueConstant.CUSTOM_MIN && matchingInfo.getNotMatchingValue() <= TypeNotMatchingValueConstant.CUSTOM_MAX) { - // 自定义转换 - if (targetType == Date.class) { - if (valueType == long.class || value == Long.class) { - return new Date((Long) value); - } - } else if (targetType == java.sql.Date.class) { - if (valueType == long.class || value == Long.class) { - return new java.sql.Date((Long) value); - } - } else if (targetType == Long.class || targetType == long.class) { - if (valueType == java.sql.Date.class || valueType == Date.class) { - return ((Date) value).getTime(); - } - } else if (targetType == String.class) { - if (valueType == char.class || valueType == Character.class || Number.class.isAssignableFrom(valueType)) { - return String.valueOf(value); - } - } else if (Iterable.class.isAssignableFrom(targetType) && Iterable.class.isAssignableFrom(valueType)) { - if (Set.class.isAssignableFrom(targetType)) { - return Sets.newHashSet((Iterable) value); - } - } else if (Iterable.class.isAssignableFrom(valueType) && String[].class == targetType) { - if (List.class.isAssignableFrom(valueType)) { - return ((List) value).stream().map(String::valueOf).collect(Collectors.toList()).toArray(new String[]{}); - } - } else if (Iterable.class.isAssignableFrom(valueType) && Integer[].class == targetType) { - if (List.class.isAssignableFrom(valueType)) { - return ((List) value).stream().map(String::valueOf).map(Integer::valueOf).collect(Collectors.toList()).toArray(new Integer[]{}); - } - } - } - return null; + return defaultTypeMatchers.conversion(value, targetType); } + +// /** +// * 类型转换 +// * @param value +// * @param targetType +// * @return +// */ +// public static Object conversion(Object value, Class targetType) { +// Assert.notNull(targetType, "目标类型不能为空!"); +// if (null == value) { +// return null; +// } +// Class valueType = value.getClass(); +// TypeMatchInfo matchingInfo = typeMatch(targetType, valueType); +// if (matchingInfo.isNotMatch()) { +// return null; +// } +// // 类型提升 +// if (matchingInfo.getTypeDistance() <= TypeDistance.ASCENSION_MAX) { +// return TypeUtil.ascensionType(value, targetType); +// } +// // 超类 +// if (matchingInfo.getTypeDistance() <= TypeDistance.SUPER_MAX) { +// return value; +// } +// if (matchingInfo.getTypeDistance() >= TypeDistance.CUSTOM_MIN && matchingInfo.getTypeDistance() <= TypeDistance.CUSTOM_MAX) { +// // 自定义转换 +// if (targetType == Date.class) { +// if (valueType == long.class || value == Long.class) { +// return new Date((Long) value); +// } +// } else if (targetType == java.sql.Date.class) { +// if (valueType == long.class || value == Long.class) { +// return new java.sql.Date((Long) value); +// } +// } else if (targetType == Long.class || targetType == long.class) { +// if (valueType == java.sql.Date.class || valueType == Date.class) { +// return ((Date) value).getTime(); +// } +// } else if (targetType == String.class) { +// if (valueType == char.class || valueType == Character.class || Number.class.isAssignableFrom(valueType)) { +// return String.valueOf(value); +// } +// } else if (Iterable.class.isAssignableFrom(targetType) && Iterable.class.isAssignableFrom(valueType)) { +// if (Set.class.isAssignableFrom(targetType)) { +// return Sets.newHashSet((Iterable) value); +// } +// } else if (Iterable.class.isAssignableFrom(valueType) && String[].class == targetType) { +// if (List.class.isAssignableFrom(valueType)) { +// return ((List) value).stream().map(String::valueOf).collect(Collectors.toList()).toArray(new String[]{}); +// } +// } else if (Iterable.class.isAssignableFrom(valueType) && Integer[].class == targetType) { +// if (List.class.isAssignableFrom(valueType)) { +// return ((List) value).stream().map(String::valueOf).map(Integer::valueOf).collect(Collectors.toList()).toArray(new Integer[]{}); +// } +// } +// } +// return null; +// } } diff --git a/neutrino-core/src/test/java/fun/asgc/neutrino/core/util/TypeUtilTest.java b/neutrino-core/src/test/java/fun/asgc/neutrino/core/util/TypeUtilTest.java new file mode 100644 index 00000000..ed2349de --- /dev/null +++ b/neutrino-core/src/test/java/fun/asgc/neutrino/core/util/TypeUtilTest.java @@ -0,0 +1,150 @@ +/** + * Copyright (C) 2018-2022 Zeyi information technology (Shanghai) Co., Ltd. + *

+ * All right reserved. + *

+ * This software is the confidential and proprietary + * information of Zeyi Company of China. + * ("Confidential Information"). You shall not disclose + * such Confidential Information and shall use it only + * in accordance with the terms of the contract agreement + * you entered into with Zeyi inc. + */ +package fun.asgc.neutrino.core.util; + +import fun.asgc.neutrino.core.type.*; +import lombok.Data; +import lombok.experimental.Accessors; +import org.junit.Test; + +/** + * + * @author: wen.y + * @date: 2022/6/17 + */ +public class TypeUtilTest { + + private static TypeMatchers typeMatchers = new TypeMatchers(); + + static { + typeMatchers.registerCustomTypeMatcher(new TypeMatcher() { + @Override + public TypeMatchInfo match(Class clazz, Class targetClass) { + TypeMatchInfo typeMatchInfo = new TypeMatchInfo(clazz, targetClass, this); + if (clazz == String.class && targetClass == Animal.class) { + typeMatchInfo.setTypeDistance(TypeDistance.CUSTOM_MIN); + typeMatchInfo.setTypeConverter(((value, targetType) -> new Animal().setName((String)value))); + } + return typeMatchInfo; + } + }); + typeMatchers.registerCustomTypeMatcher(new TypeMatcher() { + @Override + public TypeMatchInfo match(Class clazz, Class targetClass) { + TypeMatchInfo typeMatchInfo = new TypeMatchInfo(clazz, targetClass, this); + if (clazz == String.class && targetClass == Cat.class) { + typeMatchInfo.setTypeDistance(TypeDistance.CUSTOM_MIN); + typeMatchInfo.setTypeConverter((value, targetType) -> { + String[] tmp = ((String)value).split(":"); + Cat cat = new Cat(); + if (tmp.length >= 1) { + cat.setName(tmp[0]); + } + if (tmp.length >= 2) { + cat.setAge(Integer.valueOf(tmp[1])); + } + return cat; + }); + } + return typeMatchInfo; + } + }); + } + + @Test + public void conversionNull() { + System.out.println(typeMatchers.conversion(null, boolean.class)); + System.out.println(typeMatchers.conversion(null, byte.class)); + System.out.println(typeMatchers.conversion(null, short.class)); + System.out.println(typeMatchers.conversion(null, char.class)); + System.out.println(typeMatchers.conversion(null, int.class)); + System.out.println(typeMatchers.conversion(null, long.class)); + System.out.println(typeMatchers.conversion(null, float.class)); + System.out.println(typeMatchers.conversion(null, double.class)); + System.out.println(typeMatchers.conversion(null, Boolean.class)); + System.out.println(typeMatchers.conversion(null, Byte.class)); + System.out.println(typeMatchers.conversion(null, Short.class)); + System.out.println(typeMatchers.conversion(null, Character.class)); + System.out.println(typeMatchers.conversion(null, Integer.class)); + System.out.println(typeMatchers.conversion(null, Long.class)); + System.out.println(typeMatchers.conversion(null, Float.class)); + System.out.println(typeMatchers.conversion(null, Double.class)); + System.out.println(typeMatchers.conversion(null, String.class)); + + System.out.println(typeMatchers.conversion(null, Animal.class)); + System.out.println(typeMatchers.conversion(null, Cat.class)); + } + + @Test + public void conversionString() { + System.out.println(typeMatchers.conversion("aabb", boolean.class)); + System.out.println(typeMatchers.conversion("aabb", byte.class)); + System.out.println(typeMatchers.conversion("aabb", short.class)); + System.out.println(typeMatchers.conversion("aabb", char.class)); + System.out.println(typeMatchers.conversion("aabb", int.class)); + System.out.println(typeMatchers.conversion("aabb", long.class)); + System.out.println(typeMatchers.conversion("aabb", float.class)); + System.out.println(typeMatchers.conversion("aabb", double.class)); + System.out.println(typeMatchers.conversion("aabb", Boolean.class)); + System.out.println(typeMatchers.conversion("aabb", Byte.class)); + System.out.println(typeMatchers.conversion("aabb", Short.class)); + System.out.println(typeMatchers.conversion("aabb", Character.class)); + System.out.println(typeMatchers.conversion("aabb", Integer.class)); + System.out.println(typeMatchers.conversion("aabb", Long.class)); + System.out.println(typeMatchers.conversion("aabb", Float.class)); + System.out.println(typeMatchers.conversion("aabb", Double.class)); + System.out.println(typeMatchers.conversion("aabb", String.class)); + + System.out.println(typeMatchers.conversion("aabb", Animal.class)); + System.out.println(typeMatchers.conversion("aabb:10", Cat.class)); + } + + @Test + public void conversionInt() { + typeMatchers.setEnableExtensionMatcher(false); + + System.out.println(typeMatchers.conversion(100, boolean.class)); + System.out.println(typeMatchers.conversion(101, byte.class)); + System.out.println(typeMatchers.conversion(102, short.class)); + System.out.println(typeMatchers.conversion(103, char.class)); + System.out.println(typeMatchers.conversion(104, int.class)); + System.out.println(typeMatchers.conversion(105, long.class)); + System.out.println(typeMatchers.conversion(106, float.class)); + System.out.println(typeMatchers.conversion(107, double.class)); + System.out.println(typeMatchers.conversion(108, Boolean.class)); + System.out.println(typeMatchers.conversion(109, Byte.class)); + System.out.println(typeMatchers.conversion(110, Short.class)); + System.out.println(typeMatchers.conversion(111, Character.class)); + System.out.println(typeMatchers.conversion(112, Integer.class)); + System.out.println(typeMatchers.conversion(113, Long.class)); + System.out.println(typeMatchers.conversion(114, Float.class)); + System.out.println(typeMatchers.conversion(115, Double.class)); + System.out.println(typeMatchers.conversion(116, String.class)); + + System.out.println(typeMatchers.conversion(117, Animal.class)); + System.out.println(typeMatchers.conversion(118, Cat.class)); + } + + + @Accessors(chain = true) + @Data + public static class Animal { + private String name; + } + + @Accessors(chain = true) + @Data + private static class Cat extends Animal { + private int age; + } +}