diff --git a/flyfish-data/src/main/java/com/flyfish/framework/domain/base/Domain.java b/flyfish-data/src/main/java/com/flyfish/framework/domain/base/Domain.java index 0fc17fa..1e4b67e 100644 --- a/flyfish-data/src/main/java/com/flyfish/framework/domain/base/Domain.java +++ b/flyfish-data/src/main/java/com/flyfish/framework/domain/base/Domain.java @@ -22,6 +22,7 @@ public abstract class Domain implements Po, Serializable { * 主键 */ @Id + @Property(readonly = true) protected String id; /** diff --git a/flyfish-web/src/main/java/com/flyfish/framework/beans/meta/BeanProperty.java b/flyfish-web/src/main/java/com/flyfish/framework/beans/meta/BeanProperty.java index 84cf37c..8cb75ca 100644 --- a/flyfish-web/src/main/java/com/flyfish/framework/beans/meta/BeanProperty.java +++ b/flyfish-web/src/main/java/com/flyfish/framework/beans/meta/BeanProperty.java @@ -1,13 +1,20 @@ package com.flyfish.framework.beans.meta; import com.flyfish.framework.annotations.Property; +import com.flyfish.framework.utils.StringFormats; import lombok.Data; +import lombok.val; +import org.apache.commons.lang3.ClassUtils; import org.apache.commons.lang3.reflect.FieldUtils; +import org.apache.commons.lang3.reflect.TypeUtils; import org.springframework.beans.BeanUtils; import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.data.mongodb.core.mapping.Document; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; import java.util.*; import java.util.stream.Collectors; @@ -41,6 +48,61 @@ public class BeanProperty { // 类型为object时,拥有子表单 private List children; + /** + * 来自属性解释器构造 + * 支持对象嵌套 + * + * @param descriptor 解释器 + * @return 结果 + */ + public static BeanProperty form(PropertyDescriptor descriptor, Class beanClass) { + BeanProperty property = new BeanProperty(); + property.setName(descriptor.getName()); + property.setType(BeanPropertyType.of(descriptor, beanClass)); + // 尝试获取field + Field field = FieldUtils.getField(beanClass, descriptor.getName(), true); + // 存在field,可以干一些坏事 + if (null != field) { + Property props = AnnotationUtils.findAnnotation(field, Property.class); + if (null != props) { + String parentName = Optional.ofNullable(beanClass.getAnnotation(RestBean.class)).map(RestBean::name).orElse(""); + property.setTitle(props.inherited() ? parentName + props.title() : props.title()); + property.setDescription(props.description()); + property.setReadonly(props.readonly()); + } + } + Class clazz = descriptor.getPropertyType(); + switch (property.getType()) { + case LIST: + // 尝试获取泛型参数,存在时,赋值子表单 + if (null != field && field.isAnnotationPresent(SubBean.class)) { + parseSubClass(field).ifPresent(subClazz -> property.setChildren(from(subClazz))); + } + break; + case OBJECT: + // 有子bean注解才处理 + if (null != field && field.isAnnotationPresent(SubBean.class)) { + property.setChildren(from(clazz)); + } + break; + case DB_REF: + // 当存在db-ref时,解析为动态数据源 + Document document = AnnotationUtils.findAnnotation(clazz, Document.class); + if (null != document) { + property.prop("uri", document.value()); + } else { + property.setType(BeanPropertyType.STRING); + } + break; + case ENUM: + // 为枚举时,填入枚举类型 + String name = StringFormats.camel2Line(ClassUtils.getShortClassName(clazz)); + property.prop("code", name); + break; + } + return property; + } + /** * 类加载并解析属性 * @@ -56,44 +118,35 @@ public class BeanProperty { } /** - * 来自属性解释器构造 - * 支持对象嵌套 + * 解析子类型,用于表格组件 * - * @param descriptor 解释器 + * @param field 反射域 * @return 结果 */ - public static BeanProperty form(PropertyDescriptor descriptor, Class beanClass) { - // 尝试获取field - Field field = FieldUtils.getField(beanClass, descriptor.getName(), true); - // 存在field,可以干一些坏事 - BeanProperty property = new BeanProperty(); - property.setName(descriptor.getName()); - property.setType(BeanPropertyType.of(descriptor, beanClass)); - if (null != field) { - Property props = AnnotationUtils.findAnnotation(field, Property.class); - if (null != props) { - String parentName = Optional.ofNullable(beanClass.getAnnotation(RestBean.class)).map(RestBean::name).orElse(""); - property.setTitle(props.inherited() ? parentName + props.title() : props.title()); - property.setDescription(props.description()); - property.setReadonly(props.readonly()); - } + private static Optional> parseSubClass(Field field) { + // 获取实际的泛型 + Type type = field.getGenericType(); + if (type instanceof ParameterizedType) { + val types = TypeUtils.getTypeArguments((ParameterizedType) type); + return types.entrySet().stream().findFirst().map(entry -> { + Type parsed = entry.getValue(); + if (parsed instanceof Class) { + Class clazz = (Class) parsed; + if (!ClassUtils.isPrimitiveOrWrapper(clazz) && !CharSequence.class.isAssignableFrom(clazz)) { + return clazz; + } + } + return null; + }); } - Class clazz = descriptor.getPropertyType(); - if (property.getType() == BeanPropertyType.OBJECT) { - // 有子bean注解才处理 - if (null != field && field.isAnnotationPresent(SubBean.class)) { - property.setChildren(from(clazz)); - } - } else if (property.getType() == BeanPropertyType.DB_REF) { - // 当存在db-ref时,解析为动态数据源 - RestBean restBean = clazz.getAnnotation(RestBean.class); - if (null != restBean) { - String uri = restBean.value(); - Map props = new HashMap<>(); - props.put("uri", uri); - property.setProps(props); - } + return Optional.empty(); + } + + public BeanProperty prop(String key, Object value) { + if (null == props) { + props = new HashMap<>(); } - return property; + props.put(key, value); + return this; } } diff --git a/flyfish-web/src/main/java/com/flyfish/framework/beans/meta/BeanProps.java b/flyfish-web/src/main/java/com/flyfish/framework/beans/meta/BeanProps.java new file mode 100644 index 0000000..6b20f5c --- /dev/null +++ b/flyfish-web/src/main/java/com/flyfish/framework/beans/meta/BeanProps.java @@ -0,0 +1,11 @@ +package com.flyfish.framework.beans.meta; + +/** + * 枚举常用的bean属性 + * @author wangyu + */ +public interface BeanProps { + + // 表格的列,支持组件化 + String COLUMNS = "columns"; +}