| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.dolphinscheduler.api.service.impl; |
| |
| import static org.apache.dolphinscheduler.api.constants.ApiFuncIdentificationConstant.WORKFLOW_INSTANCE; |
| import static org.apache.dolphinscheduler.api.enums.Status.PROCESS_INSTANCE_NOT_EXIST; |
| import static org.apache.dolphinscheduler.api.enums.Status.PROCESS_INSTANCE_STATE_OPERATION_ERROR; |
| import static org.apache.dolphinscheduler.common.constants.Constants.DATA_LIST; |
| import static org.apache.dolphinscheduler.common.constants.Constants.DEPENDENT_SPLIT; |
| import static org.apache.dolphinscheduler.common.constants.Constants.GLOBAL_PARAMS; |
| import static org.apache.dolphinscheduler.common.constants.Constants.LOCAL_PARAMS; |
| import static org.apache.dolphinscheduler.common.constants.Constants.PROCESS_INSTANCE_STATE; |
| import static org.apache.dolphinscheduler.common.constants.Constants.TASK_LIST; |
| import static org.apache.dolphinscheduler.plugin.task.api.TaskConstants.TASK_TYPE_DEPENDENT; |
| import static org.apache.dolphinscheduler.plugin.task.api.TaskConstants.TASK_TYPE_SUB_PROCESS; |
| |
| import org.apache.dolphinscheduler.api.constants.ApiFuncIdentificationConstant; |
| import org.apache.dolphinscheduler.api.dto.DynamicSubWorkflowDto; |
| import org.apache.dolphinscheduler.api.dto.gantt.GanttDto; |
| import org.apache.dolphinscheduler.api.dto.gantt.Task; |
| import org.apache.dolphinscheduler.api.dto.workflowInstance.WorkflowInstanceQueryRequest; |
| import org.apache.dolphinscheduler.api.enums.Status; |
| import org.apache.dolphinscheduler.api.exceptions.ServiceException; |
| import org.apache.dolphinscheduler.api.service.ExecutorService; |
| import org.apache.dolphinscheduler.api.service.LoggerService; |
| import org.apache.dolphinscheduler.api.service.ProcessDefinitionService; |
| import org.apache.dolphinscheduler.api.service.ProcessInstanceService; |
| import org.apache.dolphinscheduler.api.service.ProjectService; |
| import org.apache.dolphinscheduler.api.service.TaskInstanceService; |
| import org.apache.dolphinscheduler.api.service.UsersService; |
| import org.apache.dolphinscheduler.api.utils.PageInfo; |
| import org.apache.dolphinscheduler.api.utils.Result; |
| import org.apache.dolphinscheduler.common.constants.CommandKeyConstants; |
| import org.apache.dolphinscheduler.common.constants.Constants; |
| import org.apache.dolphinscheduler.common.enums.Flag; |
| import org.apache.dolphinscheduler.common.enums.WorkflowExecutionStatus; |
| import org.apache.dolphinscheduler.common.graph.DAG; |
| import org.apache.dolphinscheduler.common.model.TaskNodeRelation; |
| import org.apache.dolphinscheduler.common.utils.DateUtils; |
| import org.apache.dolphinscheduler.common.utils.JSONUtils; |
| import org.apache.dolphinscheduler.common.utils.placeholder.BusinessTimeUtils; |
| import org.apache.dolphinscheduler.dao.AlertDao; |
| import org.apache.dolphinscheduler.dao.entity.ProcessDefinition; |
| import org.apache.dolphinscheduler.dao.entity.ProcessInstance; |
| import org.apache.dolphinscheduler.dao.entity.ProcessTaskRelationLog; |
| import org.apache.dolphinscheduler.dao.entity.Project; |
| import org.apache.dolphinscheduler.dao.entity.RelationSubWorkflow; |
| import org.apache.dolphinscheduler.dao.entity.ResponseTaskLog; |
| import org.apache.dolphinscheduler.dao.entity.TaskDefinition; |
| import org.apache.dolphinscheduler.dao.entity.TaskDefinitionLog; |
| import org.apache.dolphinscheduler.dao.entity.TaskInstance; |
| import org.apache.dolphinscheduler.dao.entity.User; |
| import org.apache.dolphinscheduler.dao.mapper.ProcessDefinitionLogMapper; |
| import org.apache.dolphinscheduler.dao.mapper.ProcessDefinitionMapper; |
| import org.apache.dolphinscheduler.dao.mapper.ProcessInstanceMapper; |
| import org.apache.dolphinscheduler.dao.mapper.ProjectMapper; |
| import org.apache.dolphinscheduler.dao.mapper.RelationSubWorkflowMapper; |
| import org.apache.dolphinscheduler.dao.mapper.TaskDefinitionLogMapper; |
| import org.apache.dolphinscheduler.dao.mapper.TaskDefinitionMapper; |
| import org.apache.dolphinscheduler.dao.mapper.TaskInstanceMapper; |
| import org.apache.dolphinscheduler.dao.repository.ProcessInstanceDao; |
| import org.apache.dolphinscheduler.dao.repository.ProcessInstanceMapDao; |
| import org.apache.dolphinscheduler.dao.repository.TaskInstanceDao; |
| import org.apache.dolphinscheduler.dao.utils.WorkflowUtils; |
| import org.apache.dolphinscheduler.plugin.task.api.TaskPluginManager; |
| import org.apache.dolphinscheduler.plugin.task.api.enums.DependResult; |
| import org.apache.dolphinscheduler.plugin.task.api.model.Property; |
| import org.apache.dolphinscheduler.plugin.task.api.parameters.ParametersNode; |
| import org.apache.dolphinscheduler.plugin.task.api.utils.ParameterUtils; |
| import org.apache.dolphinscheduler.service.expand.CuringParamsService; |
| import org.apache.dolphinscheduler.service.model.TaskNode; |
| import org.apache.dolphinscheduler.service.process.ProcessService; |
| |
| import org.apache.commons.lang3.StringUtils; |
| |
| import java.io.BufferedReader; |
| import java.io.ByteArrayInputStream; |
| import java.io.IOException; |
| import java.io.InputStreamReader; |
| import java.nio.charset.StandardCharsets; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Comparator; |
| import java.util.Date; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Objects; |
| import java.util.function.Function; |
| import java.util.stream.Collectors; |
| |
| import lombok.extern.slf4j.Slf4j; |
| |
| import org.springframework.beans.factory.annotation.Autowired; |
| import org.springframework.context.annotation.Lazy; |
| import org.springframework.stereotype.Service; |
| import org.springframework.transaction.annotation.Transactional; |
| |
| import com.baomidou.mybatisplus.core.metadata.IPage; |
| import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; |
| import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| |
| /** |
| * process instance service impl |
| */ |
| @Service |
| @Slf4j |
| public class ProcessInstanceServiceImpl extends BaseServiceImpl implements ProcessInstanceService { |
| |
| public static final String TASK_TYPE = "taskType"; |
| |
| public static final String LOCAL_PARAMS_LIST = "localParamsList"; |
| |
| @Autowired |
| ProjectMapper projectMapper; |
| |
| @Autowired |
| ProjectService projectService; |
| |
| @Autowired |
| ProcessService processService; |
| |
| @Autowired |
| TaskInstanceDao taskInstanceDao; |
| |
| @Lazy |
| @Autowired |
| private TaskInstanceService taskInstanceService; |
| |
| @Autowired |
| ProcessInstanceMapper processInstanceMapper; |
| |
| @Autowired |
| ProcessInstanceDao processInstanceDao; |
| |
| @Autowired |
| private ProcessInstanceMapDao processInstanceMapDao; |
| |
| @Autowired |
| ProcessDefinitionMapper processDefineMapper; |
| |
| @Autowired |
| ProcessDefinitionService processDefinitionService; |
| |
| @Autowired |
| ExecutorService execService; |
| |
| @Autowired |
| TaskInstanceMapper taskInstanceMapper; |
| |
| @Autowired |
| LoggerService loggerService; |
| |
| @Autowired |
| ProcessDefinitionLogMapper processDefinitionLogMapper; |
| |
| @Autowired |
| TaskDefinitionLogMapper taskDefinitionLogMapper; |
| |
| @Autowired |
| UsersService usersService; |
| |
| @Autowired |
| TaskDefinitionMapper taskDefinitionMapper; |
| |
| @Autowired |
| private RelationSubWorkflowMapper relationSubWorkflowMapper; |
| |
| @Autowired |
| private AlertDao alertDao; |
| |
| @Autowired |
| private CuringParamsService curingGlobalParamsService; |
| |
| /** |
| * return top n SUCCESS process instance order by running time which started between startTime and endTime |
| */ |
| @Override |
| public Map<String, Object> queryTopNLongestRunningProcessInstance(User loginUser, long projectCode, int size, |
| String startTime, String endTime) { |
| Project project = projectMapper.queryByCode(projectCode); |
| // check user access for project |
| Map<String, Object> result = |
| projectService.checkProjectAndAuth(loginUser, project, projectCode, |
| ApiFuncIdentificationConstant.WORKFLOW_INSTANCE); |
| if (result.get(Constants.STATUS) != Status.SUCCESS) { |
| return result; |
| } |
| |
| if (0 > size) { |
| putMsg(result, Status.NEGTIVE_SIZE_NUMBER_ERROR, size); |
| return result; |
| } |
| if (Objects.isNull(startTime)) { |
| putMsg(result, Status.DATA_IS_NULL, Constants.START_TIME); |
| return result; |
| } |
| Date start = DateUtils.stringToDate(startTime); |
| if (Objects.isNull(endTime)) { |
| putMsg(result, Status.DATA_IS_NULL, Constants.END_TIME); |
| return result; |
| } |
| Date end = DateUtils.stringToDate(endTime); |
| if (start == null || end == null) { |
| putMsg(result, Status.REQUEST_PARAMS_NOT_VALID_ERROR, Constants.START_END_DATE); |
| return result; |
| } |
| if (start.getTime() > end.getTime()) { |
| putMsg(result, Status.START_TIME_BIGGER_THAN_END_TIME_ERROR, startTime, endTime); |
| return result; |
| } |
| |
| List<ProcessInstance> processInstances = processInstanceMapper.queryTopNProcessInstance(size, start, end, |
| WorkflowExecutionStatus.SUCCESS, projectCode); |
| result.put(DATA_LIST, processInstances); |
| putMsg(result, Status.SUCCESS); |
| return result; |
| } |
| |
| /** |
| * query process instance by id |
| * |
| * @param loginUser login user |
| * @param projectCode project code |
| * @param processId process instance id |
| * @return process instance detail |
| */ |
| @Override |
| public Map<String, Object> queryProcessInstanceById(User loginUser, long projectCode, Integer processId) { |
| Project project = projectMapper.queryByCode(projectCode); |
| // check user access for project |
| Map<String, Object> result = |
| projectService.checkProjectAndAuth(loginUser, project, projectCode, |
| ApiFuncIdentificationConstant.WORKFLOW_INSTANCE); |
| if (result.get(Constants.STATUS) != Status.SUCCESS) { |
| return result; |
| } |
| ProcessInstance processInstance = processService.findProcessInstanceDetailById(processId) |
| .orElseThrow(() -> new ServiceException(PROCESS_INSTANCE_NOT_EXIST, processId)); |
| |
| ProcessDefinition processDefinition = |
| processService.findProcessDefinition(processInstance.getProcessDefinitionCode(), |
| processInstance.getProcessDefinitionVersion()); |
| |
| if (processDefinition == null || projectCode != processDefinition.getProjectCode()) { |
| log.error("Process definition does not exist, projectCode:{}.", projectCode); |
| putMsg(result, Status.PROCESS_DEFINE_NOT_EXIST, processId); |
| } else { |
| processInstance.setLocations(processDefinition.getLocations()); |
| processInstance.setDagData(processService.genDagData(processDefinition)); |
| result.put(DATA_LIST, processInstance); |
| putMsg(result, Status.SUCCESS); |
| } |
| |
| return result; |
| } |
| |
| @Override |
| public ProcessInstance queryByWorkflowInstanceIdThrowExceptionIfNotFound(Integer workflowInstanceId) { |
| ProcessInstance processInstance = processInstanceDao.queryById(workflowInstanceId); |
| if (processInstance == null) { |
| throw new ServiceException(PROCESS_INSTANCE_NOT_EXIST, workflowInstanceId); |
| } |
| return processInstance; |
| } |
| |
| /** |
| * query workflow instance by id |
| * |
| * @param loginUser login user |
| * @param workflowInstanceId workflow instance id |
| * @return workflow instance detail |
| */ |
| @Override |
| public Map<String, Object> queryProcessInstanceById(User loginUser, Integer workflowInstanceId) { |
| ProcessInstance processInstance = processInstanceMapper.selectById(workflowInstanceId); |
| ProcessDefinition processDefinition = |
| processDefineMapper.queryByCode(processInstance.getProcessDefinitionCode()); |
| |
| return queryProcessInstanceById(loginUser, processDefinition.getProjectCode(), workflowInstanceId); |
| } |
| |
| /** |
| * paging query process instance list, filtering according to project, process definition, time range, keyword, process status |
| * |
| * @param loginUser login user |
| * @param projectCode project code |
| * @param processDefineCode process definition code |
| * @param pageNo page number |
| * @param pageSize page size |
| * @param searchVal search value |
| * @param stateType state type |
| * @param host host |
| * @param startDate start time |
| * @param endDate end time |
| * @param otherParamsJson otherParamsJson handle other params |
| * @return process instance list |
| */ |
| @Override |
| public Result<PageInfo<ProcessInstance>> queryProcessInstanceList(User loginUser, |
| long projectCode, |
| long processDefineCode, |
| String startDate, |
| String endDate, |
| String searchVal, |
| String executorName, |
| WorkflowExecutionStatus stateType, |
| String host, |
| String otherParamsJson, |
| Integer pageNo, |
| Integer pageSize) { |
| |
| Result result = new Result(); |
| // check user access for project |
| projectService.checkProjectAndAuthThrowException(loginUser, projectCode, WORKFLOW_INSTANCE); |
| |
| int[] statusArray = null; |
| // filter by state |
| if (stateType != null) { |
| statusArray = new int[]{stateType.getCode()}; |
| } |
| |
| Date start = checkAndParseDateParameters(startDate); |
| Date end = checkAndParseDateParameters(endDate); |
| |
| Page<ProcessInstance> page = new Page<>(pageNo, pageSize); |
| PageInfo<ProcessInstance> pageInfo = new PageInfo<>(pageNo, pageSize); |
| |
| IPage<ProcessInstance> processInstanceList = processInstanceMapper.queryProcessInstanceListPaging( |
| page, |
| projectCode, |
| processDefineCode, |
| searchVal, |
| executorName, |
| statusArray, |
| host, |
| start, |
| end); |
| |
| List<ProcessInstance> processInstances = processInstanceList.getRecords(); |
| List<Integer> userIds = Collections.emptyList(); |
| if (CollectionUtils.isNotEmpty(processInstances)) { |
| userIds = processInstances.stream().map(ProcessInstance::getExecutorId).collect(Collectors.toList()); |
| } |
| List<User> users = usersService.queryUser(userIds); |
| Map<Integer, User> idToUserMap = Collections.emptyMap(); |
| if (CollectionUtils.isNotEmpty(users)) { |
| idToUserMap = users.stream().collect(Collectors.toMap(User::getId, Function.identity())); |
| } |
| |
| for (ProcessInstance processInstance : processInstances) { |
| processInstance.setDuration(WorkflowUtils.getWorkflowInstanceDuration(processInstance)); |
| User executor = idToUserMap.get(processInstance.getExecutorId()); |
| if (null != executor) { |
| processInstance.setExecutorName(executor.getUserName()); |
| } |
| } |
| |
| pageInfo.setTotal((int) processInstanceList.getTotal()); |
| pageInfo.setTotalList(processInstances); |
| result.setData(pageInfo); |
| putMsg(result, Status.SUCCESS); |
| return result; |
| } |
| |
| /** |
| * paging query process instance list, filtering according to project, process definition, time range, keyword, process status |
| * |
| * @param loginUser login user |
| * @param workflowInstanceQueryRequest workflowInstanceQueryRequest |
| * @return process instance list |
| */ |
| @Override |
| public Result queryProcessInstanceList(User loginUser, WorkflowInstanceQueryRequest workflowInstanceQueryRequest) { |
| Result result = new Result(); |
| ProcessInstance processInstance = workflowInstanceQueryRequest.convert2ProcessInstance(); |
| String projectName = workflowInstanceQueryRequest.getProjectName(); |
| if (!StringUtils.isBlank(projectName)) { |
| Project project = projectMapper.queryByName(projectName); |
| projectService.checkProjectAndAuthThrowException(loginUser, project, |
| ApiFuncIdentificationConstant.WORKFLOW_DEFINITION); |
| ProcessDefinition processDefinition = |
| processDefineMapper.queryByDefineName(project.getCode(), processInstance.getName()); |
| processInstance.setProcessDefinitionCode(processDefinition.getCode()); |
| processInstance.setProjectCode(project.getCode()); |
| } |
| |
| Page<ProcessInstance> page = |
| new Page<>(workflowInstanceQueryRequest.getPageNo(), workflowInstanceQueryRequest.getPageSize()); |
| PageInfo<ProcessInstance> pageInfo = |
| new PageInfo<>(workflowInstanceQueryRequest.getPageNo(), workflowInstanceQueryRequest.getPageSize()); |
| |
| IPage<ProcessInstance> processInstanceList = processInstanceMapper.queryProcessInstanceListV2Paging( |
| page, |
| processInstance.getProjectCode(), |
| processInstance.getProcessDefinitionCode(), |
| processInstance.getName(), |
| workflowInstanceQueryRequest.getStartTime(), |
| workflowInstanceQueryRequest.getEndTime(), |
| workflowInstanceQueryRequest.getState(), |
| processInstance.getHost()); |
| |
| List<ProcessInstance> processInstances = processInstanceList.getRecords(); |
| List<Integer> userIds = Collections.emptyList(); |
| if (CollectionUtils.isNotEmpty(processInstances)) { |
| userIds = processInstances.stream().map(ProcessInstance::getExecutorId).collect(Collectors.toList()); |
| } |
| List<User> users = usersService.queryUser(userIds); |
| Map<Integer, User> idToUserMap = Collections.emptyMap(); |
| if (CollectionUtils.isNotEmpty(users)) { |
| idToUserMap = users.stream().collect(Collectors.toMap(User::getId, Function.identity())); |
| } |
| |
| for (ProcessInstance Instance : processInstances) { |
| Instance.setDuration(WorkflowUtils.getWorkflowInstanceDuration(Instance)); |
| User executor = idToUserMap.get(Instance.getExecutorId()); |
| if (null != executor) { |
| Instance.setExecutorName(executor.getUserName()); |
| } |
| } |
| |
| pageInfo.setTotal((int) processInstanceList.getTotal()); |
| pageInfo.setTotalList(processInstances); |
| result.setData(pageInfo); |
| putMsg(result, Status.SUCCESS); |
| return result; |
| } |
| |
| /** |
| * query task list by process instance id |
| * |
| * @param loginUser login user |
| * @param projectCode project code |
| * @param processId process instance id |
| * @return task list for the process instance |
| * @throws IOException io exception |
| */ |
| @Override |
| public Map<String, Object> queryTaskListByProcessId(User loginUser, long projectCode, |
| Integer processId) throws IOException { |
| Project project = projectMapper.queryByCode(projectCode); |
| // check user access for project |
| Map<String, Object> result = |
| projectService.checkProjectAndAuth(loginUser, project, projectCode, |
| ApiFuncIdentificationConstant.WORKFLOW_INSTANCE); |
| if (result.get(Constants.STATUS) != Status.SUCCESS) { |
| return result; |
| } |
| ProcessInstance processInstance = processService.findProcessInstanceDetailById(processId) |
| .orElseThrow(() -> new ServiceException(PROCESS_INSTANCE_NOT_EXIST, processId)); |
| ProcessDefinition processDefinition = |
| processDefineMapper.queryByCode(processInstance.getProcessDefinitionCode()); |
| if (processDefinition != null && projectCode != processDefinition.getProjectCode()) { |
| log.error("Process definition does not exist, projectCode:{}, processDefinitionId:{}.", projectCode, |
| processId); |
| putMsg(result, PROCESS_INSTANCE_NOT_EXIST, processId); |
| return result; |
| } |
| List<TaskInstance> taskInstanceList = |
| taskInstanceDao.queryValidTaskListByWorkflowInstanceId(processId, processInstance.getTestFlag()); |
| addDependResultForTaskList(loginUser, taskInstanceList); |
| Map<String, Object> resultMap = new HashMap<>(); |
| resultMap.put(PROCESS_INSTANCE_STATE, processInstance.getState().toString()); |
| resultMap.put(TASK_LIST, taskInstanceList); |
| result.put(DATA_LIST, resultMap); |
| |
| putMsg(result, Status.SUCCESS); |
| return result; |
| } |
| |
| @Override |
| public List<DynamicSubWorkflowDto> queryDynamicSubWorkflowInstances(User loginUser, Integer taskId) { |
| TaskInstance taskInstance = taskInstanceDao.queryById(taskId); |
| Map<String, Object> result = new HashMap<>(); |
| if (taskInstance == null) { |
| putMsg(result, Status.TASK_INSTANCE_NOT_EXISTS, taskId); |
| throw new ServiceException(Status.TASK_INSTANCE_NOT_EXISTS, taskId); |
| } |
| |
| TaskDefinition taskDefinition = taskDefinitionMapper.queryByCode(taskInstance.getTaskCode()); |
| if (taskDefinition == null) { |
| putMsg(result, Status.TASK_INSTANCE_NOT_EXISTS, taskId); |
| throw new ServiceException(Status.TASK_INSTANCE_NOT_EXISTS, taskId); |
| } |
| |
| if (!taskInstance.isDynamic()) { |
| putMsg(result, Status.TASK_INSTANCE_NOT_DYNAMIC_TASK, taskInstance.getName()); |
| throw new ServiceException(Status.TASK_INSTANCE_NOT_EXISTS, taskId); |
| } |
| List<RelationSubWorkflow> relationSubWorkflows = relationSubWorkflowMapper |
| .queryAllSubProcessInstance((long) taskInstance.getProcessInstanceId(), |
| taskInstance.getTaskCode()); |
| List<Long> allSubProcessInstanceId = relationSubWorkflows.stream() |
| .map(RelationSubWorkflow::getSubWorkflowInstanceId).collect(java.util.stream.Collectors.toList()); |
| List<ProcessInstance> allSubWorkflows = processInstanceDao.queryByIds(allSubProcessInstanceId); |
| |
| if (allSubWorkflows == null || allSubWorkflows.isEmpty()) { |
| putMsg(result, Status.SUB_PROCESS_INSTANCE_NOT_EXIST, taskId); |
| throw new ServiceException(Status.SUB_PROCESS_INSTANCE_NOT_EXIST, taskId); |
| } |
| Long subWorkflowCode = allSubWorkflows.get(0).getProcessDefinitionCode(); |
| int subWorkflowVersion = allSubWorkflows.get(0).getProcessDefinitionVersion(); |
| ProcessDefinition subProcessDefinition = |
| processService.findProcessDefinition(subWorkflowCode, subWorkflowVersion); |
| if (subProcessDefinition == null) { |
| putMsg(result, Status.PROCESS_DEFINE_NOT_EXIST, subWorkflowCode); |
| throw new ServiceException(Status.PROCESS_DEFINE_NOT_EXIST, subWorkflowCode); |
| } |
| |
| allSubWorkflows.sort(Comparator.comparing(ProcessInstance::getId)); |
| |
| List<DynamicSubWorkflowDto> allDynamicSubWorkflowDtos = new ArrayList<>(); |
| int index = 1; |
| for (ProcessInstance processInstance : allSubWorkflows) { |
| DynamicSubWorkflowDto dynamicSubWorkflowDto = new DynamicSubWorkflowDto(); |
| dynamicSubWorkflowDto.setProcessInstanceId(processInstance.getId()); |
| dynamicSubWorkflowDto.setIndex(index); |
| dynamicSubWorkflowDto.setState(processInstance.getState()); |
| dynamicSubWorkflowDto.setName(subProcessDefinition.getName()); |
| Map<String, String> commandParamMap = JSONUtils.toMap(processInstance.getCommandParam()); |
| String parameter = commandParamMap.get(CommandKeyConstants.CMD_DYNAMIC_START_PARAMS); |
| dynamicSubWorkflowDto.setParameters(JSONUtils.toMap(parameter)); |
| allDynamicSubWorkflowDtos.add(dynamicSubWorkflowDto); |
| index++; |
| |
| } |
| |
| return allDynamicSubWorkflowDtos; |
| } |
| |
| /** |
| * add dependent result for dependent task |
| */ |
| private void addDependResultForTaskList(User loginUser, List<TaskInstance> taskInstanceList) throws IOException { |
| for (TaskInstance taskInstance : taskInstanceList) { |
| if (TASK_TYPE_DEPENDENT.equalsIgnoreCase(taskInstance.getTaskType())) { |
| log.info("DEPENDENT type task instance need to set dependent result, taskCode:{}, taskInstanceId:{}", |
| taskInstance.getTaskCode(), taskInstance.getId()); |
| // TODO The result of dependent item should not be obtained from the log, waiting for optimization. |
| Result<ResponseTaskLog> logResult = loggerService.queryLog(loginUser, |
| taskInstance.getId(), Constants.LOG_QUERY_SKIP_LINE_NUMBER, Constants.LOG_QUERY_LIMIT); |
| if (logResult.getCode() == Status.SUCCESS.ordinal()) { |
| String log = logResult.getData().getMessage(); |
| Map<String, DependResult> resultMap = parseLogForDependentResult(log); |
| taskInstance.setDependentResult(JSONUtils.toJsonString(resultMap)); |
| } |
| } |
| } |
| } |
| |
| @Override |
| public Map<String, DependResult> parseLogForDependentResult(String content) throws IOException { |
| Map<String, DependResult> resultMap = new HashMap<>(); |
| if (StringUtils.isEmpty(content)) { |
| log.warn("Log content is empty."); |
| return resultMap; |
| } |
| |
| BufferedReader br = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(content.getBytes( |
| StandardCharsets.UTF_8)), StandardCharsets.UTF_8)); |
| String line; |
| while ((line = br.readLine()) != null) { |
| if (line.contains(DEPENDENT_SPLIT)) { |
| String[] tmpStringArray = line.split(":\\|\\|"); |
| if (tmpStringArray.length != 2) { |
| continue; |
| } |
| String dependResultString = tmpStringArray[1]; |
| String[] dependStringArray = dependResultString.split(","); |
| if (dependStringArray.length != 3) { |
| continue; |
| } |
| String key = dependStringArray[0].trim().split(":")[1].trim(); |
| String result = dependStringArray[1].trim().split(":")[1].trim(); |
| DependResult dependResult = DependResult.valueOf(result); |
| resultMap.put(key, dependResult); |
| } |
| } |
| return resultMap; |
| } |
| |
| /** |
| * query sub process instance detail info by task id |
| * |
| * @param loginUser login user |
| * @param projectCode project code |
| * @param taskId task id |
| * @return sub process instance detail |
| */ |
| @Override |
| public Map<String, Object> querySubProcessInstanceByTaskId(User loginUser, long projectCode, Integer taskId) { |
| Project project = projectMapper.queryByCode(projectCode); |
| // check user access for project |
| Map<String, Object> result = |
| projectService.checkProjectAndAuth(loginUser, project, projectCode, |
| ApiFuncIdentificationConstant.WORKFLOW_INSTANCE); |
| if (result.get(Constants.STATUS) != Status.SUCCESS) { |
| return result; |
| } |
| |
| TaskInstance taskInstance = taskInstanceDao.queryById(taskId); |
| if (taskInstance == null) { |
| log.error("Task instance does not exist, projectCode:{}, taskInstanceId{}.", projectCode, taskId); |
| putMsg(result, Status.TASK_INSTANCE_NOT_EXISTS, taskId); |
| return result; |
| } |
| |
| TaskDefinition taskDefinition = taskDefinitionMapper.queryByCode(taskInstance.getTaskCode()); |
| if (taskDefinition != null && projectCode != taskDefinition.getProjectCode()) { |
| log.error("Task definition does not exist, projectCode:{}, taskDefinitionCode:{}.", projectCode, |
| taskInstance.getTaskCode()); |
| putMsg(result, Status.TASK_INSTANCE_NOT_EXISTS, taskId); |
| return result; |
| } |
| |
| if (!taskInstance.isSubProcess()) { |
| log.warn("Task instance is not {} type instance, projectCode:{}, taskInstanceId:{}.", |
| TASK_TYPE_SUB_PROCESS, projectCode, taskId); |
| putMsg(result, Status.TASK_INSTANCE_NOT_SUB_WORKFLOW_INSTANCE, taskInstance.getName()); |
| return result; |
| } |
| |
| ProcessInstance subWorkflowInstance = processService.findSubProcessInstance( |
| taskInstance.getProcessInstanceId(), taskInstance.getId()); |
| if (subWorkflowInstance == null) { |
| log.error("SubProcess instance does not exist, projectCode:{}, taskInstanceId:{}.", projectCode, |
| taskInstance.getId()); |
| putMsg(result, Status.SUB_PROCESS_INSTANCE_NOT_EXIST, taskId); |
| return result; |
| } |
| Map<String, Object> dataMap = new HashMap<>(); |
| dataMap.put(Constants.SUBPROCESS_INSTANCE_ID, subWorkflowInstance.getId()); |
| result.put(DATA_LIST, dataMap); |
| putMsg(result, Status.SUCCESS); |
| return result; |
| } |
| |
| /** |
| * update process instance |
| * |
| * @param loginUser login user |
| * @param projectCode project code |
| * @param taskRelationJson process task relation json |
| * @param taskDefinitionJson taskDefinitionJson |
| * @param processInstanceId process instance id |
| * @param scheduleTime schedule time |
| * @param syncDefine sync define |
| * @param globalParams global params |
| * @param locations locations for nodes |
| * @param timeout timeout |
| * @return update result code |
| */ |
| @Transactional |
| @Override |
| public Map<String, Object> updateProcessInstance(User loginUser, long projectCode, Integer processInstanceId, |
| String taskRelationJson, |
| String taskDefinitionJson, String scheduleTime, Boolean syncDefine, |
| String globalParams, |
| String locations, int timeout) { |
| // check user access for project |
| projectService.checkProjectAndAuthThrowException(loginUser, projectCode, |
| ApiFuncIdentificationConstant.INSTANCE_UPDATE); |
| Map<String, Object> result = new HashMap<>(); |
| // check process instance exists |
| ProcessInstance processInstance = processService.findProcessInstanceDetailById(processInstanceId) |
| .orElseThrow(() -> new ServiceException(PROCESS_INSTANCE_NOT_EXIST, processInstanceId)); |
| // check process instance exists in project |
| ProcessDefinition processDefinition0 = |
| processDefineMapper.queryByCode(processInstance.getProcessDefinitionCode()); |
| if (processDefinition0 != null && projectCode != processDefinition0.getProjectCode()) { |
| log.error("Process definition does not exist, projectCode:{}, processDefinitionCode:{}.", projectCode, |
| processInstance.getProcessDefinitionCode()); |
| putMsg(result, PROCESS_INSTANCE_NOT_EXIST, processInstanceId); |
| return result; |
| } |
| // check process instance status |
| if (!processInstance.getState().isFinished()) { |
| log.warn("Process Instance state is {} so can not update process instance, processInstanceId:{}.", |
| processInstance.getState().getDesc(), processInstanceId); |
| putMsg(result, PROCESS_INSTANCE_STATE_OPERATION_ERROR, |
| processInstance.getName(), processInstance.getState().toString(), "update"); |
| return result; |
| } |
| |
| // |
| Map<String, String> commandParamMap = JSONUtils.toMap(processInstance.getCommandParam()); |
| String timezoneId = null; |
| if (commandParamMap == null || StringUtils.isBlank(commandParamMap.get(Constants.SCHEDULE_TIMEZONE))) { |
| timezoneId = loginUser.getTimeZone(); |
| } else { |
| timezoneId = commandParamMap.get(Constants.SCHEDULE_TIMEZONE); |
| } |
| |
| setProcessInstance(processInstance, scheduleTime, globalParams, timeout, timezoneId); |
| List<TaskDefinitionLog> taskDefinitionLogs = JSONUtils.toList(taskDefinitionJson, TaskDefinitionLog.class); |
| if (taskDefinitionLogs.isEmpty()) { |
| log.warn("Parameter taskDefinitionJson is empty"); |
| putMsg(result, Status.DATA_IS_NOT_VALID, taskDefinitionJson); |
| return result; |
| } |
| for (TaskDefinitionLog taskDefinitionLog : taskDefinitionLogs) { |
| if (!TaskPluginManager.checkTaskParameters(ParametersNode.builder() |
| .taskType(taskDefinitionLog.getTaskType()) |
| .taskParams(taskDefinitionLog.getTaskParams()) |
| .dependence(taskDefinitionLog.getDependence()) |
| .build())) { |
| log.error("Task parameters are invalid, taskDefinitionName:{}.", taskDefinitionLog.getName()); |
| putMsg(result, Status.PROCESS_NODE_S_PARAMETER_INVALID, taskDefinitionLog.getName()); |
| return result; |
| } |
| } |
| int saveTaskResult = processService.saveTaskDefine(loginUser, projectCode, taskDefinitionLogs, syncDefine); |
| if (saveTaskResult == Constants.DEFINITION_FAILURE) { |
| log.error("Update task definition error, projectCode:{}, processInstanceId:{}", projectCode, |
| processInstanceId); |
| putMsg(result, Status.UPDATE_TASK_DEFINITION_ERROR); |
| throw new ServiceException(Status.UPDATE_TASK_DEFINITION_ERROR); |
| } |
| ProcessDefinition processDefinition = |
| processDefineMapper.queryByCode(processInstance.getProcessDefinitionCode()); |
| List<ProcessTaskRelationLog> taskRelationList = |
| JSONUtils.toList(taskRelationJson, ProcessTaskRelationLog.class); |
| // check workflow json is valid |
| result = processDefinitionService.checkProcessNodeList(taskRelationJson, taskDefinitionLogs); |
| if (result.get(Constants.STATUS) != Status.SUCCESS) { |
| return result; |
| } |
| |
| processDefinition.set(projectCode, processDefinition.getName(), processDefinition.getDescription(), |
| globalParams, locations, timeout); |
| processDefinition.setUpdateTime(new Date()); |
| int insertVersion = processService.saveProcessDefine(loginUser, processDefinition, syncDefine, Boolean.FALSE); |
| if (insertVersion == 0) { |
| log.error("Update process definition error, projectCode:{}, processDefinitionName:{}.", projectCode, |
| processDefinition.getName()); |
| putMsg(result, Status.UPDATE_PROCESS_DEFINITION_ERROR); |
| throw new ServiceException(Status.UPDATE_PROCESS_DEFINITION_ERROR); |
| } else |
| log.info("Update process definition complete, projectCode:{}, processDefinitionName:{}.", projectCode, |
| processDefinition.getName()); |
| int insertResult = processService.saveTaskRelation(loginUser, processDefinition.getProjectCode(), |
| processDefinition.getCode(), insertVersion, taskRelationList, taskDefinitionLogs, syncDefine); |
| if (insertResult == Constants.EXIT_CODE_SUCCESS) { |
| log.info( |
| "Update task relations complete, projectCode:{}, processDefinitionCode:{}, processDefinitionVersion:{}.", |
| projectCode, processDefinition.getCode(), insertVersion); |
| putMsg(result, Status.SUCCESS); |
| result.put(Constants.DATA_LIST, processDefinition); |
| } else { |
| log.info( |
| "Update task relations error, projectCode:{}, processDefinitionCode:{}, processDefinitionVersion:{}.", |
| projectCode, processDefinition.getCode(), insertVersion); |
| putMsg(result, Status.UPDATE_PROCESS_DEFINITION_ERROR); |
| throw new ServiceException(Status.UPDATE_PROCESS_DEFINITION_ERROR); |
| } |
| processInstance.setProcessDefinitionVersion(insertVersion); |
| boolean update = processInstanceDao.updateById(processInstance); |
| if (!update) { |
| log.error( |
| "Update process instance version error, projectCode:{}, processDefinitionCode:{}, processDefinitionVersion:{}", |
| projectCode, processDefinition.getCode(), insertVersion); |
| putMsg(result, Status.UPDATE_PROCESS_INSTANCE_ERROR); |
| throw new ServiceException(Status.UPDATE_PROCESS_INSTANCE_ERROR); |
| } |
| log.info( |
| "Update process instance complete, projectCode:{}, processDefinitionCode:{}, processDefinitionVersion:{}, processInstanceId:{}", |
| projectCode, processDefinition.getCode(), insertVersion, processInstanceId); |
| putMsg(result, Status.SUCCESS); |
| return result; |
| } |
| |
| /** |
| * update process instance attributes |
| */ |
| private void setProcessInstance(ProcessInstance processInstance, String scheduleTime, |
| String globalParams, int timeout, String timezone) { |
| Date schedule = processInstance.getScheduleTime(); |
| if (scheduleTime != null) { |
| schedule = DateUtils.stringToDate(scheduleTime); |
| } |
| processInstance.setScheduleTime(schedule); |
| List<Property> globalParamList = JSONUtils.toList(globalParams, Property.class); |
| Map<String, String> globalParamMap = |
| globalParamList.stream().collect(Collectors.toMap(Property::getProp, Property::getValue)); |
| globalParams = curingGlobalParamsService.curingGlobalParams(processInstance.getId(), globalParamMap, |
| globalParamList, processInstance.getCmdTypeIfComplement(), schedule, timezone); |
| processInstance.setTimeout(timeout); |
| processInstance.setGlobalParams(globalParams); |
| } |
| |
| /** |
| * query parent process instance detail info by sub process instance id |
| * |
| * @param loginUser login user |
| * @param projectCode project code |
| * @param subId sub process id |
| * @return parent instance detail |
| */ |
| @Override |
| public Map<String, Object> queryParentInstanceBySubId(User loginUser, long projectCode, Integer subId) { |
| Project project = projectMapper.queryByCode(projectCode); |
| // check user access for project |
| Map<String, Object> result = |
| projectService.checkProjectAndAuth(loginUser, project, projectCode, |
| ApiFuncIdentificationConstant.WORKFLOW_INSTANCE); |
| if (result.get(Constants.STATUS) != Status.SUCCESS) { |
| return result; |
| } |
| |
| ProcessInstance subInstance = processService.findProcessInstanceDetailById(subId) |
| .orElseThrow(() -> new ServiceException(PROCESS_INSTANCE_NOT_EXIST, subId)); |
| if (subInstance.getIsSubProcess() == Flag.NO) { |
| log.warn( |
| "Process instance is not sub process instance type, processInstanceId:{}, processInstanceName:{}.", |
| subId, subInstance.getName()); |
| putMsg(result, Status.PROCESS_INSTANCE_NOT_SUB_PROCESS_INSTANCE, subInstance.getName()); |
| return result; |
| } |
| |
| ProcessInstance parentWorkflowInstance = processService.findParentProcessInstance(subId); |
| if (parentWorkflowInstance == null) { |
| log.error("Parent process instance does not exist, projectCode:{}, subProcessInstanceId:{}.", |
| projectCode, subId); |
| putMsg(result, Status.SUB_PROCESS_INSTANCE_NOT_EXIST); |
| return result; |
| } |
| Map<String, Object> dataMap = new HashMap<>(); |
| dataMap.put(Constants.PARENT_WORKFLOW_INSTANCE, parentWorkflowInstance.getId()); |
| result.put(DATA_LIST, dataMap); |
| putMsg(result, Status.SUCCESS); |
| return result; |
| } |
| |
| /** |
| * delete process instance by id, at the same time,delete task instance and their mapping relation data |
| * |
| * @param loginUser login user |
| * @param processInstanceId process instance id |
| * @return delete result code |
| */ |
| @Override |
| @Transactional |
| public void deleteProcessInstanceById(User loginUser, Integer processInstanceId) { |
| ProcessInstance processInstance = processService.findProcessInstanceDetailById(processInstanceId) |
| .orElseThrow(() -> new ServiceException(PROCESS_INSTANCE_NOT_EXIST, processInstanceId)); |
| ProcessDefinition processDefinition = processDefinitionLogMapper.queryByDefinitionCodeAndVersion( |
| processInstance.getProcessDefinitionCode(), processInstance.getProcessDefinitionVersion()); |
| |
| Project project = projectMapper.queryByCode(processDefinition.getProjectCode()); |
| // check user access for project |
| projectService.checkProjectAndAuthThrowException(loginUser, project, |
| ApiFuncIdentificationConstant.INSTANCE_DELETE); |
| // check process instance status |
| if (!processInstance.getState().isFinished()) { |
| log.warn("Process Instance state is {} so can not delete process instance, processInstanceId:{}.", |
| processInstance.getState().getDesc(), processInstanceId); |
| throw new ServiceException(PROCESS_INSTANCE_STATE_OPERATION_ERROR, processInstance.getName(), |
| processInstance.getState(), "delete"); |
| } |
| deleteProcessInstanceById(processInstanceId); |
| } |
| |
| /** |
| * view process instance variables |
| * |
| * @param projectCode project code |
| * @param processInstanceId process instance id |
| * @return variables data |
| */ |
| @Override |
| public Map<String, Object> viewVariables(long projectCode, Integer processInstanceId) { |
| Map<String, Object> result = new HashMap<>(); |
| |
| ProcessInstance processInstance = processInstanceMapper.queryDetailById(processInstanceId); |
| |
| if (processInstance == null) { |
| log.error("Process instance does not exist, projectCode:{}, processInstanceId:{}.", projectCode, |
| processInstanceId); |
| putMsg(result, Status.PROCESS_INSTANCE_NOT_EXIST, processInstanceId); |
| return result; |
| } |
| |
| ProcessDefinition processDefinition = |
| processDefineMapper.queryByCode(processInstance.getProcessDefinitionCode()); |
| if (processDefinition != null && projectCode != processDefinition.getProjectCode()) { |
| log.error("Process definition does not exist, projectCode:{}, processDefinitionCode:{}.", projectCode, |
| processInstance.getProcessDefinitionCode()); |
| putMsg(result, PROCESS_INSTANCE_NOT_EXIST, processInstanceId); |
| return result; |
| } |
| |
| Map<String, String> commandParam = JSONUtils.toMap(processInstance.getCommandParam()); |
| String timezone = null; |
| if (commandParam != null) { |
| timezone = commandParam.get(Constants.SCHEDULE_TIMEZONE); |
| } |
| Map<String, String> timeParams = BusinessTimeUtils |
| .getBusinessTime(processInstance.getCmdTypeIfComplement(), |
| processInstance.getScheduleTime(), timezone); |
| String userDefinedParams = processInstance.getGlobalParams(); |
| // global params |
| List<Property> globalParams = new ArrayList<>(); |
| |
| // global param string |
| String globalParamStr = |
| ParameterUtils.convertParameterPlaceholders(JSONUtils.toJsonString(globalParams), timeParams); |
| globalParams = JSONUtils.toList(globalParamStr, Property.class); |
| for (Property property : globalParams) { |
| timeParams.put(property.getProp(), property.getValue()); |
| } |
| |
| if (userDefinedParams != null && userDefinedParams.length() > 0) { |
| globalParams = JSONUtils.toList(userDefinedParams, Property.class); |
| } |
| |
| Map<String, Map<String, Object>> localUserDefParams = getLocalParams(processInstance, timeParams); |
| |
| Map<String, Object> resultMap = new HashMap<>(); |
| |
| resultMap.put(GLOBAL_PARAMS, globalParams); |
| resultMap.put(LOCAL_PARAMS, localUserDefParams); |
| |
| result.put(DATA_LIST, resultMap); |
| putMsg(result, Status.SUCCESS); |
| return result; |
| } |
| |
| /** |
| * get local params |
| */ |
| private Map<String, Map<String, Object>> getLocalParams(ProcessInstance processInstance, |
| Map<String, String> timeParams) { |
| Map<String, Map<String, Object>> localUserDefParams = new HashMap<>(); |
| List<TaskInstance> taskInstanceList = |
| taskInstanceMapper.findValidTaskListByProcessId(processInstance.getId(), Flag.YES, |
| processInstance.getTestFlag()); |
| for (TaskInstance taskInstance : taskInstanceList) { |
| TaskDefinitionLog taskDefinitionLog = taskDefinitionLogMapper.queryByDefinitionCodeAndVersion( |
| taskInstance.getTaskCode(), taskInstance.getTaskDefinitionVersion()); |
| |
| String localParams = JSONUtils.getNodeString(taskDefinitionLog.getTaskParams(), LOCAL_PARAMS); |
| if (!StringUtils.isEmpty(localParams)) { |
| localParams = ParameterUtils.convertParameterPlaceholders(localParams, timeParams); |
| List<Property> localParamsList = JSONUtils.toList(localParams, Property.class); |
| |
| Map<String, Object> localParamsMap = new HashMap<>(); |
| localParamsMap.put(TASK_TYPE, taskDefinitionLog.getTaskType()); |
| localParamsMap.put(LOCAL_PARAMS_LIST, localParamsList); |
| if (CollectionUtils.isNotEmpty(localParamsList)) { |
| localUserDefParams.put(taskDefinitionLog.getName(), localParamsMap); |
| } |
| } |
| } |
| return localUserDefParams; |
| } |
| |
| /** |
| * encapsulation gantt structure |
| * |
| * @param projectCode project code |
| * @param processInstanceId process instance id |
| * @return gantt tree data |
| * @throws Exception exception when json parse |
| */ |
| @Override |
| public Map<String, Object> viewGantt(long projectCode, Integer processInstanceId) throws Exception { |
| Map<String, Object> result = new HashMap<>(); |
| ProcessInstance processInstance = processInstanceMapper.queryDetailById(processInstanceId); |
| |
| if (processInstance == null) { |
| log.error("Process instance does not exist, projectCode:{}, processInstanceId:{}.", projectCode, |
| processInstanceId); |
| putMsg(result, Status.PROCESS_INSTANCE_NOT_EXIST, processInstanceId); |
| return result; |
| } |
| |
| ProcessDefinition processDefinition = processDefinitionLogMapper.queryByDefinitionCodeAndVersion( |
| processInstance.getProcessDefinitionCode(), |
| processInstance.getProcessDefinitionVersion()); |
| if (processDefinition == null || projectCode != processDefinition.getProjectCode()) { |
| log.error("Process definition does not exist, projectCode:{}, processDefinitionCode:{}.", projectCode, |
| processInstance.getProcessDefinitionCode()); |
| putMsg(result, PROCESS_INSTANCE_NOT_EXIST, processInstanceId); |
| return result; |
| } |
| GanttDto ganttDto = new GanttDto(); |
| DAG<Long, TaskNode, TaskNodeRelation> dag = processService.genDagGraph(processDefinition); |
| // topological sort |
| List<Long> nodeList = dag.topologicalSort(); |
| |
| ganttDto.setTaskNames(nodeList); |
| |
| List<Task> taskList = new ArrayList<>(); |
| if (CollectionUtils.isNotEmpty(nodeList)) { |
| List<TaskInstance> taskInstances = taskInstanceMapper.queryByProcessInstanceIdsAndTaskCodes( |
| Collections.singletonList(processInstanceId), nodeList); |
| for (Long node : nodeList) { |
| TaskInstance taskInstance = null; |
| for (TaskInstance instance : taskInstances) { |
| if (instance.getProcessInstanceId() == processInstanceId && instance.getTaskCode() == node) { |
| taskInstance = instance; |
| break; |
| } |
| } |
| if (taskInstance == null) { |
| continue; |
| } |
| Date startTime = taskInstance.getStartTime() == null ? new Date() : taskInstance.getStartTime(); |
| Date endTime = taskInstance.getEndTime() == null ? new Date() : taskInstance.getEndTime(); |
| Task task = new Task(); |
| task.setTaskName(taskInstance.getName()); |
| task.getStartDate().add(startTime.getTime()); |
| task.getEndDate().add(endTime.getTime()); |
| task.setIsoStart(startTime); |
| task.setIsoEnd(endTime); |
| task.setStatus(taskInstance.getState().name()); |
| task.setExecutionDate(taskInstance.getStartTime()); |
| task.setDuration(DateUtils.format2Readable(endTime.getTime() - startTime.getTime())); |
| taskList.add(task); |
| } |
| } |
| ganttDto.setTasks(taskList); |
| |
| result.put(DATA_LIST, ganttDto); |
| putMsg(result, Status.SUCCESS); |
| return result; |
| } |
| |
| /** |
| * query process instance by processDefinitionCode and stateArray |
| * |
| * @param processDefinitionCode processDefinitionCode |
| * @param states states array |
| * @return process instance list |
| */ |
| @Override |
| public List<ProcessInstance> queryByProcessDefineCodeAndStatus(Long processDefinitionCode, int[] states) { |
| return processInstanceMapper.queryByProcessDefineCodeAndStatus(processDefinitionCode, states); |
| } |
| |
| @Override |
| public List<ProcessInstance> queryByWorkflowCodeVersionStatus(Long workflowDefinitionCode, |
| int workflowDefinitionVersion, int[] states) { |
| return processInstanceDao.queryByWorkflowCodeVersionStatus(workflowDefinitionCode, workflowDefinitionVersion, |
| states); |
| } |
| |
| /** |
| * query process instance by processDefinitionCode |
| * |
| * @param processDefinitionCode processDefinitionCode |
| * @param size size |
| * @return process instance list |
| */ |
| @Override |
| public List<ProcessInstance> queryByProcessDefineCode(Long processDefinitionCode, int size) { |
| return processInstanceMapper.queryByProcessDefineCode(processDefinitionCode, size); |
| } |
| |
| /** |
| * query process instance list bt trigger code |
| * |
| * @param loginUser |
| * @param projectCode |
| * @param triggerCode |
| * @return |
| */ |
| @Override |
| public Map<String, Object> queryByTriggerCode(User loginUser, long projectCode, Long triggerCode) { |
| |
| Project project = projectMapper.queryByCode(projectCode); |
| // check user access for project |
| Map<String, Object> result = |
| projectService.checkProjectAndAuth(loginUser, project, projectCode, WORKFLOW_INSTANCE); |
| if (result.get(Constants.STATUS) != Status.SUCCESS || triggerCode == null) { |
| return result; |
| } |
| |
| List<ProcessInstance> processInstances = processInstanceMapper.queryByTriggerCode( |
| triggerCode); |
| result.put(DATA_LIST, processInstances); |
| putMsg(result, Status.SUCCESS); |
| return result; |
| } |
| |
| @Override |
| public void deleteProcessInstanceByWorkflowDefinitionCode(long workflowDefinitionCode) { |
| while (true) { |
| List<ProcessInstance> processInstances = |
| processInstanceMapper.queryByProcessDefineCode(workflowDefinitionCode, 100); |
| if (CollectionUtils.isEmpty(processInstances)) { |
| break; |
| } |
| log.info("Begin to delete workflow instance, workflow definition code: {}", workflowDefinitionCode); |
| for (ProcessInstance processInstance : processInstances) { |
| if (!processInstance.getState().isFinished()) { |
| log.warn("Workflow instance is not finished cannot delete, process instance id:{}", |
| processInstance.getId()); |
| throw new ServiceException(PROCESS_INSTANCE_STATE_OPERATION_ERROR, processInstance.getName(), |
| processInstance.getState(), "delete"); |
| } |
| deleteProcessInstanceById(processInstance.getId()); |
| } |
| log.info("Success delete workflow instance, workflow definition code: {}, size: {}", |
| workflowDefinitionCode, processInstances.size()); |
| } |
| } |
| |
| @Override |
| public void deleteProcessInstanceById(int workflowInstanceId) { |
| // delete task instance |
| taskInstanceService.deleteByWorkflowInstanceId(workflowInstanceId); |
| // delete sub process instances |
| deleteSubWorkflowInstanceIfNeeded(workflowInstanceId); |
| // delete alert |
| alertDao.deleteByWorkflowInstanceId(workflowInstanceId); |
| // delete process instance |
| processInstanceDao.deleteById(workflowInstanceId); |
| } |
| |
| private void deleteSubWorkflowInstanceIfNeeded(int workflowInstanceId) { |
| List<Integer> subWorkflowInstanceIds = processInstanceMapDao.querySubWorkflowInstanceIds(workflowInstanceId); |
| if (org.apache.commons.collections4.CollectionUtils.isEmpty(subWorkflowInstanceIds)) { |
| return; |
| } |
| for (Integer subWorkflowInstanceId : subWorkflowInstanceIds) { |
| deleteProcessInstanceById(subWorkflowInstanceId); |
| } |
| processInstanceMapDao.deleteByParentId(workflowInstanceId); |
| } |
| } |