内置扩展匹配器相关结构优化

This commit is contained in:
aoshiguchen
2022-06-29 16:33:24 +08:00
parent 580a713161
commit 01b078231d
12 changed files with 851 additions and 259 deletions
@@ -0,0 +1,49 @@
/**
* 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 java.util.List;
/**
* 匹配器组
* @author: aoshiguchen
* @date: 2022/6/29
*/
public interface TypeMatcherGroup {
/**
* 匹配器列表
* @return
*/
List<TypeMatcher> matchers();
/**
* 获取最小距离
* @return
*/
int getDistanceMin();
/**
* 获取最大距离
* @return
*/
int getDistanceMax();
}
@@ -21,16 +21,13 @@
*/
package fun.asgc.neutrino.core.type;
import fun.asgc.neutrino.core.type.extension.*;
import fun.asgc.neutrino.core.util.Assert;
import fun.asgc.neutrino.core.util.StringUtil;
import fun.asgc.neutrino.core.util.CollectionUtil;
import fun.asgc.neutrino.core.util.TypeUtil;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
*
@@ -41,21 +38,122 @@ public class TypeMatchers {
/**
* 默认的基本匹配器列表
*/
private static List<TypeMatcher> defaultTypeMatcherList = Collections.synchronizedList(new ArrayList<>());
private static List<TypeMatcher> defaultTypeMatcherList = new ArrayList<>();
/**
* 默认内置扩展的匹配器列表
*/
private static List<TypeMatcher> extensionMatcherList = Collections.synchronizedList(new ArrayList<>());
private static List<TypeMatcher> extensionMatcherList = new ArrayList<>();
/**
* 内置扩展匹配器组列表
*/
private static List<TypeMatcherGroup> extensionMatcherGroupList = new ArrayList<>();
/**
* 用户自定义的匹配器列表
*/
private List<TypeMatcher> customTypeMatcherList = Collections.synchronizedList(new ArrayList<>());
private List<TypeMatcher> customTypeMatcherList = new ArrayList<>();
/**
* 是否启用内置扩展匹配器
*/
private volatile boolean enableExtensionMatcher = true;
static {
init();
}
/**
* 注册自定义类型匹配器具
* @param typeMatcher
*/
public synchronized void registerCustomTypeMatcher(TypeMatcher typeMatcher) {
customTypeMatcherList.add(typeMatcher);
}
/**
* 注册内置扩展匹配器组
* @param typeMatcherGroup
*/
public static synchronized void registerExtensionTypeMatcher(TypeMatcherGroup typeMatcherGroup) {
if (null == typeMatcherGroup || CollectionUtil.isEmpty(typeMatcherGroup.matchers())) {
return;
}
// 内置扩展匹配器距离区间检测
if (typeMatcherGroup.getDistanceMin() < TypeMatchLevel.EXTENSION.getDistanceMin() ||
typeMatcherGroup.getDistanceMax() > TypeMatchLevel.EXTENSION.getDistanceMax() ||
typeMatcherGroup.getDistanceMax() < typeMatcherGroup.getDistanceMin()) {
throw new RuntimeException(String.format("内置扩展器:[%s] 距离区间定义有误!", typeMatcherGroup.getClass().getSimpleName()));
}
for (TypeMatcherGroup group : extensionMatcherGroupList) {
// 距离区间不能重叠
if (!(typeMatcherGroup.getDistanceMin() > group.getDistanceMax() || typeMatcherGroup.getDistanceMax() < group.getDistanceMin())) {
throw new RuntimeException(String.format("内置扩展器:[%s]与[%s] 距离区间定义有重叠!", typeMatcherGroup.getClass().getSimpleName(), group.getClass().getSimpleName()));
}
}
extensionMatcherGroupList.add(typeMatcherGroup);
// 按照距离区间排序
extensionMatcherList = extensionMatcherGroupList.stream().sorted(Comparator.comparing(TypeMatcherGroup::getDistanceMin))
.map(TypeMatcherGroup::matchers).flatMap(List::stream).collect(Collectors.toList());
}
/**
* 匹配
* @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);
}
/**
* 初始化
*/
private static void init() {
// 空匹配
defaultTypeMatcherList.add(new TypeMatcher() {
@Override
@@ -149,258 +247,27 @@ public class TypeMatchers {
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() + 100);
matchInfo.setTypeConverter(((value, targetType) -> String.valueOf(value)));
}
if (TypeUtil.isChar(targetClass) && TypeUtil.isString(clazz)) {
matchInfo.setTypeDistance(TypeMatchLevel.EXTENSION.getDistanceMin() + 101);
matchInfo.setTypeConverter(((value, targetType) -> ((String)value).charAt(0)));
}
return matchInfo;
}
});
// Boolean
extensionMatcherList.add(new TypeMatcher() {
@Override
public TypeMatchInfo match(Class<?> clazz, Class<?> targetClass) {
TypeMatchInfo matchInfo = new TypeMatchInfo(clazz, targetClass, this);
if (TypeUtil.isString(clazz) && TypeUtil.isBoolean(targetClass)) {
matchInfo.setTypeDistance(TypeMatchLevel.EXTENSION.getDistanceMin() + 110);
matchInfo.setTypeConverter(((value, targetType) -> ((String)value).toLowerCase().equals("true")));
}
return matchInfo;
}
});
// Number
extensionMatcherList.add(new TypeMatcher() {
@Override
public TypeMatchInfo match(Class<?> clazz, Class<?> targetClass) {
TypeMatchInfo matchInfo = new TypeMatchInfo(clazz, targetClass, this);
if (TypeUtil.isString(clazz) && TypeUtil.isByte(targetClass)) {
matchInfo.setTypeDistance(TypeMatchLevel.EXTENSION.getDistanceMin() + 111);
matchInfo.setTypeConverter((value, targetType) -> {
try {
return Byte.valueOf((String)value);
} catch (Exception e) {
// ignore
}
return 0;
});
}
if (TypeUtil.isString(clazz) && TypeUtil.isShort(targetClass)) {
matchInfo.setTypeDistance(TypeMatchLevel.EXTENSION.getDistanceMin() + 112);
matchInfo.setTypeConverter((value, targetType) -> {
try {
return Short.valueOf((String)value);
} catch (Exception e) {
// ignore
}
return 0;
});
}
if (TypeUtil.isString(clazz) && TypeUtil.isInteger(targetClass)) {
matchInfo.setTypeDistance(TypeMatchLevel.EXTENSION.getDistanceMin() + 113);
matchInfo.setTypeConverter((value, targetType) -> {
try {
return Integer.valueOf((String)value);
} catch (Exception e) {
// ignore
}
return 0;
});
}
if (TypeUtil.isString(clazz) && TypeUtil.isLong(targetClass)) {
matchInfo.setTypeDistance(TypeMatchLevel.EXTENSION.getDistanceMin() + 114);
matchInfo.setTypeConverter((value, targetType) -> {
try {
return Long.valueOf((String)value);
} catch (Exception e) {
// ignore
}
return 0;
});
}
if (TypeUtil.isString(clazz) && TypeUtil.isFloat(targetClass)) {
matchInfo.setTypeDistance(TypeMatchLevel.EXTENSION.getDistanceMin() + 115);
matchInfo.setTypeConverter((value, targetType) -> {
try {
return Float.valueOf((String)value);
} catch (Exception e) {
// ignore
}
return 0;
});
}
if (TypeUtil.isString(clazz) && TypeUtil.isDouble(targetClass)) {
matchInfo.setTypeDistance(TypeMatchLevel.EXTENSION.getDistanceMin() + 116);
matchInfo.setTypeConverter((value, targetType) -> {
try {
return Double.valueOf((String)value);
} catch (Exception e) {
// ignore
}
return 0;
});
}
return matchInfo;
}
});
// 日期
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() + 200);
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);
}
}));
} else if (LocalDateTime.class.isAssignableFrom(clazz) && TypeUtil.isDate(targetClass)) {
matchInfo.setTypeDistance(TypeMatchLevel.EXTENSION.getDistanceMin() + 201);
matchInfo.setTypeConverter(((value, targetType) -> {
ZoneId zone = ZoneId.systemDefault();
Instant instant = ((LocalDateTime)value).atZone(zone).toInstant();
return Date.from(instant);
}));
}
return matchInfo;
}
});
// 日期
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() + 300);
matchInfo.setTypeConverter(((value, targetType) -> ((java.util.Date)value).getTime()));
}
return matchInfo;
}
});
// Object[] -> List
extensionMatcherList.add(new TypeMatcher() {
@Override
public TypeMatchInfo match(Class<?> clazz, Class<?> targetClass) {
TypeMatchInfo matchInfo = new TypeMatchInfo(clazz, targetClass, this);
if (List.class == targetClass && clazz.isArray()) {
matchInfo.setTypeDistance(TypeMatchLevel.EXTENSION.getDistanceMin() + 400);
matchInfo.setTypeConverter(((value, targetType) -> Stream.of((Object[])value).collect(Collectors.toList())));
}
return matchInfo;
}
});
// List -> Object[]
extensionMatcherList.add(new TypeMatcher() {
@Override
public TypeMatchInfo match(Class<?> clazz, Class<?> targetClass) {
TypeMatchInfo matchInfo = new TypeMatchInfo(clazz, targetClass, this);
if (List.class.isAssignableFrom(clazz) && targetClass.isArray()) {
matchInfo.setTypeDistance(TypeMatchLevel.EXTENSION.getDistanceMin() + 500);
matchInfo.setTypeConverter((value, targetType) -> ((List)value).toArray());
}
return matchInfo;
}
});
// Object[] -> Set
extensionMatcherList.add(new TypeMatcher() {
@Override
public TypeMatchInfo match(Class<?> clazz, Class<?> targetClass) {
TypeMatchInfo matchInfo = new TypeMatchInfo(clazz, targetClass, this);
if (Set.class == targetClass && clazz.isArray()) {
matchInfo.setTypeDistance(TypeMatchLevel.EXTENSION.getDistanceMin() + 600);
matchInfo.setTypeConverter(((value, targetType) -> Stream.of((Object[])value).collect(Collectors.toSet())));
}
return matchInfo;
}
});
// Set -> Object[]
extensionMatcherList.add(new TypeMatcher() {
@Override
public TypeMatchInfo match(Class<?> clazz, Class<?> targetClass) {
TypeMatchInfo matchInfo = new TypeMatchInfo(clazz, targetClass, this);
if (Set.class.isAssignableFrom(clazz) && targetClass.isArray()) {
matchInfo.setTypeDistance(TypeMatchLevel.EXTENSION.getDistanceMin() + 700);
matchInfo.setTypeConverter((value, targetType) -> ((Set)value).toArray());
}
return matchInfo;
}
});
}
// 注册内置扩展匹配
int extensionMatcherGroupSize = 100000;
int extensionMatcherGroupDistance = TypeMatchLevel.EXTENSION.getDistanceMin();
/**
* 注册自定义类型匹配器具
* @param typeMatcher
*/
public void registerCustomTypeMatcher(TypeMatcher typeMatcher) {
customTypeMatcherList.add(typeMatcher);
}
registerExtensionTypeMatcher(new StringMatcherGroup(extensionMatcherGroupDistance + extensionMatcherGroupSize * 0,
extensionMatcherGroupDistance + extensionMatcherGroupSize * 1 - 1));
registerExtensionTypeMatcher(new BooleanMatcherGroup(extensionMatcherGroupDistance + extensionMatcherGroupSize * 1,
extensionMatcherGroupDistance + extensionMatcherGroupSize * 2 - 1));
registerExtensionTypeMatcher(new NumberMatcherGroup(extensionMatcherGroupDistance + extensionMatcherGroupSize * 2,
extensionMatcherGroupDistance + extensionMatcherGroupSize * 3 - 1));
registerExtensionTypeMatcher(new DateMatcherGroup(extensionMatcherGroupDistance + extensionMatcherGroupSize * 3,
extensionMatcherGroupDistance + extensionMatcherGroupSize * 4 - 1));
registerExtensionTypeMatcher(new ListMatcherGroup(extensionMatcherGroupDistance + extensionMatcherGroupSize * 4,
extensionMatcherGroupDistance + extensionMatcherGroupSize * 5 - 1));
registerExtensionTypeMatcher(new SetMatcherGroup(extensionMatcherGroupDistance + extensionMatcherGroupSize * 5,
extensionMatcherGroupDistance + extensionMatcherGroupSize * 6 - 1));
registerExtensionTypeMatcher(new MapMatcherGroup(extensionMatcherGroupDistance + extensionMatcherGroupSize * 6,
extensionMatcherGroupDistance + extensionMatcherGroupSize * 7 - 1));
registerExtensionTypeMatcher(new ArrayMatcherGroup(extensionMatcherGroupDistance + extensionMatcherGroupSize * 7,
extensionMatcherGroupDistance + extensionMatcherGroupSize * 8 - 1));
/**
* 匹配
* @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);
}
}
@@ -0,0 +1,77 @@
/**
* 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.extension;
import fun.asgc.neutrino.core.type.TypeMatcher;
import fun.asgc.neutrino.core.type.TypeMatcherGroup;
import java.util.ArrayList;
import java.util.List;
/**
* 抽象的扩展类型匹配器组
* @author: aoshiguchen
* @date: 2022/6/29
*/
public abstract class AbstractExtensionMatcherGroup implements TypeMatcherGroup {
/**
* 最小距离
*/
protected int distanceMin;
/**
* 最大距离
*/
protected int distanceMax;
/**
* 匹配器列表
*/
private List<TypeMatcher> matchers;
public AbstractExtensionMatcherGroup(int distanceMin, int distanceMax) {
this.distanceMin = distanceMin;
this.distanceMax = distanceMax;
this.matchers = new ArrayList<>();
}
@Override
public List<TypeMatcher> matchers() {
return matchers;
}
public synchronized void add(TypeMatcher matcher) {
if (null != matcher) {
this.matchers.add(matcher);
}
}
@Override
public int getDistanceMin() {
return distanceMin;
}
@Override
public int getDistanceMax() {
return distanceMax;
}
}
@@ -0,0 +1,70 @@
/**
* 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.extension;
import fun.asgc.neutrino.core.type.TypeMatchInfo;
import fun.asgc.neutrino.core.type.TypeMatcher;
import java.util.List;
import java.util.Set;
/**
* 数组匹配器组
* @author: aoshiguchen
* @date: 2022/6/29
*/
public class ArrayMatcherGroup extends AbstractExtensionMatcherGroup {
public ArrayMatcherGroup(int distanceMin, int distanceMax) {
super(distanceMin, distanceMax);
this.init();
}
public void init() {
// List -> Object[]
add(new TypeMatcher() {
@Override
public TypeMatchInfo match(Class<?> clazz, Class<?> targetClass) {
TypeMatchInfo matchInfo = new TypeMatchInfo(clazz, targetClass, this);
if (List.class.isAssignableFrom(clazz) && targetClass.isArray()) {
matchInfo.setTypeDistance(getDistanceMin());
matchInfo.setTypeConverter((value, targetType) -> ((List)value).toArray());
}
return matchInfo;
}
});
// Set -> Object[]
add(new TypeMatcher() {
@Override
public TypeMatchInfo match(Class<?> clazz, Class<?> targetClass) {
TypeMatchInfo matchInfo = new TypeMatchInfo(clazz, targetClass, this);
if (Set.class.isAssignableFrom(clazz) && targetClass.isArray()) {
matchInfo.setTypeDistance(getDistanceMin() + 1);
matchInfo.setTypeConverter((value, targetType) -> ((Set)value).toArray());
}
return matchInfo;
}
});
}
}
@@ -0,0 +1,54 @@
/**
* 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.extension;
import fun.asgc.neutrino.core.type.TypeMatchInfo;
import fun.asgc.neutrino.core.type.TypeMatcher;
import fun.asgc.neutrino.core.util.TypeUtil;
/**
* 布尔值匹配器组
* @author: aoshiguchen
* @date: 2022/6/29
*/
public class BooleanMatcherGroup extends AbstractExtensionMatcherGroup {
public BooleanMatcherGroup(int distanceMin, int distanceMax) {
super(distanceMin, distanceMax);
this.init();
}
public void init() {
add(new TypeMatcher() {
@Override
public TypeMatchInfo match(Class<?> clazz, Class<?> targetClass) {
TypeMatchInfo matchInfo = new TypeMatchInfo(clazz, targetClass, this);
if (TypeUtil.isString(clazz) && TypeUtil.isBoolean(targetClass)) {
matchInfo.setTypeDistance(getDistanceMin());
matchInfo.setTypeConverter(((value, targetType) -> ((String)value).toLowerCase().equals("true")));
}
return matchInfo;
}
});
}
}
@@ -0,0 +1,83 @@
/**
* 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.extension;
import fun.asgc.neutrino.core.type.TypeMatchInfo;
import fun.asgc.neutrino.core.type.TypeMatcher;
import fun.asgc.neutrino.core.util.TypeUtil;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
/**
* 日期匹配器组
* @author: aoshiguchen
* @date: 2022/6/29
*/
public class DateMatcherGroup extends AbstractExtensionMatcherGroup {
public DateMatcherGroup(int distanceMin, int distanceMax) {
super(distanceMin, distanceMax);
this.init();
}
public void init() {
// Long -> Date
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(getDistanceMin());
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;
}
});
// LocalDateTime -> Date
add(new TypeMatcher() {
@Override
public TypeMatchInfo match(Class<?> clazz, Class<?> targetClass) {
TypeMatchInfo matchInfo = new TypeMatchInfo(clazz, targetClass, this);
if (LocalDateTime.class.isAssignableFrom(clazz) && TypeUtil.isDate(targetClass)) {
matchInfo.setTypeDistance(getDistanceMin() + 1);
matchInfo.setTypeConverter(((value, targetType) -> {
ZoneId zone = ZoneId.systemDefault();
Instant instant = ((LocalDateTime)value).atZone(zone).toInstant();
return Date.from(instant);
}));
}
return matchInfo;
}
});
}
}
@@ -0,0 +1,58 @@
/**
* 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.extension;
import fun.asgc.neutrino.core.type.TypeMatchInfo;
import fun.asgc.neutrino.core.type.TypeMatcher;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* list匹配器组
* @author: aoshiguchen
* @date: 2022/6/29
*/
public class ListMatcherGroup extends AbstractExtensionMatcherGroup {
public ListMatcherGroup(int distanceMin, int distanceMax) {
super(distanceMin, distanceMax);
this.init();
}
public void init() {
add(new TypeMatcher() {
@Override
public TypeMatchInfo match(Class<?> clazz, Class<?> targetClass) {
TypeMatchInfo matchInfo = new TypeMatchInfo(clazz, targetClass, this);
if (List.class == targetClass && clazz.isArray()) {
matchInfo.setTypeDistance(getDistanceMin());
matchInfo.setTypeConverter(((value, targetType) -> Stream.of((Object[])value).collect(Collectors.toList())));
}
return matchInfo;
}
});
}
}
@@ -0,0 +1,40 @@
/**
* 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.extension;
/**
* Map匹配器组
* @author: aoshiguchen
* @date: 2022/6/29
*/
public class MapMatcherGroup extends AbstractExtensionMatcherGroup {
public MapMatcherGroup(int distanceMin, int distanceMax) {
super(distanceMin, distanceMax);
this.init();
}
public void init() {
}
}
@@ -0,0 +1,169 @@
/**
* 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.extension;
import fun.asgc.neutrino.core.type.TypeMatchInfo;
import fun.asgc.neutrino.core.type.TypeMatcher;
import fun.asgc.neutrino.core.util.TypeUtil;
/**
* 字符串匹配器组
* @author: aoshiguchen
* @date: 2022/6/29
*/
public class NumberMatcherGroup extends AbstractExtensionMatcherGroup {
public NumberMatcherGroup(int distanceMin, int distanceMax) {
super(distanceMin, distanceMax);
this.init();
}
public void init() {
// String -> Byte
add(new TypeMatcher() {
@Override
public TypeMatchInfo match(Class<?> clazz, Class<?> targetClass) {
TypeMatchInfo matchInfo = new TypeMatchInfo(clazz, targetClass, this);
if (TypeUtil.isString(clazz) && TypeUtil.isByte(targetClass)) {
matchInfo.setTypeDistance(getDistanceMin());
matchInfo.setTypeConverter((value, targetType) -> {
try {
return Byte.valueOf((String)value);
} catch (Exception e) {
// ignore
}
return 0;
});
}
return matchInfo;
}
});
// String -> Short
add(new TypeMatcher() {
@Override
public TypeMatchInfo match(Class<?> clazz, Class<?> targetClass) {
TypeMatchInfo matchInfo = new TypeMatchInfo(clazz, targetClass, this);
if (TypeUtil.isString(clazz) && TypeUtil.isShort(targetClass)) {
matchInfo.setTypeDistance(getDistanceMin() + 1);
matchInfo.setTypeConverter((value, targetType) -> {
try {
return Short.valueOf((String)value);
} catch (Exception e) {
// ignore
}
return 0;
});
}
return matchInfo;
}
});
// String -> Integer
add(new TypeMatcher() {
@Override
public TypeMatchInfo match(Class<?> clazz, Class<?> targetClass) {
TypeMatchInfo matchInfo = new TypeMatchInfo(clazz, targetClass, this);
if (TypeUtil.isString(clazz) && TypeUtil.isInteger(targetClass)) {
matchInfo.setTypeDistance(getDistanceMin() + 2);
matchInfo.setTypeConverter((value, targetType) -> {
try {
return Integer.valueOf((String)value);
} catch (Exception e) {
// ignore
}
return 0;
});
}
return matchInfo;
}
});
// String -> Long
add(new TypeMatcher() {
@Override
public TypeMatchInfo match(Class<?> clazz, Class<?> targetClass) {
TypeMatchInfo matchInfo = new TypeMatchInfo(clazz, targetClass, this);
if (TypeUtil.isString(clazz) && TypeUtil.isLong(targetClass)) {
matchInfo.setTypeDistance(getDistanceMin() + 3);
matchInfo.setTypeConverter((value, targetType) -> {
try {
return Long.valueOf((String)value);
} catch (Exception e) {
// ignore
}
return 0;
});
}
return matchInfo;
}
});
// String -> Float
add(new TypeMatcher() {
@Override
public TypeMatchInfo match(Class<?> clazz, Class<?> targetClass) {
TypeMatchInfo matchInfo = new TypeMatchInfo(clazz, targetClass, this);
if (TypeUtil.isString(clazz) && TypeUtil.isFloat(targetClass)) {
matchInfo.setTypeDistance(getDistanceMin() + 4);
matchInfo.setTypeConverter((value, targetType) -> {
try {
return Float.valueOf((String)value);
} catch (Exception e) {
// ignore
}
return 0;
});
}
return matchInfo;
}
});
// String -> Double
add(new TypeMatcher() {
@Override
public TypeMatchInfo match(Class<?> clazz, Class<?> targetClass) {
TypeMatchInfo matchInfo = new TypeMatchInfo(clazz, targetClass, this);
if (TypeUtil.isString(clazz) && TypeUtil.isDouble(targetClass)) {
matchInfo.setTypeDistance(getDistanceMin() + 5);
matchInfo.setTypeConverter((value, targetType) -> {
try {
return Double.valueOf((String)value);
} catch (Exception e) {
// ignore
}
return 0;
});
}
return matchInfo;
}
});
// date -> Long
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(getDistanceMin() + 6);
matchInfo.setTypeConverter(((value, targetType) -> ((java.util.Date)value).getTime()));
}
return matchInfo;
}
});
}
}
@@ -0,0 +1,58 @@
/**
* 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.extension;
import fun.asgc.neutrino.core.type.TypeMatchInfo;
import fun.asgc.neutrino.core.type.TypeMatchLevel;
import fun.asgc.neutrino.core.type.TypeMatcher;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* set匹配器组
* @author: aoshiguchen
* @date: 2022/6/29
*/
public class SetMatcherGroup extends AbstractExtensionMatcherGroup {
public SetMatcherGroup(int distanceMin, int distanceMax) {
super(distanceMin, distanceMax);
this.init();
}
public void init() {
add(new TypeMatcher() {
@Override
public TypeMatchInfo match(Class<?> clazz, Class<?> targetClass) {
TypeMatchInfo matchInfo = new TypeMatchInfo(clazz, targetClass, this);
if (Set.class == targetClass && clazz.isArray()) {
matchInfo.setTypeDistance(getDistanceMin());
matchInfo.setTypeConverter(((value, targetType) -> Stream.of((Object[])value).collect(Collectors.toSet())));
}
return matchInfo;
}
});
}
}
@@ -0,0 +1,67 @@
/**
* 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.extension;
import fun.asgc.neutrino.core.type.TypeMatchInfo;
import fun.asgc.neutrino.core.type.TypeMatcher;
import fun.asgc.neutrino.core.util.TypeUtil;
/**
* 字符串匹配器组
* @author: aoshiguchen
* @date: 2022/6/29
*/
public class StringMatcherGroup extends AbstractExtensionMatcherGroup {
public StringMatcherGroup(int distanceMin, int distanceMax) {
super(distanceMin, distanceMax);
this.init();
}
public void init() {
// 基本类型 -> String
add(new TypeMatcher() {
@Override
public TypeMatchInfo match(Class<?> clazz, Class<?> targetClass) {
TypeMatchInfo matchInfo = new TypeMatchInfo(clazz, targetClass, this);
if (TypeUtil.isNormalBasicType(clazz) && TypeUtil.isString(targetClass)) {
matchInfo.setTypeDistance(getDistanceMin());
matchInfo.setTypeConverter(((value, targetType) -> String.valueOf(value)));
}
return matchInfo;
}
});
// String -> char
add(new TypeMatcher() {
@Override
public TypeMatchInfo match(Class<?> clazz, Class<?> targetClass) {
TypeMatchInfo matchInfo = new TypeMatchInfo(clazz, targetClass, this);
if (TypeUtil.isChar(targetClass) && TypeUtil.isString(clazz)) {
matchInfo.setTypeDistance(getDistanceMin() + 1);
matchInfo.setTypeConverter(((value, targetType) -> ((String)value).charAt(0)));
}
return matchInfo;
}
});
}
}
@@ -128,7 +128,7 @@ public class TypeUtilTest {
@Test
public void conversionInt() {
typeMatchers.setEnableExtensionMatcher(false);
typeMatchers.setEnableExtensionMatcher(true);
System.out.println(typeMatchers.conversion(100, boolean.class));
System.out.println(typeMatchers.conversion(101, byte.class));