流程图工具类ActivitiUtils
package com.mypro.activiti.utils;
import java.util.ArrayList;
import java.util.List;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.FlowNode;
import org.activiti.bpmn.model.SequenceFlow;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
/**
<p>Activiti工作流工具类</p>
@author FRH
@time 2018年12月10日上午11:26:02
@version 1.0
*/
public class ActivitiUtils {
/**
<p>获取流程走过的线</p>
@param bpmnModel 流程对象模型
@param processDefinitionEntity 流程定义对象
@param historicActivityInstances 历史流程已经执行的节点,并已经按执行的先后顺序排序
@return List<String> 流程走过的线
@author FRH
@time 2018年12月10日上午11:26:19
@version 1.0
*/
public static List<String> getHighLightedFlows(BpmnModel bpmnModel, ProcessDefinitionEntity processDefinitionEntity, List<HistoricActivityInstance> historicActivityInstances) {
// 用以保存高亮的线flowId
List<String> highFlows = new ArrayList<String>();
if(historicActivityInstances == null || historicActivityInstances.size() == 0) return highFlows;
// 遍历历史节点
for (int i = 0; i < historicActivityInstances.size() - 1; i++) {
// 取出已执行的节点
HistoricActivityInstance activityImpl_ = historicActivityInstances.get(i);
<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">// 用以保存后续开始时间相同的节点</span></span></span></span>
List<FlowNode> sameStartTimeNodes = <span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">new</span></span></span></span> ArrayList<FlowNode>();
<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">// 获取下一个节点(用于连线)</span></span></span></span>
FlowNode sameActivityImpl = getNextFlowNode(bpmnModel, historicActivityInstances, i, activityImpl_);
// FlowNode sameActivityImpl = (FlowNode) bpmnModel.getMainProcess().getFlowElement(historicActivityInstances.get(i + 1).getActivityId());
<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">// 将后面第一个节点放在时间相同节点的集合里</span></span></span></span>
<span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">if</span></span></span></span>(sameActivityImpl != <span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">null</span></span></span></span>) sameStartTimeNodes.add(sameActivityImpl);
<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">// 循环后面节点,看是否有与此后继节点开始时间相同的节点,有则添加到后继节点集合</span></span></span></span>
<span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">for</span></span></span></span> (<span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">int</span></span></span></span> j = i + <span class="hljs-number"><span class="hljs-number"><span class="hljs-number"><span class="hljs-number">1</span></span></span></span>; j < historicActivityInstances.size() - <span class="hljs-number"><span class="hljs-number"><span class="hljs-number"><span class="hljs-number">1</span></span></span></span>; j++) {
HistoricActivityInstance activityImpl1 = historicActivityInstances.get(j);<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">// 后续第一个节点</span></span></span></span>
HistoricActivityInstance activityImpl2 = historicActivityInstances.get(j + <span class="hljs-number"><span class="hljs-number"><span class="hljs-number"><span class="hljs-number">1</span></span></span></span>);<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">// 后续第二个节点</span></span></span></span>
<span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">if</span></span></span></span> (activityImpl1.getStartTime().getTime() != activityImpl2.getStartTime().getTime()) <span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">break</span></span></span></span>;
<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">// 如果第一个节点和第二个节点开始时间相同保存</span></span></span></span>
FlowNode sameActivityImpl2 = (FlowNode) bpmnModel.getMainProcess().getFlowElement(activityImpl2.getActivityId());
sameStartTimeNodes.add(sameActivityImpl2);
}
<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">// 得到节点定义的详细信息</span></span></span></span>
FlowNode activityImpl = (FlowNode) bpmnModel.getMainProcess().getFlowElement(historicActivityInstances.get(i).getActivityId());
<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">// 取出节点的所有出去的线,对所有的线进行遍历</span></span></span></span>
List<SequenceFlow> pvmTransitions = activityImpl.getOutgoingFlows();
<span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">for</span></span></span></span> (SequenceFlow pvmTransition : pvmTransitions) {
<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">// 获取节点</span></span></span></span>
FlowNode pvmActivityImpl = (FlowNode) bpmnModel.getMainProcess().getFlowElement(pvmTransition.getTargetRef());
<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">// 不是后继节点</span></span></span></span>
<span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">if</span></span></span></span>(!sameStartTimeNodes.contains(pvmActivityImpl)) <span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">continue</span></span></span></span>;
<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">// 如果取出的线的目标节点存在时间相同的节点里,保存该线的id,进行高亮显示</span></span></span></span>
highFlows.add(pvmTransition.getId());
}
}
<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">//返回高亮的线</span></span></span></span>
<span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">return</span></span></span></span> highFlows;
}
<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">/**
* <p>获取下一个节点信息</p>
* </span></span></span><span class="hljs-doctag"><span class="hljs-comment"><span class="hljs-doctag"><span class="hljs-comment"><span class="hljs-doctag"><span class="hljs-comment"><span class="hljs-doctag">@param</span></span></span></span></span></span></span><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"> bpmnModel 流程模型
* </span></span></span><span class="hljs-doctag"><span class="hljs-comment"><span class="hljs-doctag"><span class="hljs-comment"><span class="hljs-doctag"><span class="hljs-comment"><span class="hljs-doctag">@param</span></span></span></span></span></span></span><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"> historicActivityInstances 历史节点
* </span></span></span><span class="hljs-doctag"><span class="hljs-comment"><span class="hljs-doctag"><span class="hljs-comment"><span class="hljs-doctag"><span class="hljs-comment"><span class="hljs-doctag">@param</span></span></span></span></span></span></span><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"> i 当前已经遍历到的历史节点索引(找下一个节点从此节点后)
* </span></span></span><span class="hljs-doctag"><span class="hljs-comment"><span class="hljs-doctag"><span class="hljs-comment"><span class="hljs-doctag"><span class="hljs-comment"><span class="hljs-doctag">@param</span></span></span></span></span></span></span><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"> activityImpl_ 当前遍历到的历史节点实例
* </span></span></span><span class="hljs-doctag"><span class="hljs-comment"><span class="hljs-doctag"><span class="hljs-comment"><span class="hljs-doctag"><span class="hljs-comment"><span class="hljs-doctag">@return</span></span></span></span></span></span></span><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"> FlowNode 下一个节点信息
* </span></span></span><span class="hljs-doctag"><span class="hljs-comment"><span class="hljs-doctag"><span class="hljs-comment"><span class="hljs-doctag"><span class="hljs-comment"><span class="hljs-doctag">@author</span></span></span></span></span></span></span><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"> FRH
* </span></span></span><span class="hljs-doctag"><span class="hljs-comment"><span class="hljs-doctag"><span class="hljs-comment"><span class="hljs-doctag"><span class="hljs-comment"><span class="hljs-doctag">@time</span></span></span></span></span></span></span><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"> 2018年12月10日上午11:26:55
* </span></span></span><span class="hljs-doctag"><span class="hljs-comment"><span class="hljs-doctag"><span class="hljs-comment"><span class="hljs-doctag"><span class="hljs-comment"><span class="hljs-doctag">@version</span></span></span></span></span></span></span><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"> 1.0
*/</span></span></span></span>
<span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">private</span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">static</span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> FlowNode </span></span></span><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">getNextFlowNode</span></span></span></span></span></span></span><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">(BpmnModel bpmnModel, List<HistoricActivityInstance> historicActivityInstances, </span></span></span></span></span></span><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-params"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-params"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-params"><span class="hljs-keyword">int</span></span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"> i, HistoricActivityInstance activityImpl_)</span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span>{
<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">// 保存后一个节点</span></span></span></span>
FlowNode sameActivityImpl = <span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">null</span></span></span></span>;
<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">// 如果当前节点不是用户任务节点,则取排序的下一个节点为后续节点</span></span></span></span>
<span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">if</span></span></span></span>(!<span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"userTask"</span></span></span></span>.equals(activityImpl_.getActivityType())) {
<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">// 是最后一个节点,没有下一个节点</span></span></span></span>
<span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">if</span></span></span></span>(i == historicActivityInstances.size()) <span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">return</span></span></span></span> sameActivityImpl;
<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">// 不是最后一个节点,取下一个节点为后继节点</span></span></span></span>
sameActivityImpl = (FlowNode) bpmnModel.getMainProcess().getFlowElement(historicActivityInstances.get(i + <span class="hljs-number"><span class="hljs-number"><span class="hljs-number"><span class="hljs-number">1</span></span></span></span>).getActivityId());<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">// 找到紧跟在后面的一个节点</span></span></span></span>
<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">// 返回</span></span></span></span>
<span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">return</span></span></span></span> sameActivityImpl;
}
<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">// 遍历后续节点,获取当前节点后续节点</span></span></span></span>
<span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">for</span></span></span></span> (<span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">int</span></span></span></span> k = i + <span class="hljs-number"><span class="hljs-number"><span class="hljs-number"><span class="hljs-number">1</span></span></span></span>; k <= historicActivityInstances.size() - <span class="hljs-number"><span class="hljs-number"><span class="hljs-number"><span class="hljs-number">1</span></span></span></span>; k++) {
<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">// 后续节点</span></span></span></span>
HistoricActivityInstance activityImp2_ = historicActivityInstances.get(k);
<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">// 都是userTask,且主节点与后续节点的开始时间相同,说明不是真实的后继节点</span></span></span></span>
<span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">if</span></span></span></span>(<span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"userTask"</span></span></span></span>.equals(activityImp2_.getActivityType()) && activityImpl_.getStartTime().getTime() == activityImp2_.getStartTime().getTime()) <span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">continue</span></span></span></span>;
<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">// 找到紧跟在后面的一个节点</span></span></span></span>
sameActivityImpl = (FlowNode) bpmnModel.getMainProcess().getFlowElement(historicActivityInstances.get(k).getActivityId());
<span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">break</span></span></span></span>;
}
<span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">return</span></span></span></span> sameActivityImpl;
}
}
<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">// 用以保存后续开始时间相同的节点</span></span></span></span>
List<FlowNode> sameStartTimeNodes = <span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">new</span></span></span></span> ArrayList<FlowNode>();
<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">// 获取下一个节点(用于连线)</span></span></span></span>
FlowNode sameActivityImpl = getNextFlowNode(bpmnModel, historicActivityInstances, i, activityImpl_);
<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">// 将后面第一个节点放在时间相同节点的集合里</span></span></span></span>
<span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">if</span></span></span></span>(sameActivityImpl != <span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">null</span></span></span></span>) sameStartTimeNodes.add(sameActivityImpl);
<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">// 循环后面节点,看是否有与此后继节点开始时间相同的节点,有则添加到后继节点集合</span></span></span></span>
<span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">for</span></span></span></span> (<span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">int</span></span></span></span> j = i + <span class="hljs-number"><span class="hljs-number"><span class="hljs-number"><span class="hljs-number">1</span></span></span></span>; j < historicActivityInstances.size() - <span class="hljs-number"><span class="hljs-number"><span class="hljs-number"><span class="hljs-number">1</span></span></span></span>; j++) {
HistoricActivityInstance activityImpl1 = historicActivityInstances.get(j);<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">// 后续第一个节点</span></span></span></span>
HistoricActivityInstance activityImpl2 = historicActivityInstances.get(j + <span class="hljs-number"><span class="hljs-number"><span class="hljs-number"><span class="hljs-number">1</span></span></span></span>);<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">// 后续第二个节点</span></span></span></span>
<span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">if</span></span></span></span> (activityImpl1.getStartTime().getTime() != activityImpl2.getStartTime().getTime()) <span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">break</span></span></span></span>;
<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">// 如果第一个节点和第二个节点开始时间相同保存</span></span></span></span>
FlowNode sameActivityImpl2 = (FlowNode) bpmnModel.getMainProcess().getFlowElement(activityImpl2.getActivityId());
sameStartTimeNodes.add(sameActivityImpl2);
}
<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">// 得到节点定义的详细信息</span></span></span></span>
FlowNode activityImpl = (FlowNode) bpmnModel.getMainProcess().getFlowElement(historicActivityInstances.get(i).getActivityId());
<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">// 取出节点的所有出去的线,对所有的线进行遍历</span></span></span></span>
List<SequenceFlow> pvmTransitions = activityImpl.getOutgoingFlows();
<span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">for</span></span></span></span> (SequenceFlow pvmTransition : pvmTransitions) {
<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">// 获取节点</span></span></span></span>
FlowNode pvmActivityImpl = (FlowNode) bpmnModel.getMainProcess().getFlowElement(pvmTransition.getTargetRef());
<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">// 不是后继节点</span></span></span></span>
<span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">if</span></span></span></span>(!sameStartTimeNodes.contains(pvmActivityImpl)) <span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">continue</span></span></span></span>;
<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">// 如果取出的线的目标节点存在时间相同的节点里,保存该线的id,进行高亮显示</span></span></span></span>
highFlows.add(pvmTransition.getId());
}
}
<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">//返回高亮的线</span></span></span></span>
<span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">return</span></span></span></span> highFlows;
}
<span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">/**
* <p>获取下一个节点信息</p>
* </span></span></span><span class="hljs-doctag"><span class="hljs-comment"><span class="hljs-doctag"><span class="hljs-comment"><span class="hljs-doctag"><span class="hljs-comment"><span class="hljs-doctag">@param</span></span></span></span></span></span></span><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"> bpmnModel 流程模型
* </span></span></span><span class="hljs-doctag"><span class="hljs-comment"><span class=