优化底层类型转换逻辑封装,支持自定义扩展.

This commit is contained in:
aoshiguchen
2022-06-17 20:11:41 +08:00
parent 3779fc5072
commit dc04fe2fde
10 changed files with 813 additions and 176 deletions
+2
View File
@@ -22,3 +22,5 @@
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
**/*.iml
@@ -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);
}
@@ -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();
}
@@ -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;
}
}
@@ -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<Integer,TypeMatchLevel> 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;
}
}
@@ -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);
}
@@ -0,0 +1,244 @@
/**
* Copyright (C) 2018-2022 Zeyi information technology (Shanghai) Co., Ltd.
* <p>
* All right reserved.
* <p>
* 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<TypeMatcher> defaultTypeMatcherList = Collections.synchronizedList(new ArrayList<>());
/**
* 默认内置扩展的匹配器列表
*/
private static List<TypeMatcher> extensionMatcherList = Collections.synchronizedList(new ArrayList<>());
/**
* 用户自定义的匹配器列表
*/
private List<TypeMatcher> 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);
}
}
@@ -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;
@@ -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<Class<?>, Object> defaultValueMap = new HashMap<Class<?>, 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<Pair<Class<?>, 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<Class<?>, 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<Object>) 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<Object>) 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<Object>) 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<Object>) value).stream().map(String::valueOf).map(Integer::valueOf).collect(Collectors.toList()).toArray(new Integer[]{});
// }
// }
// }
// return null;
// }
}
@@ -0,0 +1,150 @@
/**
* Copyright (C) 2018-2022 Zeyi information technology (Shanghai) Co., Ltd.
* <p>
* All right reserved.
* <p>
* 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;
}
}