001/* 002 * Copyright 2024-2025, Warm-Flow (290631660@qq.com). 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.dromara.warm.flow.core.service.impl; 017 018import org.dromara.warm.flow.core.FlowFactory; 019import org.dromara.warm.flow.core.constant.ExceptionCons; 020import org.dromara.warm.flow.core.dao.FlowNodeDao; 021import org.dromara.warm.flow.core.entity.Definition; 022import org.dromara.warm.flow.core.entity.Node; 023import org.dromara.warm.flow.core.entity.Skip; 024import org.dromara.warm.flow.core.enums.NodeType; 025import org.dromara.warm.flow.core.enums.PublishStatus; 026import org.dromara.warm.flow.core.orm.service.impl.WarmServiceImpl; 027import org.dromara.warm.flow.core.service.NodeService; 028import org.dromara.warm.flow.core.utils.*; 029 030import java.io.Serializable; 031import java.util.Collection; 032import java.util.Collections; 033import java.util.List; 034import java.util.Map; 035import java.util.stream.Collectors; 036 037/** 038 * 流程节点Service业务层处理 039 * 040 * @author warm 041 * @since 2023-03-29 042 */ 043public class NodeServiceImpl extends WarmServiceImpl<FlowNodeDao<Node>, Node> implements NodeService { 044 045 @Override 046 public NodeService setDao(FlowNodeDao<Node> warmDao) { 047 this.warmDao = warmDao; 048 return this; 049 } 050 051 @Override 052 public List<Node> getByFlowCode(String flowCode) { 053 Definition definition = FlowFactory.defService().getOne(FlowFactory.newDef() 054 .setFlowCode(flowCode).setIsPublish(PublishStatus.PUBLISHED.getKey())); 055 if (ObjectUtil.isNotNull(definition)) { 056 return list(FlowFactory.newNode().setDefinitionId(definition.getId())); 057 } 058 return Collections.emptyList(); 059 } 060 061 @Override 062 public List<Node> getByNodeCodes(List<String> nodeCodes, Long definitionId) { 063 return getDao().getByNodeCodes(nodeCodes, definitionId); 064 } 065 066 @Override 067 public List<Node> getNextNodeList(Long definitionId, String nowNodeCode, String anyNodeCode, String skipType, 068 Map<String, Object> variable) { 069 // 如果是网关节点,则根据条件判断 070 return getNextByCheckGateway(variable, getNextNode(definitionId, nowNodeCode, anyNodeCode, skipType)); 071 } 072 073 @Override 074 public Node getNextNode(Long definitionId, String nowNodeCode, String anyNodeCode, String skipType) { 075 AssertUtil.isNull(definitionId, ExceptionCons.NOT_DEFINITION_ID); 076 AssertUtil.isEmpty(nowNodeCode, ExceptionCons.LOST_NODE_CODE); 077 AssertUtil.isEmpty(skipType, ExceptionCons.NULL_CONDITIONVALUE); 078 079 // 如果指定了跳转节点,直接获取节点 080 if (StringUtils.isNotEmpty(anyNodeCode)) { 081 return getOne(FlowFactory.newNode().setNodeCode(anyNodeCode).setDefinitionId(definitionId)); 082 } 083 // 查询当前节点 084 Node nowNode = getOne(FlowFactory.newNode().setNodeCode(nowNodeCode).setDefinitionId(definitionId)); 085 AssertUtil.isNull(nowNode, ExceptionCons.LOST_CUR_NODE); 086 // 获取跳转关系 087 List<Skip> skips = FlowFactory.skipService().list(FlowFactory.newSkip().setDefinitionId(definitionId) 088 .setNowNodeCode(nowNodeCode)); 089 AssertUtil.isNull(skips, ExceptionCons.NULL_SKIP_TYPE); 090 091 Skip nextSkip = getSkipByCheck(nowNode, skips, skipType); 092 AssertUtil.isNull(nextSkip, ExceptionCons.NULL_SKIP_TYPE); 093 094 // 根据跳转查询出跳转到的那个节点 095 Node nextNode = getOne(FlowFactory.newNode().setNodeCode(nextSkip.getNextNodeCode()).setDefinitionId(definitionId)); 096 AssertUtil.isNull(nextNode, ExceptionCons.NULL_NODE_CODE); 097 AssertUtil.isTrue(NodeType.isStart(nextNode.getNodeType()), ExceptionCons.FRIST_FORBID_BACK); 098 return nextNode; 099 } 100 101 /** 102 * 通过校验跳转类型获取跳转集合 103 * 104 * @param nowNode 当前节点信息 105 * @param skips 跳转集合 106 * @param skipType 跳转类型 107 * @return List<Skip> 108 * @author xiarg 109 * @since 2024/8/21 11:32 110 */ 111 private Skip getSkipByCheck(Node nowNode, List<Skip> skips, String skipType) { 112 if (CollUtil.isEmpty(skips)) { 113 return null; 114 } 115 if (!NodeType.isStart(nowNode.getNodeType())) { 116 skips = skips.stream().filter(t -> { 117 if (StringUtils.isNotEmpty(t.getSkipType())) { 118 return skipType.equals(t.getSkipType()); 119 } 120 return true; 121 }).collect(Collectors.toList()); 122 } 123 AssertUtil.isEmpty(skips, ExceptionCons.NULL_SKIP_TYPE); 124 return skips.get(0); 125 } 126 127 @Override 128 public List<Node> getNextByCheckGateway(Map<String, Object> variable, Node nextNode) { 129 // 网关节点处理 130 if (NodeType.isGateWay(nextNode.getNodeType())) { 131 List<Skip> skipsGateway = FlowFactory.skipService().list(FlowFactory.newSkip() 132 .setDefinitionId(nextNode.getDefinitionId()).setNowNodeCode(nextNode.getNodeCode())); 133 if (CollUtil.isEmpty(skipsGateway)) { 134 return null; 135 } 136 // 过滤跳转 137 if (!NodeType.isStart(nextNode.getNodeType())) { 138 skipsGateway = skipsGateway.stream().filter(t -> { 139 if (NodeType.isGateWaySerial(nextNode.getNodeType())) { 140 AssertUtil.isEmpty(variable, ExceptionCons.MUST_CONDITIONVALUE_NODE); 141 if (ObjectUtil.isNotNull(t.getSkipCondition())) { 142 return ExpressionUtil.eval(t.getSkipCondition(), variable); 143 } 144 } 145 // 并行网关返回多个跳转 146 return true; 147 }).collect(Collectors.toList()); 148 } 149 AssertUtil.isEmpty(skipsGateway, ExceptionCons.NULL_CONDITIONVALUE_NODE); 150 List<String> nextNodeCodes = StreamUtils.toList(skipsGateway, Skip::getNextNodeCode); 151 List<Node> nextNodes = FlowFactory.nodeService() 152 .getByNodeCodes(nextNodeCodes, nextNode.getDefinitionId()); 153 AssertUtil.isEmpty(nextNodes, ExceptionCons.NOT_NODE_DATA); 154 return nextNodes; 155 } 156 // 非网关节点直接返回 157 return CollUtil.toList(nextNode); 158 } 159 160 @Override 161 public int deleteNodeByDefIds(Collection<? extends Serializable> defIds) { 162 return getDao().deleteNodeByDefIds(defIds); 163 } 164 165}