From 57dd3022285466874670210df8e6bac3c2b52003 Mon Sep 17 00:00:00 2001 From: even <827656971@qq.com> Date: Mon, 28 Apr 2025 16:23:54 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B7=A5=E5=85=B7=E7=B1=BB=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E8=BF=81=E7=A7=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dependencies/pom.xml | 7 +- modules/module-ci-process-biz/pom.xml | 4 + .../context/ApplicationContextContext.java | 18 ++ .../resolver/AnnotationResourceResolver.java | 126 +++++++++ .../module/process/core/util/BeanUtils.java | 42 +++ .../entity/PipelineFollowEntity.java | 20 ++ .../impl/PipelineFollowServiceImpl.java | 97 +++++++ .../definition/dao/PipelineFollowDao.java | 59 ++++ .../process/toolkit/beans/BeanMapper.java | 168 +++++++++++ .../toolkit/beans/annotation/Mapper.java | 18 ++ .../toolkit/beans/annotation/Mappers.java | 12 + .../toolkit/beans/annotation/Mapping.java | 14 + .../toolkit/beans/annotation/Mappings.java | 12 + .../beans/metadata/BeanMapperRegister.java | 267 ++++++++++++++++++ .../toolkit/beans/model/BeanMapping.java | 12 + .../toolkit/beans/model/FieldMapping.java | 13 + 16 files changed, 888 insertions(+), 1 deletion(-) create mode 100644 modules/module-ci-process-biz/src/main/java/cd/casic/module/process/core/context/ApplicationContextContext.java create mode 100644 modules/module-ci-process-biz/src/main/java/cd/casic/module/process/core/resolver/AnnotationResourceResolver.java create mode 100644 modules/module-ci-process-biz/src/main/java/cd/casic/module/process/core/util/BeanUtils.java create mode 100644 modules/module-ci-process-biz/src/main/java/cd/casic/module/process/pipeline/definition/entity/PipelineFollowEntity.java create mode 100644 modules/module-ci-process-biz/src/main/java/cd/casic/module/process/pipeline/definition/impl/PipelineFollowServiceImpl.java create mode 100644 modules/module-ci-process-biz/src/main/java/cd/casic/module/process/toolkit/beans/BeanMapper.java create mode 100644 modules/module-ci-process-biz/src/main/java/cd/casic/module/process/toolkit/beans/annotation/Mapper.java create mode 100644 modules/module-ci-process-biz/src/main/java/cd/casic/module/process/toolkit/beans/annotation/Mappers.java create mode 100644 modules/module-ci-process-biz/src/main/java/cd/casic/module/process/toolkit/beans/annotation/Mapping.java create mode 100644 modules/module-ci-process-biz/src/main/java/cd/casic/module/process/toolkit/beans/annotation/Mappings.java create mode 100644 modules/module-ci-process-biz/src/main/java/cd/casic/module/process/toolkit/beans/metadata/BeanMapperRegister.java create mode 100644 modules/module-ci-process-biz/src/main/java/cd/casic/module/process/toolkit/beans/model/BeanMapping.java create mode 100644 modules/module-ci-process-biz/src/main/java/cd/casic/module/process/toolkit/beans/model/FieldMapping.java diff --git a/dependencies/pom.xml b/dependencies/pom.xml index e94953c..36df6fc 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -85,7 +85,7 @@ 2.6.10 2.9.3 2.3.0 - + 3.2.1 @@ -676,6 +676,11 @@ ${resilience4j-circuitbreaker.version} + + ognl + ognl + ${ognl.version} + diff --git a/modules/module-ci-process-biz/pom.xml b/modules/module-ci-process-biz/pom.xml index ce94863..ed81253 100644 --- a/modules/module-ci-process-biz/pom.xml +++ b/modules/module-ci-process-biz/pom.xml @@ -38,6 +38,10 @@ cd.casic.boot spring-boot-starter-security + + ognl + ognl + \ No newline at end of file diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/core/context/ApplicationContextContext.java b/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/core/context/ApplicationContextContext.java new file mode 100644 index 0000000..a33bb12 --- /dev/null +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/core/context/ApplicationContextContext.java @@ -0,0 +1,18 @@ +package cd.casic.module.process.core.context; + +import org.springframework.context.ConfigurableApplicationContext; + +public class ApplicationContextContext { + private static ConfigurableApplicationContext applicationContext; + + public ApplicationContextContext() { + } + + public static ConfigurableApplicationContext getApplicationContext() { + return applicationContext; + } + + public static void setApplicationContext(ConfigurableApplicationContext applicationContext) { + ApplicationContextContext.applicationContext = applicationContext; + } +} diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/core/resolver/AnnotationResourceResolver.java b/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/core/resolver/AnnotationResourceResolver.java new file mode 100644 index 0000000..4485c94 --- /dev/null +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/core/resolver/AnnotationResourceResolver.java @@ -0,0 +1,126 @@ +package cd.casic.module.process.core.resolver; + +import cd.casic.module.process.core.context.ApplicationContextContext; +import org.springframework.beans.BeansException; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.core.env.StandardEnvironment; +import org.springframework.core.io.Resource; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; +import org.springframework.core.type.AnnotationMetadata; +import org.springframework.core.type.ClassMetadata; +import org.springframework.core.type.classreading.MetadataReader; +import org.springframework.core.type.classreading.SimpleMetadataReaderFactory; +import org.springframework.util.ClassUtils; +import org.springframework.util.StringUtils; + +import java.lang.annotation.Annotation; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +public class AnnotationResourceResolver { + private static final PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); + private static final SimpleMetadataReaderFactory register = new SimpleMetadataReaderFactory(); + private static final StandardEnvironment environment = new StandardEnvironment(); + + public AnnotationResourceResolver() { + } + + public static Set resolveBeans(String pkgPath, Class annoClazz) { + Set clazzSet = new HashSet(); + ConfigurableApplicationContext applicationContext = ApplicationContextContext.getApplicationContext(); + Map beansWithAnnotationMap = applicationContext.getBeansWithAnnotation(annoClazz); + Iterator var5 = beansWithAnnotationMap.entrySet().iterator(); + + while(var5.hasNext()) { + Map.Entry entry = (Map.Entry)var5.next(); + Object object = entry.getValue(); + Class clazz = object.getClass(); + clazzSet.add(clazz); + } + + return clazzSet; + } + + public static Set resolve(String pkgPath, Class annoClazz) { + Set paths = new HashSet(); + + try { + String pathPackage = getResourcePath(pkgPath); + Resource[] resources = resolver.getResources(pathPackage); + + for(int i = 0; i < resources.length; ++i) { + Resource resource = resources[i]; + MetadataReader metadataReader = register.getMetadataReader(resource); + AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata(); + if (annotationMetadata.hasAnnotation(annoClazz.getName())) { + ClassMetadata classMetadata = metadataReader.getClassMetadata(); + String className = classMetadata.getClassName(); + ClassLoader classLoader = getClassLoader(); + Class clazz = classLoader.loadClass(className); + paths.add(clazz); + } + } + + return paths; + } catch (Exception var13) { + throw new RuntimeException(var13); + } + } + + public static Set resolveFromBeans(String pkgPath, Class annoClazz) { + Set paths = new HashSet(); + ConfigurableApplicationContext applicationContext = ApplicationContextContext.getApplicationContext(); + + try { + String pathPackage = getResourcePath(pkgPath); + Resource[] resources = resolver.getResources(pathPackage); + + for(int i = 0; i < resources.length; ++i) { + Resource resource = resources[i]; + MetadataReader metadataReader = register.getMetadataReader(resource); + AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata(); + if (annotationMetadata.hasAnnotation(annoClazz.getName())) { + ClassMetadata classMetadata = metadataReader.getClassMetadata(); + String className = classMetadata.getClassName(); + ClassLoader classLoader = getClassLoader(); + Class clazz = classLoader.loadClass(className); + + try { + Object bean = applicationContext.getBean(clazz); + if (bean == null) { + continue; + } + } catch (BeansException var15) { + continue; + } + + paths.add(clazz); + } + } + + return paths; + } catch (Exception var16) { + throw new RuntimeException(var16); + } + } + + public static String getResourcePath(String packagePath) { + if (StringUtils.isEmpty(packagePath)) { + return ""; + } else { + String resourcePath = "classpath*:" + ClassUtils.convertClassNameToResourcePath(environment.resolveRequiredPlaceholders(packagePath)) + "/**/*.class"; + return resourcePath; + } + } + + static ClassLoader getClassLoader() { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + if (classLoader == null) { + classLoader = ClassLoader.getSystemClassLoader(); + } + + return classLoader; + } +} diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/core/util/BeanUtils.java b/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/core/util/BeanUtils.java new file mode 100644 index 0000000..accccda --- /dev/null +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/core/util/BeanUtils.java @@ -0,0 +1,42 @@ +package cd.casic.module.process.core.util; + +import cd.casic.ci.commons.bean.exception.SystemException; + +import java.beans.PropertyDescriptor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +public class BeanUtils { + public BeanUtils() { + } + + public static PropertyDescriptor getPropertyDescriptor(Class clazz, String propertyName) { + try { + StringBuffer sb = new StringBuffer(); + Field f = null; + + try { + f = clazz.getDeclaredField(propertyName); + } catch (NoSuchFieldException var8) { + return null; + } + + if (f == null) { + throw new SystemException("propertyName:" + propertyName + " not found."); + } else { + String var10000 = propertyName.substring(0, 1).toUpperCase(); + String methodEnd = var10000 + propertyName.substring(1); + sb.append("set" + methodEnd); + Method setMethod = clazz.getDeclaredMethod(sb.toString(), f.getType()); + sb.delete(0, sb.length()); + sb.append("get" + methodEnd); + Method getMethod = clazz.getDeclaredMethod(sb.toString()); + PropertyDescriptor pd = new PropertyDescriptor(propertyName, getMethod, setMethod); + return pd; + } + } catch (Exception var9) { + throw new SystemException("系统错误"); +// throw new SystemException(var9); + } + } +} diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/pipeline/definition/entity/PipelineFollowEntity.java b/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/pipeline/definition/entity/PipelineFollowEntity.java new file mode 100644 index 0000000..b395732 --- /dev/null +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/pipeline/definition/entity/PipelineFollowEntity.java @@ -0,0 +1,20 @@ +package cd.casic.module.process.pipeline.definition.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import lombok.Data; + +//@Table(name="pip_other_follow") +@Data +public class PipelineFollowEntity { +// @Id +// @GeneratorValue(length = 12) +// @Column(name = "id") + @TableId + private String id; + +// @Column(name = "pipeline_id") + private String pipelineId; + +// @Column(name = "user_id") + private String userId ; +} diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/pipeline/definition/impl/PipelineFollowServiceImpl.java b/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/pipeline/definition/impl/PipelineFollowServiceImpl.java new file mode 100644 index 0000000..48b6a33 --- /dev/null +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/pipeline/definition/impl/PipelineFollowServiceImpl.java @@ -0,0 +1,97 @@ +package cd.casic.module.process.pipeline.definition.impl; + +import cd.casic.ci.commons.bean.process.definition.Pipeline; +import cd.casic.ci.commons.bean.process.definition.PipelineFollow; +import cd.casic.ci.commons.bean.process.definition.PipelineFollowQuery; +import cd.casic.ci.commons.bean.utils.PipelineUtil; +import cd.casic.framework.commons.exception.ServiceException; +import cd.casic.module.process.pipeline.definition.entity.PipelineFollowEntity; +import cd.casic.module.process.process.definition.PipelineFollowService; +import cd.casic.module.process.process.definition.dao.PipelineFollowDao; +import cd.casic.module.process.toolkit.beans.BeanMapper; +import jakarta.annotation.Resource; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.Collections; +import java.util.List; + +public class PipelineFollowServiceImpl implements PipelineFollowService { + @Resource + PipelineFollowDao pipelineFollowDao; + + @Override + public void updateFollow(PipelineFollow pipelineFollow) { + Pipeline pipeline = pipelineFollow.getPipeline(); + String pipelineId = pipeline.getId(); + if (!PipelineUtil.isNoNull(pipelineId)){ + throw new ServiceException(50001,"流水线id不能为空。"); + } +// TODO +// String userId = LoginContext.getLoginId(); + String userId = ""; + List list = + pipelineFollowDao.findOneUserFollowPipeline(userId, pipelineId); + //用户为收藏该流水线 + if (list.isEmpty()){ + PipelineFollowEntity followEntity = BeanMapper.map(pipelineFollow, PipelineFollowEntity.class); + followEntity.setUserId(userId); + String follow = pipelineFollowDao.createFollow(followEntity); + if (!PipelineUtil.isNoNull(follow)){ + throw new ServiceException(50001,"收藏失败"); + } + //用户已收藏该流水线 + }else { + deleteFollow(list.get(0).getId()); + } + } + + @Override + public List findUserFollowPipeline(String userId){ + List list = + pipelineFollowDao.findUserFollowPipeline(userId); + return BeanMapper.mapList(list, PipelineFollow.class); + } + + @Override + public List findFollowQueryList(PipelineFollowQuery followQuery){ + List list = + pipelineFollowDao.findFollowQueryList(followQuery); + if (list == null || list.isEmpty()){ + return Collections.emptyList(); + } + return BeanMapper.mapList(list, PipelineFollow.class); + } + + @Override + public void deleteFollow(String followId) { + pipelineFollowDao.deleteFollow(followId); + } + + + public void deletePipelineFollow(String pipelineId){ + PipelineFollowQuery followQuery = new PipelineFollowQuery(); + followQuery.setPipelineId(pipelineId); + List list = pipelineFollowDao.findFollowQueryList(followQuery); + + for (PipelineFollowEntity pipelineFollowEntity : list) { + deleteFollow(pipelineFollowEntity.getId()); + } + + } + + @Override + public PipelineFollow findOneFollow(String followId) { + return BeanMapper.map(pipelineFollowDao.findOneFollow(followId), PipelineFollow.class); + } + + @Override + public List findAllFollow() { + return BeanMapper.mapList(pipelineFollowDao.findAllFollow(), PipelineFollow.class); + } + + @Override + public List findAllFollowList(List idList) { + List followList = pipelineFollowDao.findAllFollowList(idList); + return BeanMapper.mapList(followList, PipelineFollow.class); + } +} diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/process/definition/dao/PipelineFollowDao.java b/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/process/definition/dao/PipelineFollowDao.java index 58b1299..aef549e 100644 --- a/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/process/definition/dao/PipelineFollowDao.java +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/process/definition/dao/PipelineFollowDao.java @@ -1,8 +1,14 @@ package cd.casic.module.process.process.definition.dao; +import cd.casic.ci.commons.bean.process.definition.PipelineFollowQuery; import cd.casic.framework.mybatis.core.mapper.BaseMapperX; +import cd.casic.module.process.pipeline.definition.entity.PipelineFollowEntity; import cd.casic.module.process.process.definition.dataobject.PipelineFollowDo; import org.apache.ibatis.annotations.Mapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.BeanPropertyRowMapper; + +import java.util.List; /** * @author by mianbin @@ -12,4 +18,57 @@ import org.apache.ibatis.annotations.Mapper; */ @Mapper public interface PipelineFollowDao extends BaseMapperX { + + /** + * 创建收藏 + * @param pipelineFollowEntity 收藏 + * @return 收藏id + */ + public String createFollow(PipelineFollowEntity pipelineFollowEntity); + + /** + * 删除收藏 + * @param followId 收藏id + */ + public void deleteFollow(String followId); + + /** + * 更新收藏 + * @param pipelineFollowEntity 更新信息 + */ + public void updateFollow(PipelineFollowEntity pipelineFollowEntity); + + /** + * 查询单个收藏信息 + * @param followId 收藏id + * @return 收藏信息 + */ + public PipelineFollowEntity findOneFollow(String followId); + + /** + * 查询所有收藏 + * @return 收藏集合 + */ + public List findAllFollow(); + + + public List findAllFollowList(List idList); + + /** + * 查询用户是否收藏该流水线 + * @param userId 用户id + * @param pipelineId 流水线id + * @return 收藏信息 + */ + public List findOneUserFollowPipeline(String userId, String pipelineId); + + /** + * 查询用户是藏的流水线 + * @param userId 用户id + * @return 收藏信息 + */ + public List findUserFollowPipeline(String userId); + + + public List findFollowQueryList(PipelineFollowQuery followQuery); } diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/toolkit/beans/BeanMapper.java b/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/toolkit/beans/BeanMapper.java new file mode 100644 index 0000000..cd3ecef --- /dev/null +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/toolkit/beans/BeanMapper.java @@ -0,0 +1,168 @@ +package cd.casic.module.process.toolkit.beans; + +import cd.casic.ci.commons.bean.exception.SystemException; +import cd.casic.module.process.core.util.BeanUtils; +import cd.casic.module.process.toolkit.beans.metadata.BeanMapperRegister; +import cd.casic.module.process.toolkit.beans.model.BeanMapping; +import cd.casic.module.process.toolkit.beans.model.FieldMapping; +import ognl.Ognl; +import ognl.OgnlException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.beans.PropertyDescriptor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class BeanMapper { + private static Logger logger = LoggerFactory.getLogger(BeanMapper.class); + + public BeanMapper() { + } + + public static T map(Object sourceObject, Class targetClz) { + if (sourceObject == null) { + return null; + } else if (targetClz == null) { + throw new SystemException("targetClass must not be null."); + } else { + try { + Class sourceClz = sourceObject.getClass(); + BeanMapping beanMapping = BeanMapperRegister.getBeanMapping(sourceClz, targetClz); + if (beanMapping == null) { + throw new SystemException(String.format("bean mapper not found,source:%s,target:%s.", sourceClz.getName(), targetClz.getName())); + } else { + T targetObject = targetClz.newInstance(); + List propertyMappingList = beanMapping.getPropertyMappingList(); + Iterator var6 = propertyMappingList.iterator(); + + while(var6.hasNext()) { + FieldMapping propertyMapping = (FieldMapping)var6.next(); + String source = propertyMapping.getSource(); + String target = propertyMapping.getTarget(); + + try { + Object fieldValue; + if (isComplexField(source)) { + fieldValue = getParentFiled(sourceObject, source); + if (fieldValue == null) { + continue; + } + } + + fieldValue = Ognl.getValue(source, sourceObject); + if (fieldValue != null) { + if (isComplexField(target)) { + initParentFieldIfNull(targetObject, target); + } + + Ognl.setValue(target, targetObject, fieldValue); + } + } catch (OgnlException var11) { + throw new SystemException("表达式解析失败"); + } + } + + return targetObject; + } + } catch (InstantiationException var12) { +// throw new SystemException(var12); + throw new SystemException("系统错误"); + } catch (IllegalAccessException var13) { +// throw new SystemException(var13); + throw new SystemException("系统错误"); + } + } + } + + static boolean isComplexField(String exp) { + return exp.contains("."); + } + + static Object getParentFiled(Object sourceObject, String exp) { + String[] arr = exp.split("\\."); + String fieldName = arr[0]; + PropertyDescriptor fieldPd = BeanUtils.getPropertyDescriptor(sourceObject.getClass(), fieldName); + Method fieldReadMethod = fieldPd.getReadMethod(); + if (!Modifier.isPublic(fieldReadMethod.getDeclaringClass().getModifiers())) { + fieldReadMethod.setAccessible(true); + } + + try { + Object fieldValue = fieldReadMethod.invoke(sourceObject); + return fieldValue; + } catch (IllegalAccessException var7) { +// throw new SystemException(var7); + throw new SystemException("系统错误"); + } catch (InvocationTargetException var8) { +// throw new SystemException(var8); + throw new SystemException("系统错误"); + } + } + + static void initParentFieldIfNull(Object targetObject, String exp) { + if (exp.contains(".")) { + String[] arr = exp.split("\\."); + String fieldName = arr[0]; + + try { + PropertyDescriptor fieldPd = BeanUtils.getPropertyDescriptor(targetObject.getClass(), fieldName); + Method fieldReadMethod = fieldPd.getReadMethod(); + if (!Modifier.isPublic(fieldReadMethod.getDeclaringClass().getModifiers())) { + fieldReadMethod.setAccessible(true); + } + + Object fieldValue = fieldReadMethod.invoke(targetObject); + if (fieldValue == null) { + Class fieldType = fieldPd.getPropertyType(); + fieldValue = fieldType.newInstance(); + if (fieldValue == null) { + throw new SystemException(String.format("init field value error.", fieldName)); + } else { + Method writeMethod = fieldPd.getWriteMethod(); + if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) { + writeMethod.setAccessible(true); + } + + writeMethod.invoke(targetObject, fieldValue); + } + } + } catch (IllegalAccessException var9) { +// throw new SystemException(var9); + throw new SystemException("系统错误"); + } catch (InvocationTargetException var10) { +// throw new SystemException(var10); + throw new SystemException("系统错误"); + } catch (InstantiationException var11) { +// throw new SystemException(var11); + throw new SystemException("系统错误"); + } + } + } + + public static List mapList(List sourceObjectList, Class targetClz) { + List targetList = new ArrayList(); + if (sourceObjectList != null && sourceObjectList.size() != 0) { + try { + Iterator var3 = sourceObjectList.iterator(); + + while(var3.hasNext()) { + Object sourceObject = var3.next(); + T targetObject = map(sourceObject, targetClz); + targetList.add(targetObject); + } + + return targetList; + } catch (Exception var6) { +// throw new SystemException(var6); + throw new SystemException("系统错误"); + } + } else { + return targetList; + } + } +} diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/toolkit/beans/annotation/Mapper.java b/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/toolkit/beans/annotation/Mapper.java new file mode 100644 index 0000000..eb8ae3a --- /dev/null +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/toolkit/beans/annotation/Mapper.java @@ -0,0 +1,18 @@ +package cd.casic.module.process.toolkit.beans.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface Mapper { + Class source() default Object.class; + + Class target() default Object.class; + + String targetName() default ""; + + String targetAlias() default ""; +} diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/toolkit/beans/annotation/Mappers.java b/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/toolkit/beans/annotation/Mappers.java new file mode 100644 index 0000000..fd62b1b --- /dev/null +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/toolkit/beans/annotation/Mappers.java @@ -0,0 +1,12 @@ +package cd.casic.module.process.toolkit.beans.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface Mappers { + Mapper[] value(); +} diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/toolkit/beans/annotation/Mapping.java b/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/toolkit/beans/annotation/Mapping.java new file mode 100644 index 0000000..0e62e78 --- /dev/null +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/toolkit/beans/annotation/Mapping.java @@ -0,0 +1,14 @@ +package cd.casic.module.process.toolkit.beans.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD, ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface Mapping { + String source() default ""; + + String target() default ""; +} \ No newline at end of file diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/toolkit/beans/annotation/Mappings.java b/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/toolkit/beans/annotation/Mappings.java new file mode 100644 index 0000000..5e7d8f2 --- /dev/null +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/toolkit/beans/annotation/Mappings.java @@ -0,0 +1,12 @@ +package cd.casic.module.process.toolkit.beans.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD, ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface Mappings { + Mapping[] value(); +} \ No newline at end of file diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/toolkit/beans/metadata/BeanMapperRegister.java b/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/toolkit/beans/metadata/BeanMapperRegister.java new file mode 100644 index 0000000..f31ef2f --- /dev/null +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/toolkit/beans/metadata/BeanMapperRegister.java @@ -0,0 +1,267 @@ +package cd.casic.module.process.toolkit.beans.metadata; + +import cd.casic.ci.commons.bean.exception.SystemException; +import cd.casic.module.process.core.resolver.AnnotationResourceResolver; +import cd.casic.module.process.toolkit.beans.annotation.Mapper; +import cd.casic.module.process.toolkit.beans.annotation.Mappers; +import cd.casic.module.process.toolkit.beans.annotation.Mapping; +import cd.casic.module.process.toolkit.beans.annotation.Mappings; +import cd.casic.module.process.toolkit.beans.model.BeanMapping; +import cd.casic.module.process.toolkit.beans.model.FieldMapping; +import org.springframework.util.StringUtils; + +import java.lang.reflect.Field; +import java.util.*; + +public class BeanMapperRegister { + private static Map mappers = new HashMap(); + private static final String RELA_SPLIT = "->"; + + public BeanMapperRegister() { + } + + public void scan(String basePackage) { + Set classSet = AnnotationResourceResolver.resolve(basePackage, Mapper.class); + Iterator var3; + Class cls; + if (classSet != null && classSet.size() > 0) { + var3 = classSet.iterator(); + + while(var3.hasNext()) { + cls = (Class)var3.next(); + Mapper mapper = (Mapper)cls.getAnnotation(Mapper.class); + this.parse(cls, mapper); + } + } + + classSet = AnnotationResourceResolver.resolve(basePackage, Mappers.class); + if (classSet != null && classSet.size() > 0) { + var3 = classSet.iterator(); + + while(var3.hasNext()) { + cls = (Class)var3.next(); + Mappers mappers = (Mappers)cls.getAnnotation(Mappers.class); + Mapper[] var6 = mappers.value(); + int var7 = var6.length; + + for(int var8 = 0; var8 < var7; ++var8) { + Mapper mapper = var6[var8]; + this.parse(cls, mapper); + } + } + } + + } + + public BeanMapperRegister map(Class sourceClass, Class targetClass) { + BeanMapping mapperMeta = new BeanMapping(); + mapperMeta.setSourceClass(sourceClass); + mapperMeta.setTargetClass(targetClass); + return this; + } + + void parse(Class mapperClz, Mapper mapper) { + BeanMapping beanMapping = null; + + try { + beanMapping = this.parseBeanMapping(mapperClz, mapper); + } catch (Exception var7) { + return; + } + + mappers.put(getBeanMappingKey(beanMapping), beanMapping); + BeanMapping reverseBeanMapping = null; + + try { + reverseBeanMapping = this.parseBeanMappingForReverse(beanMapping); + } catch (Exception var6) { + return; + } + + mappers.put(getBeanMappingKey(reverseBeanMapping), reverseBeanMapping); + } + + public BeanMapping parseBeanMappingForReverse(BeanMapping classMapping) { + BeanMapping reverseBeanMapping = new BeanMapping(); + reverseBeanMapping.setSourceClass(classMapping.getTargetClass()); + reverseBeanMapping.setTargetClass(classMapping.getSourceClass()); + Iterator var3 = classMapping.getPropertyMappingList().iterator(); + + while(var3.hasNext()) { + FieldMapping item = (FieldMapping)var3.next(); + FieldMapping propertyMapping = new FieldMapping(); + propertyMapping.setSource(item.getTarget()); + propertyMapping.setTarget(item.getSource()); + reverseBeanMapping.getPropertyMappingList().add(propertyMapping); + } + + return reverseBeanMapping; + } + + BeanMapping parseBeanMapping(Class mapperClz, Mapper mapper) { + try { + BeanMapping beanMapping = new BeanMapping(); + Class sourceClass = mapper.source(); + if (sourceClass == Object.class) { + sourceClass = mapperClz; + } + + Class targetClass = mapper.target(); + if (targetClass == Object.class) { + String targetName = mapper.targetName(); + if (!StringUtils.isEmpty(targetName)) { + targetClass = this.getClassByName(targetName); + } else { + targetClass = this.findTargetClassByRule(sourceClass); + } + } + + beanMapping.setSourceClass(sourceClass); + beanMapping.setTargetClass(targetClass); + List propertyMappingList = this.parsePropertiesMapping(beanMapping); + beanMapping.setPropertyMappingList(propertyMappingList); + return beanMapping; + } catch (Exception var7) { + throw new SystemException(String.format("parse class:%s failed.", mapperClz.getName())); +// throw new SystemException(String.format("parse class:%s failed.", mapperClz.getName()), var7); + } + } + + public Class findTargetClassByRule(Class sourceClass) { + String className = sourceClass.getName(); + String[] arr = className.split("\\."); + StringBuffer buffer = new StringBuffer(); + + for(int i = 0; i < arr.length; ++i) { + String item = arr[i]; + if (i < arr.length - 2) { + buffer.append(item).append("."); + } else if (i == arr.length - 2) { + buffer.append("entity").append("."); + } else if (i == arr.length - 1) { + String entityName = item + "Entity"; + buffer.append(entityName); + } + } + + String targetName = buffer.toString(); + Class targetClass = this.getClassByName(targetName); + return targetClass; + } + + Class getClassByName(String className) { + try { + Class targetClass = Class.forName(className); + return targetClass; + } catch (ClassNotFoundException var6) { + try { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + Class clazz = classLoader.loadClass(className); + return clazz; + } catch (ClassNotFoundException var5) { + throw new SystemException("class not found:" + className); +// throw new SystemException("class not found:" + className, var6); + } + } + } + + List parsePropertiesMapping(BeanMapping classMapping) { + List propertyMappingList = new ArrayList(); + Class sourceClz = classMapping.getSourceClass(); + Class targetClz = classMapping.getTargetClass(); + Field[] fields = sourceClz.getDeclaredFields(); + if (fields != null && fields.length > 0) { + } + + Field[] var6 = fields; + int var7 = fields.length; + + for(int var8 = 0; var8 < var7; ++var8) { + Field field = var6[var8]; + if (field.getAnnotation(Mapping.class) != null) { + Mapping mapping = (Mapping)field.getAnnotation(Mapping.class); + this.validField(sourceClz, mapping.source()); + this.validField(targetClz, mapping.target()); + FieldMapping propertyMapping = buildPropertyMapping(field, mapping); + propertyMappingList.add(propertyMapping); + } else if (field.getAnnotation(Mappings.class) != null) { + Mappings mappings = (Mappings)field.getAnnotation(Mappings.class); + Mapping[] var11 = mappings.value(); + int var12 = var11.length; + + for(int var13 = 0; var13 < var12; ++var13) { + Mapping mapping = var11[var13]; + this.validField(sourceClz, mapping.source()); + this.validField(targetClz, mapping.target()); + FieldMapping propertyMapping = buildPropertyMapping(field, mapping); + propertyMappingList.add(propertyMapping); + } + } else { + try { + this.validField(targetClz, field.getName()); + } catch (Exception var16) { + continue; + } + + FieldMapping propertyMapping = new FieldMapping(field.getName(), field.getName()); + propertyMappingList.add(propertyMapping); + } + } + + return propertyMappingList; + } + + void validField(Class clz, String fieldName) { + if (!fieldName.contains(".")) { + try { + clz.getDeclaredField(fieldName); + } catch (NoSuchFieldException var11) { + throw new SystemException(String.format("mapping field not found,clz:%s,field:%s", clz.getName(), fieldName)); + } + } else { + String[] arr = fieldName.split("\\."); + String parentFieldName = arr[0]; + Field parentField = null; + + try { + parentField = clz.getDeclaredField(parentFieldName); + } catch (NoSuchFieldException var10) { + throw new SystemException(String.format("mapping field not found,clz:%s,field:%s", clz.getName(), parentFieldName)); + } + + String childFieldName = arr[1]; + Class parentFieldClz = null; + + try { + parentFieldClz = parentField.getType(); + parentFieldClz.getDeclaredField(childFieldName); + } catch (NoSuchFieldException var9) { + throw new SystemException(String.format("mapping field not found,clz:%s,field:%s", parentFieldClz.getName(), childFieldName)); + } + } + + } + + static FieldMapping buildPropertyMapping(Field field, Mapping mapping) { + FieldMapping propertyMappingMeta = new FieldMapping(); + propertyMappingMeta.setSource(mapping.source()); + propertyMappingMeta.setTarget(mapping.target()); + return propertyMappingMeta; + } + + public static BeanMapping getBeanMapping(Class sourceClass, Class targetClass) { + String mappingKey = getBeanMappingKey(sourceClass, targetClass); + BeanMapping classMapping = (BeanMapping)mappers.get(mappingKey); + return classMapping; + } + + static String getBeanMappingKey(BeanMapping beanMapping) { + String var10000 = beanMapping.getSourceClass().getName(); + return var10000 + "->" + beanMapping.getTargetClass().getName(); + } + + static String getBeanMappingKey(Class sourceClass, Class targetClass) { + String var10000 = sourceClass.getName(); + return var10000 + "->" + targetClass.getName(); + } +} diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/toolkit/beans/model/BeanMapping.java b/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/toolkit/beans/model/BeanMapping.java new file mode 100644 index 0000000..069c831 --- /dev/null +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/toolkit/beans/model/BeanMapping.java @@ -0,0 +1,12 @@ +package cd.casic.module.process.toolkit.beans.model; + +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; +@Data +public class BeanMapping { + private Class sourceClass; + private Class targetClass; + private List propertyMappingList = new ArrayList(); +} diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/toolkit/beans/model/FieldMapping.java b/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/toolkit/beans/model/FieldMapping.java new file mode 100644 index 0000000..61e9f95 --- /dev/null +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/module/process/toolkit/beans/model/FieldMapping.java @@ -0,0 +1,13 @@ +package cd.casic.module.process.toolkit.beans.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class FieldMapping { + private String source; + private String target; +}