
org.swiftboot.web.command.BasePopulateCommand Maven / Gradle / Ivy
Show all versions of swiftboot-web Show documentation
package org.swiftboot.web.command;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.annotations.ApiModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.swiftboot.collections.CollectionUtils;
import org.swiftboot.data.model.entity.IdPersistable;
import org.swiftboot.util.BeanUtils;
import org.swiftboot.util.GenericUtils;
import org.swiftboot.web.Info;
import org.swiftboot.web.R;
import org.swiftboot.web.annotation.PopulateIgnore;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Optional;
import java.util.function.Predicate;
/**
* 提供将参数填入实体类的方法 populateEntity() 和创建 Command 类所对应的实体类的方法 createEntity()
* 要求实体类 E 必须有无参数的构造函数,除了用注解 {@link JsonIgnore} 或 {@link PopulateIgnore} 标注的属性之外,
* Command 中存在的属性实体类也必须存在(名称和类型一一对应),否则抛出异常。
*
* @param 对应的实体类
* @author swiftech
*/
@ApiModel
public abstract class BasePopulateCommand
extends HttpCommand {
private static final Logger log = LoggerFactory.getLogger(BasePopulateCommand.class);
/**
* 创建对应的实体类 P 的实例并且用属性值填充实例,
* 除了用注解 {@link JsonIgnore} 或 {@link PopulateIgnore} 标注的属性之外,
* Command 中存在的属性实体类也必须存在(名称和类型一一对应),否则抛出异常。
*
* @return
*/
public P createEntity() {
P ret;
Class
entityClass = (Class
) GenericUtils.ancestorGenericClass(getClass());
if (entityClass == null) {
throw new RuntimeException(Info.get(BasePopulateCommand.class, R.REFLECT_TYPE_OF_ENTITY_FAIL));
}
try {
Constructor
constructor = entityClass.getConstructor();
ret = constructor.newInstance();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(Info.get(BasePopulateCommand.class, R.CONSTRUCT_ENTITY_FAIL1, entityClass));
}
this.doPopulate(entityClass, ret, true);
return ret;
}
/**
* 将 Command 中的属性值填充至实体类中,包括继承自 BasePopulateCommand 的类实例和集合。
* 除了用注解 {@link JsonIgnore} 或 {@link PopulateIgnore} 标注的属性之外,
* Command 中存在的属性实体类也必须存在,否则抛出异常。
*
* @param entity
* @return
*/
public P populateEntity(P entity) {
this.doPopulate((Class
) entity.getClass(), entity, true);
return entity;
}
/**
* 将 Command 中的属性值填充至实体类中。
* 除了用注解 {@link JsonIgnore} 或 {@link PopulateIgnore} 标注的属性之外,
* Command 中存在的属性实体类也必须存在,否则抛出异常。
*
* @param entity
* @return
* @since 1.1
*/
public P populateEntityNoRecursive(P entity) {
this.doPopulate((Class
) entity.getClass(), entity, false);
return entity;
}
/**
* internal populating
*
* @param entityClass
* @param entity
* @param recursive
*/
private void doPopulate(Class
entityClass, P entity, boolean recursive) {
Collection allFields = BeanUtils.getFieldsIgnore(this.getClass(), JsonIgnore.class, PopulateIgnore.class);
for (Field srcField : allFields) {
// 处理嵌套
if (recursive) {
Field targetField;
Object target;
try {
targetField = BeanUtils.getDeclaredField(entity, srcField.getName());
target = BeanUtils.forceGetProperty(entity, targetField);
} catch (Exception e) {
log.warn(e.getLocalizedMessage());
continue;
}
if (BasePopulateCommand.class.isAssignableFrom(srcField.getType())) {
BasePopulateCommand sub = (BasePopulateCommand) BeanUtils.forceGetProperty(this, srcField);
if (sub == null) {
// System.out.printf("Ignore populate field: %s%n", srcField);
continue;
}
try {
if (target == null) {
// System.out.println("Create sub entity");
IdPersistable relEntity = sub.createEntity();
BeanUtils.forceSetProperty(entity, targetField, relEntity);
}
else {
// System.out.println("Populate sub entity");
IdPersistable relEntity = (IdPersistable) target;
sub.populateEntity(relEntity);
}
} catch (Exception e) {
e.printStackTrace();
continue;
}
continue;
}
else if (Collection.class.isAssignableFrom(srcField.getType())) {
Collection> items = (Collection>) BeanUtils.forceGetProperty(this, srcField);
try {
if (target == null) {
// Populate collections for new created entity.
Collection