diff --git a/hsweb-commons/hsweb-commons-entity/src/main/java/org/hswebframework/web/commons/entity/TreeSupportEntity.java b/hsweb-commons/hsweb-commons-entity/src/main/java/org/hswebframework/web/commons/entity/TreeSupportEntity.java index 8b78ca15c..ca1a8b2a6 100644 --- a/hsweb-commons/hsweb-commons-entity/src/main/java/org/hswebframework/web/commons/entity/TreeSupportEntity.java +++ b/hsweb-commons/hsweb-commons-entity/src/main/java/org/hswebframework/web/commons/entity/TreeSupportEntity.java @@ -21,7 +21,6 @@ package org.hswebframework.web.commons.entity; import org.hswebframework.web.id.IDGenerator; import org.hswebframwork.utils.RandomUtil; -import org.hswebframwork.utils.StringUtils; import java.math.BigDecimal; import java.util.*; @@ -52,11 +51,6 @@ public interface TreeSupportEntity extends GenericEntity { void setLevel(Integer level); - default void setLevelFromPath() { - if (getPath() != null) - setLevel(getPath().split("-").length); - } - > List getChildren(); /** @@ -85,7 +79,8 @@ public interface TreeSupportEntity extends GenericEntity { List children = parent.getChildren(); if (parent.getPath() == null) { parent.setPath(RandomUtil.randomChar(4)); - parent.setLevelFromPath(); + if (parent.getPath() != null) + parent.setLevel(parent.getPath().split("-").length); } if (children != null) { PK pid = parent.getId(); @@ -104,7 +99,7 @@ public interface TreeSupportEntity extends GenericEntity { } child.setParentId(pid); child.setPath(parent.getPath() + "-" + RandomUtil.randomChar(4)); - child.setLevelFromPath(); + child.setLevel(child.getPath().split("-").length); target.add(child); expandTree2List(child, target, idGenerator); } diff --git a/hsweb-commons/hsweb-commons-entity/src/main/java/org/hswebframework/web/commons/entity/factory/MapperEntityFactory.java b/hsweb-commons/hsweb-commons-entity/src/main/java/org/hswebframework/web/commons/entity/factory/MapperEntityFactory.java index 7950488c7..31da4ab4f 100644 --- a/hsweb-commons/hsweb-commons-entity/src/main/java/org/hswebframework/web/commons/entity/factory/MapperEntityFactory.java +++ b/hsweb-commons/hsweb-commons-entity/src/main/java/org/hswebframework/web/commons/entity/factory/MapperEntityFactory.java @@ -18,23 +18,27 @@ package org.hswebframework.web.commons.entity.factory; -import org.apache.commons.beanutils.BeanUtils; +import com.alibaba.fastjson.JSON; import org.hswebframework.web.NotFoundException; +import org.hswebframwork.utils.ClassUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.lang.reflect.Modifier; import java.util.HashMap; import java.util.Map; +import java.util.Objects; import java.util.function.Supplier; /** * @author zhouhao * @since 3.0 */ +@SuppressWarnings("unchecked") public class MapperEntityFactory implements EntityFactory { - private Map realTypeMapper = new HashMap<>(); - private Logger logger = LoggerFactory.getLogger(this.getClass()); + private Map realTypeMapper = new HashMap<>(); + private Logger logger = LoggerFactory.getLogger(this.getClass()); + private Map copierCache = new HashMap<>(); public MapperEntityFactory() { } @@ -48,45 +52,74 @@ public class MapperEntityFactory implements EntityFactory { return this; } + public MapperEntityFactory addCopier(PropertyCopier copier) { + Class source = ClassUtils.getGenericType(copier.getClass(), 0); + Class target = ClassUtils.getGenericType(copier.getClass(), 1); + if (source == null || source == Object.class) { + throw new UnsupportedOperationException("generic type " + source + " not support"); + } + if (target == null || target == Object.class) { + throw new UnsupportedOperationException("generic type " + target + " not support"); + } + addCopier(source, target, copier); + return this; + } + + public MapperEntityFactory addCopier(Class source, Class target, PropertyCopier copier) { + copierCache.put(getCopierCacheKey(source, target), copier); + return this; + } + + private String getCopierCacheKey(Class source, Class target) { + return source.getName().concat("->").concat(target.getName()); + + } + @Override public T copyProperties(S source, T target) { + Objects.requireNonNull(source); + Objects.requireNonNull(target); try { - // TODO: 17-3-30 应该设计为可自定义 - BeanUtils.copyProperties(target, source); + PropertyCopier copier = copierCache.get(getCopierCacheKey(source.getClass(), target.getClass())); + if (null != copier) return copier.copyProperties(source, target); + + return JSON.parseObject(JSON.toJSONString(source), (Class) target.getClass()); } catch (Exception e) { logger.warn("copy properties error", e); } return target; } + protected Mapper initCache(Class beanClass) { + Mapper mapper = null; + Class realType = null; + if (!Modifier.isInterface(beanClass.getModifiers()) && !Modifier.isAbstract(beanClass.getModifiers())) { + realType = beanClass; + } + //尝试使用 Simple类,如: package.SimpleUserBean + if (realType == null) { + String simpleClassName = beanClass.getPackage().getName().concat(".Simple").concat(beanClass.getSimpleName()); + try { + realType = (Class) Class.forName(simpleClassName); + } catch (ClassNotFoundException e) { + throw new NotFoundException(e.getMessage()); + } + } + if (realType != null) { + mapper = new Mapper<>(realType, new DefaultInstanceGetter(realType)); + realTypeMapper.put(beanClass, mapper); + } + return mapper; + } + @Override - @SuppressWarnings("unchecked") public T newInstance(Class beanClass) { if (beanClass == null) return null; Mapper mapper = realTypeMapper.get(beanClass); if (mapper != null) return mapper.getInstanceGetter().get(); - synchronized (beanClass) { - mapper = realTypeMapper.get(beanClass); - if (mapper != null) return mapper.getInstanceGetter().get(); - Class realType = null; - if (!Modifier.isInterface(beanClass.getModifiers()) && !Modifier.isAbstract(beanClass.getModifiers())) { - realType = beanClass; - } - //尝试使用 Simple类,如: package.SimpleUserBean - if (realType == null) { - String simpleClassName = beanClass.getPackage().getName().concat(".Simple").concat(beanClass.getSimpleName()); - try { - realType = (Class) Class.forName(simpleClassName); - } catch (ClassNotFoundException e) { - throw new NotFoundException(e.getMessage()); - } - } - if (realType != null) { - mapper = new Mapper<>(realType, new DefaultInstanceGetter(realType)); - realTypeMapper.put(beanClass, mapper); - return mapper.getInstanceGetter().get(); - } - } + mapper = initCache(beanClass); + if (mapper != null) return mapper.getInstanceGetter().get(); + throw new NotFoundException("can't create instance for " + beanClass); } @@ -97,7 +130,10 @@ public class MapperEntityFactory implements EntityFactory { if (null != mapper) { return mapper.getTarget(); } - return null; + mapper = initCache(beanClass); + if (mapper != null) + return mapper.getTarget(); + return beanClass; } public static class Mapper { diff --git a/hsweb-commons/hsweb-commons-entity/src/main/java/org/hswebframework/web/commons/entity/factory/PropertyCopier.java b/hsweb-commons/hsweb-commons-entity/src/main/java/org/hswebframework/web/commons/entity/factory/PropertyCopier.java new file mode 100644 index 000000000..c137e8720 --- /dev/null +++ b/hsweb-commons/hsweb-commons-entity/src/main/java/org/hswebframework/web/commons/entity/factory/PropertyCopier.java @@ -0,0 +1,11 @@ +package org.hswebframework.web.commons.entity.factory; + +/** + * 属性复制接口,用于自定义属性复制 + * + * @author zhouhao + * @since 3.0 + */ +public interface PropertyCopier { + T copyProperties(S source, T target); +}