com.gitee.feizns.dynamic.bean.Prop Maven / Gradle / Ivy
package com.gitee.feizns.dynamic.bean;
import com.gitee.feizns.dynamic.Ex;
import com.gitee.feizns.dynamic.Objs;
import com.gitee.feizns.dynamic.convert.Converter;
import com.gitee.feizns.dynamic.convert.Converts;
import com.gitee.feizns.dynamic.reflect.Types;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Stream;
/**
* 代表一个类上某个属性的元信息
*
* 如果有类class User { public String getName(){return null;} }
* 要代表User类的name属性也就是 Prop nameProp = Prop.of(User.class, "name");
* 因为该属性仅有一个getName();代表该属性是可读的但是不可写
*
* {@code
* //这个属性代表这是User.class类型的name属性
* //String是name属性的数据类型,User则代表该属性所属的类型
* Prop nameProp = Prop.of(User.class, "name")
* }
* @param 属性数据类型
* @param 属性源对象的类型
* @author feizns
* @since 2019/6/5
*/
public interface Prop extends AnnotatedElement, Cloneable {
/**
* 获取属性值
* {@code
* static class User {
* String name;
* public User(String name){ this.name = name; }
* public String getName() { return this.name; }
* }
* Prop.of(new User("张三"), "name").val(); //"张三"
* }
* @return 返回属性的值
*/
default D val() {
return invokeReadMethod();
}
/**
* 获取属性值
* {@code
* static class User {
* Integer name;
* public User(Integer name){ this.name = name; }
* public Integer getName() { return this.name; }
* }
* Prop.of(new User(1), "name").val(String.class); //"1"
* }
* @apiNote 会尝试将原数据类型转换为期望得到的数据类型
* @param targetType 期望得到的属性值类型Class
* @param 期望返回的属性值类型
* @return 返回对应类型的值
*/
default R val(Class targetType) {
D value = val();
return value != null ? Converts.to(value, targetType) : null;
}
/**
* 值列表(对于原来是数组或是Iterable的对象进行转换为List,对于非集合的数据返回一个数据的数组)
* @param targetType 目标类型
* @return {@link List }<{@link R }>
*/
@SuppressWarnings("unchecked")
default List list(Class targetType) {
return (List) new ArrayList<>(java.util.Arrays.asList(Objs.toArray(val(targetType))));
}
/**
* 值列表(对于原来是数组或是Iterable的对象进行转换为List,对于非集合的数据返回一个数据的数组)
* @return {@link List }<{@link R }>
*/
@SuppressWarnings("unchecked")
default List list() {
return (List) new ArrayList<>(Arrays.asList(Objs.toArray(val())));
}
/**
* 判断当前属性值是否为null
* @return 是/否
*/
default boolean isNull() {
return Objects.isNull(val());
}
/**
* 判断当前属性是否是一个数组
* @return boolean
*/
default boolean isArray() {
Class> returnType = fieldClassOrReadMethodReturnType();
return returnType != null && returnType.isArray();
}
/**
* 判断当前属性是否是一个Iterable
* @return boolean
*/
default boolean isIterable() {
Class> returnType = fieldClassOrReadMethodReturnType();
return returnType != null && instanceOf(Iterable.class);
}
/**
* 判断当前属性是否是一个JavaBean
* @return boolean
*/
default boolean isJavaBeanType() {
Class> returnType = fieldClassOrReadMethodReturnType();
return returnType != null && Types.isJavaBeanType(returnType);
}
/**
* instanceof 任意一个
* @param types 类型
* @return boolean
*/
default boolean instanceOf(Class>... types) {
Class> returnType = fieldClassOrReadMethodReturnType();
return java.util.Arrays.stream(types).anyMatch(type -> type.isAssignableFrom(returnType));
}
/**
* 为属性赋值
*
* 获取旧值并设置新值
*
* @param newVal 属性新值
* @return oldVal 返回旧值
*/
default D getAndSet(D newVal) {
D oldVal = val();
set(newVal);
return oldVal;
}
/**
* 设置属性
*
* 将类型不兼容的将会启用自动类型转换
*
* @param newVal 新值
* @return 为属性设置新值
*/
default Prop set(Object newVal) {
return set(newVal, Converts::to);
}
/**
* 设置属性值类型和属性的类型不一致时、指定类型转换规则
*
* 如果转换器、不支持转换、则不会调用set函数
*
* @see Converter
* @see Converter#support(Object, Class)
* @see Converter#to(Object, Class)
* @param newVal 新值
* @param converter 转换器
* @return 属性
* @param 设置的值类型
*/
@SuppressWarnings("unchecked")
default Prop set(T newVal, Converter converter) {
Class> writeMethodParameterType = writeMethodParameterType();
if ( writeMethodParameterType != null ) {
if ( converter.support(newVal, writeMethodParameterType) ) {
D realNewVal = converter.to(newVal, (Class) writeMethodParameterType);
return invokeWriteMethod(realNewVal);
}
}
return this;
}
/**
* 调用读取属性方法
* @return 属性本身
*/
@SuppressWarnings("unchecked")
default D invokeReadMethod() {
S source = getSource();
Method readMethod = readMethod();
if ( source != null && readMethod != null )
return Ex.tryCatch(() -> (D) readMethod.invoke(source)).orElse(null);
return null;
}
/**
* 调用写方法
* @param newVal 新值
* @return 属性本身
*/
default Prop invokeWriteMethod(D newVal) {
S source = getSource();
Method writeMethod = writeMethod();
if ( source != null && writeMethod != null )
Ex.tryCatch(() -> writeMethod.invoke(source, newVal));
return this;
}
/**
* 对当前属性做一次尝试从source值对象获取值并赋值给当前对象的操作
*
* 将当前属性、期望从source中获取的第一个非空属性值赋值给当前属性
*
* @param source 值对象
* @return 为属性设置新值
*/
default Prop tryGet(Object source) {
Props.tryGet(this, source);
return this;
}
/**
* 将当前属性的属性值作为原对象获取其子属性
* (该方法获取属性值的属性)
* {@code
@Data
class User {
Integer id;
User child;
User(Integer id) { this.id = id; }
}
public static void main(String[] args) {
User one = new User(1);
User two = new User(2);
User three = new User(3);
one.child = two;
two.child = three;
Prop prop = Prop.of(one, "child");
System.out.println(one == prop.getTarget()); //true
System.out.println(two == prop.val()); //true
Prop threeProp = prop.get("child");
System.out.println(threeProp.getTarget() == two); //true
System.out.println(threeProp.val() == three); //true
}
* }
* @param name 属性名
* @param 子属性的数据类型
* @return 返回对应名称的属性信息
*/
default
Prop
get(String name) {
return of(val(), name);
}
/**
* 获取属性
*
该方法获取属性值的属性
* (如果属性是一个只写属性,则需要通过propertyClass指名writeMethod的参数类型)
* @param name 属性名称
* @param propertyClass 属性Class类型
* @param 属性真实类型
* @return 返回对应名称的属性信息
*/
default
Prop
get(String name, Class
propertyClass) {
return of(val(), name, propertyClass);
}
/**
* 获取属性
*
(假设该属性已属于某个对象,则可以通过该方法获取属性的子属性)
* @param getter 属性的get方法引用
* @param 属性类型
* @return 返回对应get方法引用的属性信息
*/
default
Prop
get(Getter getter) {
return of(val(), getter);
}
/**
* 属性名
* @return 返回一个属性的属性名
*/
String name();
/**
* 是否可读
* @return 如果属性有读方法(get方法)则可读, 返回true。否则返回false
*/
default boolean isReadable() {
return readMethod() != null;
}
/**
* 是否可写
* @return 如果属性有写方法(set方法)则可写, 返回true。否则返回false
*/
default boolean isWritable() {
return writeMethod() != null;
}
/**
* 判断当前对象是否用户源对象实例
* @return 是/否
*/
default boolean hasSource() {
return getSource() != null;
}
/**
* 获取源对象
* @return 返回该属性是源对象。(该属性属于这个source对象)
*/
S getSource();
/**
* 获取属性所属对象的类型
*
* Prop prop = Prop.of(user1, "name");
* System.out.println(prop.getSourceClass()); //User.class
*
* @return 返回属性所属对象的类型
*/
@SuppressWarnings("unchecked")
default Class getSourceClass() {
return getSource() != null ? (Class) getSource().getClass() : null;
}
/**
* 获取字段
* @return 返回存储数据的字段
*/
Field field();
/**
* 获取属性的字段{@link Class}类型
* @return {@link Class}
*/
default Class> fieldClass() {
return Optional.ofNullable(field()).map(Field::getType).orElse(null);
}
/**
* 默认获取属性类型、没有属性则获取Get方法类型
* @return {@link Class}
*/
default Class> fieldClassOrReadMethodReturnType() {
Class> type = fieldClass();
if ( type == null )
type = Optional.ofNullable(readMethod()).map(Method::getReturnType).orElse(null);
return type;
}
/**
* 获取属性的字段类型
* @return {@link Type}
*/
default Type fieldType() {
return Optional.ofNullable(field()).map(Field::getGenericType).orElse(null);
}
/**
* 获取属性的类型信息
*
* 属性上获取不到则到get方法上获取
*
* @return {@link Type}
*/
default Type fieldTypeOrReadMethodGenericReturnType() {
Type type = fieldType();
if ( type == null )
type = Optional.ofNullable(readMethod()).map(Method::getGenericReturnType).orElse(null);
return type;
}
/**
* 读方法(对应属性的GET方法)
* (如果是属性不可读则返回null)
* 假设属性是name则对应的读方法为getName()
* @return 返回读取数据的方法
*/
Method readMethod();
/**
* 获取读方法的返回值类型
* @return 读方法的返回值类型
*/
default Class> readMethodReturnType() {
Method readMethod = readMethod();
return readMethod != null ? readMethod.getReturnType(): null;
}
/**
* 写方法(对应属性的SET方法)
* 假设属性是name则对应的读方法为setName()
* @apiNote 如果是属性不可写则返回null
* @return 返回写入数据的方法
*/
Method writeMethod();
/**
* 写入函数的参数类型
* @return 写入函数的类型
*/
default Class> writeMethodParameterType() {
Method writeMethod = writeMethod();
return writeMethod != null ? writeMethod.getParameterTypes()[0] : null;
}
/**
* 查找一个属性上的注解,默认按照【字段、读方法、写方法】的顺序去查找
* 例:如果一个属性name,它的字段和getName()方法上都有@JsonIngore注解则返回字段上的注解信息
* @param annotationClass 注解类型
* @param 实际注解类型
* @return {@link java.lang.annotation.Annotation}
* @throws NullPointerException 如果参数annotationClass为空
*/
@Override
default T getAnnotation(Class annotationClass) {
Stream elements = annotatedElements().filter(item -> item.isAnnotationPresent(annotationClass));
Optional annotatedElement = elements.findFirst();
return annotatedElement.map(element -> element.getAnnotation(annotationClass)).orElse(null);
}
/**
* 获取从属性的字段、读方法、写方法上三者上的所有注解(不包含私有元素的注解)
*
* 例:如果存在一个属性name,它的字段field是使用private修饰的,读方法getName()则是使用public修饰.
* 如:@Autowired private String name;和 @JsonIgnore public String getName() 则仅返回
* [@JsonIgnore]
*
* @see #getDeclaredAnnotations() 如果需要返回私有字段上的可以看
* @return 按照字段、读方法、写方法的顺序放置三者的所有注解在返回值数组中
*/
@Override
default Annotation[] getAnnotations() {
return annotatedElements().flatMap(item -> java.util.Arrays.stream(item.getAnnotations())).toArray(Annotation[]::new);
}
/**
* 获取从属性的字段、读方法、写方法上三者上的所有注解(含私有元素的注解)
*
* 例:如果存在一个属性name,它的字段field上有注解@Autowired,读方法getName()上有@JsonIgnore.
* 如:@Autowired private String name;和 @JsonIgnore public String getName() 则返回
* [@Autowired, @JsonIgnore]
*
* @see #getAnnotations() 如果不需要返回私有成员上的注解可以看
* @return 按照字段、读方法、写方法的顺序放置三者的所有注解在返回值数组中
*/
@Override
default Annotation[] getDeclaredAnnotations() {
return annotatedElements().flatMap(item -> java.util.Arrays.stream(item.getDeclaredAnnotations())).toArray(Annotation[]::new);
}
/**
* 属性上的元素信息=【字段元信息、读方法元信息、写方法元信息】
* @return 返回一个装载了字段、读方法、写方法的流
*/
default Stream annotatedElements() {
return java.util.Arrays.stream(new AnnotatedElement[]{ field(), readMethod(), writeMethod() }).filter(Objects::nonNull);
}
/**
* 以当前属性的元数据构建属性.
* @param source 源
* @return {@link Prop}<{@link D}, {@link S}>
*/
Prop of(S source);
/**
* 根据目标类型,属性名构建一个属性
* {@code
* Prop prop = Prop.of(new User("张三"), "name")
* System.out.println(prop.val()); //"张三"
* }
* @param target 属性源对象
* @param name 属性名称
* @param 属性的源对象类型
* @param 属性的数据类型
* @return 属性信息
*/
static Prop of(O target, String name) {
return new DefaultPropImpl<>(target, name);
}
/**
* 根据目标类型,GET方法引用构建一个属性
* {@code
* Prop prop = Prop.of(new User("张三"), User::getName)
* System.out.println(prop.val()); //"张三"
* }
* @param target 属性源对象
* @param getter 属性GET方法的方法引用
* @param 属性的源对象类型
* @param 属性的数据类型
* @return 属性信息
*/
static Prop of(O target, Getter getter) {
return new DefaultPropImpl<>(target, getter);
}
/**
* 根据目标类型,属性名称构建一个属性
* 如果属性是一个只写属性(也就不会有field和readMethod),则需要通过propertyClass指名writeMethod的参数类型
* {@code
* Prop prop = Prop.of(new User("张三"), "name", String.class)
* System.out.println(prop.val()); //"张三"
* prop.set("李四");
* System.out.println(prop.val()); //"李四"
* }
* @param target 属性所属源对象
* @param name 属性名称
* @param 属性源对象的类型
* @param 属性数据的类型
* @return 属性信息
*/
static Prop of(O target, String name, Class propertyClass) {
return new DefaultPropImpl<>(target, name, propertyClass);
}
/**
* 根据目标类型,属性名称构建一个属性
* {@code
* Prop prop = Prop.of(User.class, "name")
* System.out.println(prop.val()); //"张三"
* }
* @param targetClass 属性原对象的Class
* @param name 属性名称
* @param 属性源对象的类型
* @param 属性数据的类型
* @return 属性信息
*/
static Prop of(Class targetClass, String name) {
return new DefaultPropImpl<>(targetClass, name);
}
/**
* 根据目标类型,getter方法引用构建一个属性
* {@code
* Prop prop = Prop.of(User.class, User::getName)
* System.out.println(prop.val()); //"张三"
* }
* @param targetClass 目标类型Class
* @param getter getter方法引用
* @param 属性源对象的类型
* @param 属性数据的类型
* @return 属性信息
*/
static Prop of(Class targetClass, Getter getter) {
return new DefaultPropImpl<>(targetClass, getter);
}
/**
* 根据目标类型,属性名,属性类型构建一个属性
* (如果属性是一个只写属性(也就不会有field和readMethod),则需要通过propertyClass指名writeMethod的参数类型)
* {@code
* Prop prop = Prop.of(User.class, "name", String.class)
* System.out.println(prop.val()); //"张三"
* prop.set("李四");
* System.out.println(prop.val()); //"李四"
* }
* @param targetClass 目标类型Class
* @param name 属性名称
* @param propertyClass 属性类型Class
* @param 目标对象类型
* @param 属性类型
* @return 属性信息
*/
static Prop of(Class targetClass, String name, Class propertyClass) {
return new DefaultPropImpl<>(targetClass, name, propertyClass);
}
}