mirror of
				https://github.com/YunaiV/ruoyi-vue-pro.git
				synced 2025-10-31 18:49:06 +08:00 
			
		
		
		
	BPM 模型重构 7:任务分配规则的后端,全部实现完成
This commit is contained in:
		| @ -45,8 +45,10 @@ public interface BpmErrorCodeConstants { | |||||||
|  |  | ||||||
|     // ========== 流程任务分配规则 1-009-006-000 ========== |     // ========== 流程任务分配规则 1-009-006-000 ========== | ||||||
|     ErrorCode TASK_ASSIGN_RULE_EXISTS = new ErrorCode(1009006000, "流程({}) 的任务({}) 已经存在分配规则"); |     ErrorCode TASK_ASSIGN_RULE_EXISTS = new ErrorCode(1009006000, "流程({}) 的任务({}) 已经存在分配规则"); | ||||||
|     ErrorCode TASK_ASSIGN_RULE_NOT_EXISTS = new ErrorCode(1009006000, "流程任务分配规则不存在"); |     ErrorCode TASK_ASSIGN_RULE_NOT_EXISTS = new ErrorCode(1009006001, "流程任务分配规则不存在"); | ||||||
|     ErrorCode TASK_UPDATE_FAIL_NOT_MODEL = new ErrorCode(1009006000, "只有流程模型的任务分配规则,才允许被修改"); |     ErrorCode TASK_UPDATE_FAIL_NOT_MODEL = new ErrorCode(1009006002, "只有流程模型的任务分配规则,才允许被修改"); | ||||||
|  |     ErrorCode TASK_CREATE_FAIL_NO_CANDIDATE_USER = new ErrorCode(1009006003, "操作失败,原因:找不到任务的审批人!"); | ||||||
|  |     ErrorCode TASK_ASSIGN_SCRIPT_NOT_EXISTS = new ErrorCode(1009006004, "操作失败,原因:任务分配脚本({}) 不存在"); | ||||||
|  |  | ||||||
|     // ========== 动态表单模块 1-009-010-000 ========== |     // ========== 动态表单模块 1-009-010-000 ========== | ||||||
|     ErrorCode FORM_NOT_EXISTS = new ErrorCode(1009010000, "动态表单不存在"); |     ErrorCode FORM_NOT_EXISTS = new ErrorCode(1009010000, "动态表单不存在"); | ||||||
|  | |||||||
| @ -4,11 +4,18 @@ import cn.hutool.core.collection.CollUtil; | |||||||
| import cn.hutool.core.util.RandomUtil; | import cn.hutool.core.util.RandomUtil; | ||||||
| import cn.hutool.core.util.StrUtil; | import cn.hutool.core.util.StrUtil; | ||||||
| import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO; | import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO; | ||||||
|  | import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmUserGroupDO; | ||||||
| import cn.iocoder.yudao.adminserver.modules.bpm.enums.definition.BpmTaskAssignRuleTypeEnum; | import cn.iocoder.yudao.adminserver.modules.bpm.enums.definition.BpmTaskAssignRuleTypeEnum; | ||||||
|  | import cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.behavior.script.BpmTaskAssignScript; | ||||||
| import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmTaskAssignRuleService; | import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmTaskAssignRuleService; | ||||||
|  | import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmUserGroupService; | ||||||
|  | import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO; | ||||||
|  | import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysDeptService; | ||||||
| import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService; | import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService; | ||||||
| import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; | ||||||
|  | import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; | ||||||
| import lombok.Setter; | import lombok.Setter; | ||||||
|  | import lombok.extern.slf4j.Slf4j; | ||||||
| import org.activiti.bpmn.model.UserTask; | import org.activiti.bpmn.model.UserTask; | ||||||
| import org.activiti.engine.ActivitiException; | import org.activiti.engine.ActivitiException; | ||||||
| import org.activiti.engine.delegate.DelegateExecution; | import org.activiti.engine.delegate.DelegateExecution; | ||||||
| @ -17,26 +24,49 @@ import org.activiti.engine.impl.el.ExpressionManager; | |||||||
| import org.activiti.engine.impl.persistence.entity.TaskEntity; | import org.activiti.engine.impl.persistence.entity.TaskEntity; | ||||||
| import org.activiti.engine.impl.persistence.entity.TaskEntityManager; | import org.activiti.engine.impl.persistence.entity.TaskEntityManager; | ||||||
|  |  | ||||||
| import java.util.List; | import javax.annotation.Resource; | ||||||
| import java.util.Objects; | import java.util.*; | ||||||
| import java.util.Set; | import java.util.function.Consumer; | ||||||
|  | import java.util.function.Function; | ||||||
|  |  | ||||||
|  | import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.TASK_ASSIGN_SCRIPT_NOT_EXISTS; | ||||||
|  | import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.TASK_CREATE_FAIL_NO_CANDIDATE_USER; | ||||||
|  | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.*; | ||||||
|  | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | ||||||
|  | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | ||||||
|  | import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 自定义的流程任务的 assignee 负责人的分配 |  * 自定义的流程任务的 assignee 负责人的分配 | ||||||
|  * |  * | ||||||
|  * @author 芋道源码 |  * @author 芋道源码 | ||||||
|  */ |  */ | ||||||
|  | @Slf4j | ||||||
| public class BpmUserTaskActivitiBehavior extends UserTaskActivityBehavior { | public class BpmUserTaskActivitiBehavior extends UserTaskActivityBehavior { | ||||||
|  |  | ||||||
|     @Setter |     @Setter | ||||||
|     private BpmTaskAssignRuleService bpmTaskRuleService; |     private BpmTaskAssignRuleService bpmTaskRuleService; | ||||||
|     @Setter |     @Setter | ||||||
|     private SysPermissionService permissionService; |     private SysPermissionService permissionService; | ||||||
|  |     @Setter | ||||||
|  |     private SysDeptService deptService; | ||||||
|  |     @Setter | ||||||
|  |     private BpmUserGroupService userGroupService; | ||||||
|  |     @Resource | ||||||
|  |     private SysUserService userService; | ||||||
|  |     /** | ||||||
|  |      * 任务分配脚本 | ||||||
|  |      */ | ||||||
|  |     private Map<Long, BpmTaskAssignScript> scriptMap = Collections.emptyMap(); | ||||||
|  |  | ||||||
|     public BpmUserTaskActivitiBehavior(UserTask userTask) { |     public BpmUserTaskActivitiBehavior(UserTask userTask) { | ||||||
|         super(userTask); |         super(userTask); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     public void setScripts(List<BpmTaskAssignScript> scripts) { | ||||||
|  |         this.scriptMap = convertMap(scripts, script -> script.getEnum().getId()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     protected void handleAssignments(TaskEntityManager taskEntityManager, |     protected void handleAssignments(TaskEntityManager taskEntityManager, | ||||||
|                                      String assignee, String owner, List<String> candidateUsers, List<String> candidateGroups, |                                      String assignee, String owner, List<String> candidateUsers, List<String> candidateGroups, | ||||||
| @ -51,7 +81,7 @@ public class BpmUserTaskActivitiBehavior extends UserTaskActivityBehavior { | |||||||
|         // 设置候选人们 |         // 设置候选人们 | ||||||
|         candidateUserIds.remove(assigneeUserId); // 已经成为负责人了,就不要在扮演候选人了 |         candidateUserIds.remove(assigneeUserId); // 已经成为负责人了,就不要在扮演候选人了 | ||||||
|         if (CollUtil.isNotEmpty(candidateUserIds)) { |         if (CollUtil.isNotEmpty(candidateUserIds)) { | ||||||
|             task.addCandidateUsers(CollectionUtils.convertSet(candidateUserIds, String::valueOf)); |             task.addCandidateUsers(convertSet(candidateUserIds, String::valueOf)); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @ -80,20 +110,23 @@ public class BpmUserTaskActivitiBehavior extends UserTaskActivityBehavior { | |||||||
|         if (Objects.equals(BpmTaskAssignRuleTypeEnum.ROLE.getType(), rule.getType())) { |         if (Objects.equals(BpmTaskAssignRuleTypeEnum.ROLE.getType(), rule.getType())) { | ||||||
|             assigneeUserIds = calculateTaskCandidateUsersByRole(task, rule); |             assigneeUserIds = calculateTaskCandidateUsersByRole(task, rule); | ||||||
|         } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.DEPT_MEMBER.getType(), rule.getType())) { |         } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.DEPT_MEMBER.getType(), rule.getType())) { | ||||||
|             assigneeUserIds = calculateTaskCandidateUsersByDept(task, rule); |             assigneeUserIds = calculateTaskCandidateUsersByMember(task, rule); | ||||||
|         } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.DEPT_LEADER.getType(), rule.getType())) { |         } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.DEPT_LEADER.getType(), rule.getType())) { | ||||||
|             assigneeUserIds = calculateTaskCandidateUsersByDept(task, rule); |             assigneeUserIds = calculateTaskCandidateUsersByDeptLeader(task, rule); | ||||||
|         } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.USER.getType(), rule.getType())) { |         }  else if (Objects.equals(BpmTaskAssignRuleTypeEnum.USER.getType(), rule.getType())) { | ||||||
|             assigneeUserIds = calculateTaskCandidateUsersByUser(task, rule); |             assigneeUserIds = calculateTaskCandidateUsersByUser(task, rule); | ||||||
|         } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.USER_GROUP.getType(), rule.getType())) { |         } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.USER_GROUP.getType(), rule.getType())) { | ||||||
|             assigneeUserIds = calculateTaskCandidateUsersByUser(task, rule); |             assigneeUserIds = calculateTaskCandidateUsersByUserGroup(task, rule); | ||||||
|  |         } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.SCRIPT.getType(), rule.getType())) { | ||||||
|  |             assigneeUserIds = calculateTaskCandidateUsersByScript(task, rule); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // TODO 芋艿:统一过滤掉被禁用的用户 |         // TODO 芋艿:统一过滤掉被禁用的用户 | ||||||
|         // 如果候选人为空,抛出异常 TODO 芋艿:没候选人的策略选择。1 - 挂起;2 - 直接结束;3 - 强制一个兜底人 |         // 如果候选人为空,抛出异常 TODO 芋艿:没候选人的策略选择。1 - 挂起;2 - 直接结束;3 - 强制一个兜底人 | ||||||
|         if (CollUtil.isEmpty(assigneeUserIds)) { |         if (CollUtil.isEmpty(assigneeUserIds)) { | ||||||
|             throw new ActivitiException(StrUtil.format("流程任务({}/{}/{}) 任务规则({}) 找不到候选人", |             log.error("[calculateTaskCandidateUsers][流程任务({}/{}/{}) 任务规则({}) 找不到候选人]", | ||||||
|                     task.getId(), task.getProcessDefinitionId(), task.getTaskDefinitionKey())); |                     task.getId(), task.getProcessDefinitionId(), task.getTaskDefinitionKey(), toJsonString(rule)); | ||||||
|  |             throw exception(TASK_CREATE_FAIL_NO_CANDIDATE_USER); | ||||||
|         } |         } | ||||||
|         return assigneeUserIds; |         return assigneeUserIds; | ||||||
|     } |     } | ||||||
| @ -102,12 +135,14 @@ public class BpmUserTaskActivitiBehavior extends UserTaskActivityBehavior { | |||||||
|         return permissionService.getUserRoleIdListByRoleIds(rule.getOptions()); |         return permissionService.getUserRoleIdListByRoleIds(rule.getOptions()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private Set<Long> calculateTaskCandidateUsersByDept(TaskEntity task, BpmTaskAssignRuleDO rule) { |     private Set<Long> calculateTaskCandidateUsersByMember(TaskEntity task, BpmTaskAssignRuleDO rule) { | ||||||
|         throw new UnsupportedOperationException("暂不支持该任务规则"); |         List<SysUserDO> users = userService.getUsersByPostIds(rule.getOptions()); | ||||||
|  |         return convertSet(users, SysUserDO::getId); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private Set<Long> calculateTaskCandidateUsersByDeptLeader(TaskEntity task, BpmTaskAssignRuleDO rule) { |     private Set<Long> calculateTaskCandidateUsersByDeptLeader(TaskEntity task, BpmTaskAssignRuleDO rule) { | ||||||
|         throw new UnsupportedOperationException("暂不支持该任务规则"); |         List<SysDeptDO> depts = deptService.getDepts(rule.getOptions()); | ||||||
|  |         return convertSet(depts, SysDeptDO::getLeaderUserId); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private Set<Long> calculateTaskCandidateUsersByUser(TaskEntity task, BpmTaskAssignRuleDO rule) { |     private Set<Long> calculateTaskCandidateUsersByUser(TaskEntity task, BpmTaskAssignRuleDO rule) { | ||||||
| @ -115,11 +150,26 @@ public class BpmUserTaskActivitiBehavior extends UserTaskActivityBehavior { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     private Set<Long> calculateTaskCandidateUsersByUserGroup(TaskEntity task, BpmTaskAssignRuleDO rule) { |     private Set<Long> calculateTaskCandidateUsersByUserGroup(TaskEntity task, BpmTaskAssignRuleDO rule) { | ||||||
|         throw new UnsupportedOperationException("暂不支持该任务规则"); |         List<BpmUserGroupDO> userGroups = userGroupService.getUserGroupList(rule.getOptions()); | ||||||
|  |         Set<Long> userIds = new HashSet<>(); | ||||||
|  |         userGroups.forEach(bpmUserGroupDO -> userIds.addAll(bpmUserGroupDO.getMemberUserIds())); | ||||||
|  |         return userIds; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private Set<Long> calculateTaskCandidateUsersByScript(TaskEntity task, BpmTaskAssignRuleDO rule) { |     private Set<Long> calculateTaskCandidateUsersByScript(TaskEntity task, BpmTaskAssignRuleDO rule) { | ||||||
|         throw new UnsupportedOperationException("暂不支持该任务规则"); |         // 获得对应的脚本 | ||||||
|  |         List<BpmTaskAssignScript> scripts = new ArrayList<>(rule.getOptions().size()); | ||||||
|  |         rule.getOptions().forEach(id -> { | ||||||
|  |             BpmTaskAssignScript script = scriptMap.get(id); | ||||||
|  |             if (script == null) { | ||||||
|  |                 throw exception(TASK_ASSIGN_SCRIPT_NOT_EXISTS, id); | ||||||
|  |             } | ||||||
|  |             scripts.add(script); | ||||||
|  |         }); | ||||||
|  |         // 逐个计算任务 | ||||||
|  |         Set<Long> userIds = new HashSet<>(); | ||||||
|  |         scripts.forEach(script -> CollUtil.addAll(userIds, script.calculateTaskCandidateUsers(task))); | ||||||
|  |         return userIds; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,5 +1,6 @@ | |||||||
| package cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.behavior.script; | package cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.behavior.script; | ||||||
|  |  | ||||||
|  | import cn.iocoder.yudao.adminserver.modules.bpm.enums.definition.BpmTaskRuleScriptEnum; | ||||||
| import org.activiti.engine.impl.persistence.entity.TaskEntity; | import org.activiti.engine.impl.persistence.entity.TaskEntity; | ||||||
|  |  | ||||||
| import java.util.List; | import java.util.List; | ||||||
| @ -23,4 +24,11 @@ public interface BpmTaskAssignScript { | |||||||
|      */ |      */ | ||||||
|     List<Long> calculateTaskCandidateUsers(TaskEntity task); |     List<Long> calculateTaskCandidateUsers(TaskEntity task); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获得枚举值 | ||||||
|  |      * | ||||||
|  |      * @return 枚举值 | ||||||
|  |      */ | ||||||
|  |     BpmTaskRuleScriptEnum getEnum(); | ||||||
|  |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -68,5 +68,9 @@ public interface SysUserMapper extends BaseMapperX<SysUserDO> { | |||||||
|         return selectList("status", status); |         return selectList("status", status); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     default List<SysUserDO> selectListByDeptIds(Collection<Integer> deptIds) { | ||||||
|  |         return selectList("dept_id", deptIds); | ||||||
|  |     } | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | |||||||
| @ -84,6 +84,14 @@ public interface SysDeptService { | |||||||
|      */ |      */ | ||||||
|     SysDeptDO getDept(Long id); |     SysDeptDO getDept(Long id); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获得部门信息数组 | ||||||
|  |      * | ||||||
|  |      * @param ids 部门编号数组 | ||||||
|  |      * @return 部门信息数组 | ||||||
|  |      */ | ||||||
|  |     List<SysDeptDO> getDepts(Collection<Long> ids); | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 获得所有子部门,从缓存中 |      * 获得所有子部门,从缓存中 | ||||||
|      * |      * | ||||||
|  | |||||||
| @ -1,7 +1,6 @@ | |||||||
| package cn.iocoder.yudao.adminserver.modules.system.service.dept.impl; | package cn.iocoder.yudao.adminserver.modules.system.service.dept.impl; | ||||||
|  |  | ||||||
| import cn.hutool.core.collection.CollUtil; | import cn.hutool.core.collection.CollUtil; | ||||||
| import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleDO; |  | ||||||
| import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||||||
| import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; | import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; | ||||||
| import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | ||||||
| @ -233,6 +232,11 @@ public class SysDeptServiceImpl implements SysDeptService { | |||||||
|         return deptMapper.selectById(id); |         return deptMapper.selectById(id); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public List<SysDeptDO> getDepts(Collection<Long> ids) { | ||||||
|  |         return deptMapper.selectBatchIds(ids); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     private void checkCreateOrUpdate(Long id, Long parentId, String name) { |     private void checkCreateOrUpdate(Long id, Long parentId, String name) { | ||||||
|         // 校验自己存在 |         // 校验自己存在 | ||||||
|         checkDeptExists(id); |         checkDeptExists(id); | ||||||
|  | |||||||
| @ -174,6 +174,22 @@ public interface SysUserService { | |||||||
|      */ |      */ | ||||||
|     List<SysUserDO> getUsersByStatus(Integer status); |     List<SysUserDO> getUsersByStatus(Integer status); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获得指定岗位的用户数组 | ||||||
|  |      * | ||||||
|  |      * @param postIds 岗位数组 | ||||||
|  |      * @return 用户数组 | ||||||
|  |      */ | ||||||
|  |     List<SysUserDO> getUsersByPostIds(Collection<Long> postIds); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获得指定部门的用户数组 | ||||||
|  |      * | ||||||
|  |      * @param deptIds 部门数组 | ||||||
|  |      * @return 用户数组 | ||||||
|  |      */ | ||||||
|  |     List<SysUserDO> getUsersByDeptIds(Collection<Integer> deptIds); | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 校验用户们是否有效。如下情况,视为无效: |      * 校验用户们是否有效。如下情况,视为无效: | ||||||
|      * 1. 用户编号不存在 |      * 1. 用户编号不存在 | ||||||
|  | |||||||
| @ -389,6 +389,26 @@ public class SysUserServiceImpl implements SysUserService { | |||||||
|         return userMapper.selectListByStatus(status); |         return userMapper.selectListByStatus(status); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public List<SysUserDO> getUsersByPostIds(Collection<Long> postIds) { | ||||||
|  |         if (CollUtil.isEmpty(postIds)) { | ||||||
|  |             return Collections.emptyList(); | ||||||
|  |         } | ||||||
|  |         // 过滤不符合条件的 | ||||||
|  |         // TODO 芋艿:暂时只能内存过滤。解决方案:1、新建一个关联表;2、基于 where + 函数;3、json 字段,适合 mysql 8+ 版本 | ||||||
|  |         List<SysUserDO> users = userMapper.selectList(); | ||||||
|  |         users.removeIf(user -> !CollUtil.containsAny(user.getPostIds(), postIds)); | ||||||
|  |         return users; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public List<SysUserDO> getUsersByDeptIds(Collection<Integer> deptIds) { | ||||||
|  |         if (CollUtil.isEmpty(deptIds)) { | ||||||
|  |             return Collections.emptyList(); | ||||||
|  |         } | ||||||
|  |         return userMapper.selectListByDeptIds(deptIds); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void validUsers(Set<Long> ids) { |     public void validUsers(Set<Long> ids) { | ||||||
|         if (CollUtil.isEmpty(ids)) { |         if (CollUtil.isEmpty(ids)) { | ||||||
|  | |||||||
| @ -50,14 +50,14 @@ public class CollectionUtils { | |||||||
|         if (CollUtil.isEmpty(from)) { |         if (CollUtil.isEmpty(from)) { | ||||||
|             return new ArrayList<>(); |             return new ArrayList<>(); | ||||||
|         } |         } | ||||||
|         return from.stream().map(func).collect(Collectors.toList()); |         return from.stream().map(func).filter(Objects::nonNull).collect(Collectors.toList()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public static <T, U> Set<U> convertSet(Collection<T> from, Function<T, U> func) { |     public static <T, U> Set<U> convertSet(Collection<T> from, Function<T, U> func) { | ||||||
|         if (CollUtil.isEmpty(from)) { |         if (CollUtil.isEmpty(from)) { | ||||||
|             return new HashSet<>(); |             return new HashSet<>(); | ||||||
|         } |         } | ||||||
|         return from.stream().map(func).collect(Collectors.toSet()); |         return from.stream().map(func).filter(Objects::nonNull).collect(Collectors.toSet()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public static <T, K> Map<K, T> convertMap(Collection<T> from, Function<T, K> keyFunc) { |     public static <T, K> Map<K, T> convertMap(Collection<T> from, Function<T, K> keyFunc) { | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 YunaiV
					YunaiV