天天看點

Activiti6.0.0 跟蹤流程執行情況用紅色框在流程圖上辨別路線跟節點

更新到Activiti6.0.0  之後,發現pvm 包整個被删掉了。。。。這樣一來就導緻之前的跟蹤流失效了。代碼連編譯都通過不了。

因為pvm包沒了,是以就不能再使用ActivityImpl 等相關類了。隻能改成用org.activiti.bpmn.model包下的FlowNode類來替代。好在他們差不多,是以代碼改動也不大。下面是完整代碼:
    /**
 * @Author 葛明
 * @Note 讀取流程資源
 * @Date 2017-1-3 15:11
 * @param processDefinitionId 流程定義ID
 * @param resourceName        資源名稱
 */
@RequestMapping(value = "/read-resource")
public void readResource(String processDefinitionId, String resourceName,String pProcessInstanceId, HttpServletResponse response)
        throws Exception {
    // 設定頁面不緩存
    response.setHeader("Pragma", "No-cache");
    response.setHeader("Cache-Control", "no-cache");
    response.setDateHeader("Expires", 0);

    ProcessDefinitionQuery pdq = repositoryService.createProcessDefinitionQuery();
    ProcessDefinition pd = pdq.processDefinitionId(processDefinitionId).singleResult();

    if(resourceName.endsWith(".png") && StringUtils.isEmpty(pProcessInstanceId) == false)
    {
        getActivitiProccessImage(pProcessInstanceId,response);
        //ProcessDiagramGenerator.generateDiagram(pde, "png", getRuntimeService().getActiveActivityIds(processInstanceId));
    }
    else
    {
        // 通過接口讀取
        InputStream resourceAsStream = repositoryService.getResourceAsStream(pd.getDeploymentId(), resourceName);

        // 輸出資源内容到相應對象
        byte[] b = new byte[1024];
        int len = -1;
        while ((len = resourceAsStream.read(b, 0, 1024)) != -1) {
            response.getOutputStream().write(b, 0, len);
        }
    }
}


/**
 * 擷取流程圖像,已執行節點和流程線高亮顯示
 */
public void getActivitiProccessImage(String pProcessInstanceId, HttpServletResponse response)
{
    //logger.info("[開始]-擷取流程圖圖像");
    try {
        //  擷取曆史流程執行個體
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                .processInstanceId(pProcessInstanceId).singleResult();

        if (historicProcessInstance == null) {
            //throw new BusinessException("擷取流程執行個體ID[" + pProcessInstanceId + "]對應的曆史流程執行個體失敗!");
        }
        else
        {
            // 擷取流程定義
            ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
                    .getDeployedProcessDefinition(historicProcessInstance.getProcessDefinitionId());

            // 擷取流程曆史中已執行節點,并按照節點在流程中執行先後順序排序
            List<HistoricActivityInstance> historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery()
                    .processInstanceId(pProcessInstanceId).orderByHistoricActivityInstanceId().asc().list();

            // 已執行的節點ID集合
            List<String> executedActivityIdList = new ArrayList<String>();
            int index = 1;
            //logger.info("擷取已經執行的節點ID");
            for (HistoricActivityInstance activityInstance : historicActivityInstanceList) {
                executedActivityIdList.add(activityInstance.getActivityId());

                //logger.info("第[" + index + "]個已執行節點=" + activityInstance.getActivityId() + " : " +activityInstance.getActivityName());
                index++;
            }

            BpmnModel bpmnModel = repositoryService.getBpmnModel(historicProcessInstance.getProcessDefinitionId());

            // 已執行的線集合
            List<String> flowIds = new ArrayList<String>();
            // 擷取流程走過的線 (getHighLightedFlows是下面的方法)
            flowIds = getHighLightedFlows(bpmnModel,processDefinition, historicActivityInstanceList);



            // 擷取流程圖圖像字元流
            ProcessDiagramGenerator pec = processEngine.getProcessEngineConfiguration().getProcessDiagramGenerator();
            //配置字型
            InputStream imageStream = pec.generateDiagram(bpmnModel, "png", executedActivityIdList, flowIds,"宋體","微軟雅黑","黑體",null,2.0);

            response.setContentType("image/png");
            OutputStream os = response.getOutputStream();
            int bytesRead = 0;
            byte[] buffer = new byte[8192];
            while ((bytesRead = imageStream.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            imageStream.close();
        }
        //logger.info("[完成]-擷取流程圖圖像");
    } catch (Exception e) {
        System.out.println(e.getMessage());
        //logger.error("【異常】-擷取流程圖失敗!" + e.getMessage());
        //throw new BusinessException("擷取流程圖失敗!" + e.getMessage());
    }
}

public List<String> getHighLightedFlows(BpmnModel bpmnModel,ProcessDefinitionEntity processDefinitionEntity,List<HistoricActivityInstance> historicActivityInstances)
{
    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //24小時制
    List<String> highFlows = new ArrayList<String>();// 用以儲存高亮的線flowId

    for (int i = 0; i < historicActivityInstances.size() - 1; i++)
    {
        // 對曆史流程節點進行周遊
        // 得到節點定義的詳細資訊
        FlowNode activityImpl = (FlowNode)bpmnModel.getMainProcess().getFlowElement(historicActivityInstances.get(i).getActivityId());


        List<FlowNode> sameStartTimeNodes = new ArrayList<FlowNode>();// 用以儲存後續開始時間相同的節點
        FlowNode sameActivityImpl1 = null;

        HistoricActivityInstance activityImpl_ = historicActivityInstances.get(i);// 第一個節點
        HistoricActivityInstance activityImp2_ ;

        for(int k = i + 1 ; k <= historicActivityInstances.size() - 1; k++)
        {
            activityImp2_ = historicActivityInstances.get(k);// 後續第1個節點

            if ( activityImpl_.getActivityType().equals("userTask") && activityImp2_.getActivityType().equals("userTask") &&
                    df.format(activityImpl_.getStartTime()).equals(df.format(activityImp2_.getStartTime()))   ) //都是usertask,且主節點與後續節點的開始時間相同,說明不是真實的後繼節點
            {

            }
            else
            {
                sameActivityImpl1 = (FlowNode)bpmnModel.getMainProcess().getFlowElement(historicActivityInstances.get(k).getActivityId());//找到緊跟在後面的一個節點
                break;
            }

        }
        sameStartTimeNodes.add(sameActivityImpl1); // 将後面第一個節點放在時間相同節點的集合裡
        for (int j = i + 1; j < historicActivityInstances.size() - 1; j++)
        {
            HistoricActivityInstance activityImpl1 = historicActivityInstances.get(j);// 後續第一個節點
            HistoricActivityInstance activityImpl2 = historicActivityInstances.get(j + 1);// 後續第二個節點

            if (df.format(activityImpl1.getStartTime()).equals(df.format(activityImpl2.getStartTime()))  )
            {// 如果第一個節點和第二個節點開始時間相同儲存
                FlowNode sameActivityImpl2 = (FlowNode)bpmnModel.getMainProcess().getFlowElement(activityImpl2.getActivityId());
                sameStartTimeNodes.add(sameActivityImpl2);
            }
            else
            {// 有不相同跳出循環
                break;
            }
        }
        List<SequenceFlow> pvmTransitions = activityImpl.getOutgoingFlows() ; // 取出節點的所有出去的線

        for (SequenceFlow pvmTransition : pvmTransitions)
        {// 對所有的線進行周遊
            FlowNode pvmActivityImpl = (FlowNode)bpmnModel.getMainProcess().getFlowElement( pvmTransition.getTargetRef());// 如果取出的線的目标節點存在時間相同的節點裡,儲存該線的id,進行高亮顯示
            if (sameStartTimeNodes.contains(pvmActivityImpl)) {
                highFlows.add(pvmTransition.getId());
            }
        }

    }
    return highFlows;

}