All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.gitee.feizns.dynamic.bean.Prop Maven / Gradle / Ivy

There is a newer version: 6.1-RELEASE
Show newest version
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); } }