mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-07-21 15:09:48 +08:00
fix code
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Hutool Team and hutool.cn
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.core.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 标记可读Bean<br>
|
||||
* 即包含有可读字段的Bean使用此注解标记,如含有public的字段或getter方法
|
||||
*
|
||||
* @author looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE})
|
||||
public @interface ReadableBean {
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Hutool Team and hutool.cn
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.core.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 标记可写Bean<br>
|
||||
* 即包含有可写字段的Bean使用此注解标记,如含有public的字段或setter方法
|
||||
*
|
||||
* @author looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE})
|
||||
public @interface WritableBean {
|
||||
}
|
@@ -16,6 +16,9 @@
|
||||
|
||||
package org.dromara.hutool.core.bean;
|
||||
|
||||
import org.dromara.hutool.core.annotation.AnnotationUtil;
|
||||
import org.dromara.hutool.core.annotation.ReadableBean;
|
||||
import org.dromara.hutool.core.annotation.WritableBean;
|
||||
import org.dromara.hutool.core.array.ArrayUtil;
|
||||
import org.dromara.hutool.core.bean.copier.BeanCopier;
|
||||
import org.dromara.hutool.core.bean.copier.CopyOptions;
|
||||
@@ -687,6 +690,11 @@ public class BeanUtil {
|
||||
// String中有getter方法,但为字符串,不是Bean
|
||||
return false;
|
||||
}
|
||||
|
||||
if(AnnotationUtil.hasAnnotation(clazz, ReadableBean.class)){
|
||||
return true;
|
||||
}
|
||||
|
||||
return hasGetter(clazz) || hasPublicField(clazz);
|
||||
}
|
||||
|
||||
@@ -712,6 +720,10 @@ public class BeanUtil {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(AnnotationUtil.hasAnnotation(clazz, WritableBean.class)){
|
||||
return true;
|
||||
}
|
||||
|
||||
return hasSetter(clazz) || hasPublicField(clazz);
|
||||
}
|
||||
|
||||
|
@@ -31,7 +31,7 @@ public interface ValueProvider<K>{
|
||||
|
||||
/**
|
||||
* 获取值<br>
|
||||
* 返回值一般需要匹配被注入类型,如果不匹配会调用默认转换 Convert#convert(Type, Object)实现转换
|
||||
* 返回值一般需要匹配被注入类型,如果不匹配会调用默认转换 Convert#support(Type, Object)实现转换
|
||||
*
|
||||
* @param key Bean对象中参数名
|
||||
* @param valueType 被注入的值的类型
|
||||
|
@@ -17,14 +17,11 @@
|
||||
package org.dromara.hutool.core.bean.path;
|
||||
|
||||
import org.dromara.hutool.core.array.ArrayUtil;
|
||||
import org.dromara.hutool.core.bean.path.node.NameNode;
|
||||
import org.dromara.hutool.core.bean.path.node.Node;
|
||||
import org.dromara.hutool.core.bean.path.node.NodeFactory;
|
||||
import org.dromara.hutool.core.text.CharUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
@@ -67,6 +64,7 @@ public class BeanPath implements Iterator<BeanPath> {
|
||||
|
||||
private final Node node;
|
||||
private final String child;
|
||||
private NodeBeanCreator beanCreator;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
@@ -74,6 +72,7 @@ public class BeanPath implements Iterator<BeanPath> {
|
||||
* @param expression 表达式
|
||||
*/
|
||||
public BeanPath(final String expression) {
|
||||
this.beanCreator = DefaultNodeBeanCreator.INSTANCE;
|
||||
final int length = expression.length();
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
|
||||
@@ -128,6 +127,17 @@ public class BeanPath implements Iterator<BeanPath> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置Bean创建器,用于创建Bean对象,默认为{@link DefaultNodeBeanCreator}
|
||||
*
|
||||
* @param beanCreator Bean创建器
|
||||
* @return this
|
||||
*/
|
||||
public BeanPath setBeanCreator(final NodeBeanCreator beanCreator) {
|
||||
this.beanCreator = beanCreator;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取节点
|
||||
*
|
||||
@@ -189,7 +199,7 @@ public class BeanPath implements Iterator<BeanPath> {
|
||||
final BeanPath childBeanPath = next();
|
||||
Object subBean = this.node.getValue(bean);
|
||||
if (null == subBean) {
|
||||
subBean = isListNode(childBeanPath.node) ? new ArrayList<>() : new HashMap<>();
|
||||
subBean = beanCreator.create(bean, this);
|
||||
this.node.setValue(bean, subBean);
|
||||
// 如果自定义put方法修改了value,返回修改后的value,避免值丢失
|
||||
subBean = this.node.getValue(bean);
|
||||
@@ -210,17 +220,4 @@ public class BeanPath implements Iterator<BeanPath> {
|
||||
", child='" + child + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
/**
|
||||
* 子节点值是否为列表
|
||||
*
|
||||
* @param node 节点
|
||||
* @return 是否为列表
|
||||
*/
|
||||
private static boolean isListNode(final Node node) {
|
||||
if (node instanceof NameNode) {
|
||||
return ((NameNode) node).isNumber();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Hutool Team and hutool.cn
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.core.bean.path;
|
||||
|
||||
import org.dromara.hutool.core.array.ArrayUtil;
|
||||
import org.dromara.hutool.core.bean.path.node.NameNode;
|
||||
import org.dromara.hutool.core.bean.path.node.Node;
|
||||
import org.dromara.hutool.core.reflect.ConstructorUtil;
|
||||
import org.dromara.hutool.core.reflect.FieldUtil;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 默认的Bean创建器
|
||||
*
|
||||
* @author looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class DefaultNodeBeanCreator implements NodeBeanCreator {
|
||||
|
||||
/**
|
||||
* 单例
|
||||
*/
|
||||
public static final NodeBeanCreator INSTANCE = new DefaultNodeBeanCreator();
|
||||
|
||||
@Override
|
||||
public Object create(final Object parent, final BeanPath beanPath) {
|
||||
if(parent instanceof Map || parent instanceof List || ArrayUtil.isArray(parent)){
|
||||
// 根据下一个节点类型,判断当前节点名称对应类型
|
||||
final Node node = beanPath.next().getNode();
|
||||
if (node instanceof NameNode) {
|
||||
return ((NameNode) node).isNumber() ? new ArrayList<>() : new HashMap<>();
|
||||
}
|
||||
return new HashMap<>();
|
||||
}
|
||||
|
||||
// 普通Bean
|
||||
final Node node = beanPath.getNode();
|
||||
if(node instanceof NameNode){
|
||||
final String name = ((NameNode) node).getName();
|
||||
|
||||
final Field field = FieldUtil.getField(parent.getClass(), name);
|
||||
if(null == field){
|
||||
throw new IllegalArgumentException("No field found for name: " + name);
|
||||
}
|
||||
return ConstructorUtil.newInstanceIfPossible(field.getType());
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException("Unsupported node type: " + node.getClass());
|
||||
}
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Hutool Team and hutool.cn
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.core.bean.path;
|
||||
|
||||
/**
|
||||
* BeanPath节点对应的Bean创建器<br>
|
||||
* 用于创建Bean路径节点对应的Bean
|
||||
*
|
||||
* @author looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public interface NodeBeanCreator {
|
||||
|
||||
/**
|
||||
* 创建Bean<br>
|
||||
* beanPath对应当前的路径,即如果父对象为:a,则beanPath为:a.b,则创建的Bean为:a.b.c对应的Bean对象<br>
|
||||
* 给定的a一定存在,但是本路径中b对应的Bean不存在,则创建的对象是b的值,这个值用c表示
|
||||
*
|
||||
* @param parent 父Bean
|
||||
* @param beanPath 当前路径
|
||||
* @return Bean
|
||||
*/
|
||||
Object create(final Object parent, final BeanPath beanPath);
|
||||
}
|
@@ -34,6 +34,15 @@ public class NameNode implements Node {
|
||||
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* 获取节点名
|
||||
*
|
||||
* @return 节点名
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
|
@@ -505,7 +505,7 @@ public class Hashids implements Encoder<long[], String>, Decoder<String, long[]>
|
||||
return IntStream.range(0, separators.length)
|
||||
.mapToObj(idx -> (separators[idx]))
|
||||
.filter(valid::contains)
|
||||
// ugly way to convert back to char[]
|
||||
// ugly way to support back to char[]
|
||||
.map(c -> Character.toString(c))
|
||||
.collect(Collectors.joining())
|
||||
.toCharArray();
|
||||
|
@@ -135,7 +135,7 @@ public class PercentCodec implements Encoder<byte[], byte[]>, Serializable {
|
||||
// 对于空格单独处理
|
||||
rewrittenPath.append('+');
|
||||
} else {
|
||||
// convert to external encoding before hex conversion
|
||||
// support to external encoding before hex conversion
|
||||
try {
|
||||
writer.write(c);
|
||||
writer.flush();
|
||||
|
@@ -67,7 +67,7 @@ public class Z85Codec implements Encoder<byte[], String>, Decoder<String, byte[]
|
||||
// Support inputs that are not divisible by 4 with no remainder.
|
||||
final int padding = 4 - (remainder == 0 ? 4 : remainder);
|
||||
|
||||
// SPEC: 4 octets convert into 5 printable characters.
|
||||
// SPEC: 4 octets support into 5 printable characters.
|
||||
// char.length = length + 1/4 length == 5/4 length.
|
||||
final char[] chars = new char[length + (length >>> 2) + (remainder == 0 ? 0 : 1)];
|
||||
int idx = 0;
|
||||
|
@@ -45,7 +45,7 @@ public abstract class AbstractConverter implements Converter, Serializable {
|
||||
return null;
|
||||
}
|
||||
if (TypeUtil.isUnknown(targetType)) {
|
||||
throw new ConvertException("Unsupported convert to unKnown type: {}", targetType);
|
||||
throw new ConvertException("Unsupported support to unKnown type: {}", targetType);
|
||||
}
|
||||
|
||||
final Class<?> targetClass = TypeUtil.getClass(targetType);
|
||||
|
@@ -201,6 +201,6 @@ public class CompositeConverter implements Converter, Serializable {
|
||||
}
|
||||
|
||||
// 无法转换
|
||||
throw new ConvertException("Can not convert from {}: [{}] to [{}]", value.getClass().getName(), value, type.getTypeName());
|
||||
throw new ConvertException("Can not support from {}: [{}] to [{}]", value.getClass().getName(), value, type.getTypeName());
|
||||
}
|
||||
}
|
||||
|
@@ -90,7 +90,7 @@ public class RegisterConverter extends ConverterWithRoot implements Serializable
|
||||
}
|
||||
|
||||
// 无法转换
|
||||
throw new ConvertException("Can not convert from {}: [{}] to [{}]", value.getClass().getName(), value, targetType.getTypeName());
|
||||
throw new ConvertException("Can not support from {}: [{}] to [{}]", value.getClass().getName(), value, targetType.getTypeName());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -108,7 +108,7 @@ public class DateConverter extends AbstractConverter implements MatcherConverter
|
||||
}
|
||||
}
|
||||
|
||||
throw new ConvertException("Can not convert {}:[{}] to {}", value.getClass().getName(), value, targetClass.getName());
|
||||
throw new ConvertException("Can not support {}:[{}] to {}", value.getClass().getName(), value, targetClass.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -67,7 +67,7 @@ public class EnumConverter extends AbstractConverter implements MatcherConverter
|
||||
return enumValue;
|
||||
}
|
||||
|
||||
throw new ConvertException("Can not convert {} to {}", value, targetClass);
|
||||
throw new ConvertException("Can not support {} to {}", value, targetClass);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -78,7 +78,7 @@ public class NumberConverter extends AbstractConverter implements MatcherConvert
|
||||
protected String convertToStr(final Object value) {
|
||||
final String result = StrUtil.trim(super.convertToStr(value));
|
||||
if(StrUtil.isEmpty(result)){
|
||||
throw new ConvertException("Can not convert empty value to Number!");
|
||||
throw new ConvertException("Can not support empty value to Number!");
|
||||
}
|
||||
|
||||
if (result.length() > 1) {
|
||||
|
@@ -76,7 +76,7 @@ public class PrimitiveConverter extends AbstractConverter implements MatcherConv
|
||||
}
|
||||
|
||||
if(null == result){
|
||||
throw new ConvertException("Can not convert {} to {}", value, primitiveClass);
|
||||
throw new ConvertException("Can not support {} to {}", value, primitiveClass);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@@ -408,7 +408,7 @@ public class FastDateFormat extends Format implements PositionDateParser, DatePr
|
||||
return printer.getMaxLengthEstimate();
|
||||
}
|
||||
|
||||
// convert DateTimeFormatter
|
||||
// support DateTimeFormatter
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
|
@@ -266,7 +266,7 @@ public class Version implements Comparable<Version>, Serializable {
|
||||
}
|
||||
return c;
|
||||
}
|
||||
// Types differ, so convert number to string form
|
||||
// Types differ, so support number to string form
|
||||
final int c = o1.toString().compareTo(o2.toString());
|
||||
if (c == 0){
|
||||
continue;
|
||||
|
@@ -329,7 +329,7 @@ public class ConvertTest {
|
||||
|
||||
@Test
|
||||
public void toClassTest(){
|
||||
final Class<?> convert = ConvertUtil.convert(Class.class, "org.dromara.hutool.core.convert.ConvertTest.Product");
|
||||
final Class<?> convert = ConvertUtil.convert(Class.class, "org.dromara.hutool.core.support.ConvertTest.Product");
|
||||
Assertions.assertSame(Product.class, convert);
|
||||
}
|
||||
|
||||
|
@@ -219,7 +219,7 @@ public class ByteUtilTest {
|
||||
final byte[] bytes = new byte[]{(byte) 0xFF, (byte) 0xFE, (byte) 0x01, (byte) 0x00};
|
||||
final int expectedValue = 130815;
|
||||
final int actualValue = ByteUtil.toInt(bytes, 0, ByteOrder.LITTLE_ENDIAN);
|
||||
assertEquals(expectedValue, actualValue, "Failed to convert bytes to int using LITTLE_ENDIAN");
|
||||
assertEquals(expectedValue, actualValue, "Failed to support bytes to int using LITTLE_ENDIAN");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -228,6 +228,6 @@ public class ByteUtilTest {
|
||||
final byte[] bytes = new byte[]{(byte) 0xFF, (byte) 0xFE, (byte) 0x01, (byte) 0x00};
|
||||
final int expectedValue = -130816;
|
||||
final int actualValue = ByteUtil.toInt(bytes, 0, ByteOrder.BIG_ENDIAN);
|
||||
assertEquals(expectedValue, actualValue, "Failed to convert bytes to int using BIG_ENDIAN");
|
||||
assertEquals(expectedValue, actualValue, "Failed to support bytes to int using BIG_ENDIAN");
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user