org.zodiac.flowable.engine.service.impl.AbstractTenantFlowEngineServiceImpl Maven / Gradle / Ivy
package org.zodiac.flowable.engine.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.flowable.bpmn.converter.BpmnXMLConverter;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.Process;
import org.flowable.editor.language.json.converter.BpmnJsonConverter;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.impl.persistence.entity.ExecutionEntityImpl;
import org.flowable.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.flowable.engine.impl.persistence.entity.ProcessDefinitionEntityImpl;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.repository.ProcessDefinitionQuery;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.engine.runtime.ProcessInstanceQuery;
import org.flowable.engine.task.Comment;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zodiac.commons.io.FileObject;
import org.zodiac.commons.util.Colls;
import org.zodiac.commons.util.DateTimes;
import org.zodiac.commons.util.Exceptions;
import org.zodiac.commons.util.FileUtil;
import org.zodiac.commons.util.Func;
import org.zodiac.commons.util.Strings;
import org.zodiac.core.service.exception.ServiceException;
import org.zodiac.flowable.core.model.ProcessFlowModeEnum;
import org.zodiac.flowable.core.util.ProcessTaskUtil;
import org.zodiac.flowable.core.model.PlatformProcessFlow;
import org.zodiac.flowable.engine.constants.FlowEngineConstants;
import org.zodiac.flowable.engine.mapper.TenantFlowModelEntityMapper;
import org.zodiac.flowable.engine.model.FlowExecution;
import org.zodiac.flowable.engine.model.TenantFlowProcessModel;
import org.zodiac.flowable.engine.model.entity.TenantFlowModelEntity;
import org.zodiac.flowable.engine.service.TenantFlowEngineService;
import org.zodiac.flowable.engine.service.ProcessFlowStartUserSupplier;
import org.zodiac.flowable.engine.util.ProcessFlowCacheUtil;
import org.zodiac.flowable.engine.util.FlowCategoryNameSupplier;
import org.zodiac.mybatisplus.base.BaseEnhancedServiceImpl;
import org.zodiac.security.SecurityAuthOperations;
import org.zodiac.tenant.model.entity.TenantUserEntity;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
/**
* 工作流服务实现类。
*
*/
public abstract class AbstractTenantFlowEngineServiceImpl, E extends TenantFlowModelEntity, PE extends TenantFlowProcessModel>
extends BaseEnhancedServiceImpl implements TenantFlowEngineService {
private static final String ALREADY_IN_STATE = "already in state";
private static final BpmnJsonConverter BPMN_JSON_CONVERTER = new BpmnJsonConverter();
private static final BpmnXMLConverter BPMN_XML_CONVERTER = new BpmnXMLConverter();
protected Logger log = LoggerFactory.getLogger(getClass());
private final ObjectMapper objectMapper;
private final RepositoryService repositoryService;
private final RuntimeService runtimeService;
private final HistoryService historyService;
private final TaskService taskService;
private final SecurityAuthOperations securityAuthOperations;
public AbstractTenantFlowEngineServiceImpl(ObjectMapper objectMapper, RepositoryService repositoryService,
RuntimeService runtimeService, HistoryService historyService, TaskService taskService,
SecurityAuthOperations securityAuthOperations) {
this.objectMapper = objectMapper;
this.repositoryService = repositoryService;
this.runtimeService = runtimeService;
this.historyService = historyService;
this.taskService = taskService;
this.securityAuthOperations = securityAuthOperations;
}
@Override
public IPage selectFlowPage(IPage page, E flowModel) {
return page.setRecords(baseMapper.selectFlowPage(page, flowModel));
}
@Override
public IPage selectProcessPage(IPage page, String category, Integer mode,
FlowCategoryNameSupplier flowCategoryNameSupplier) {
ProcessDefinitionQuery processDefinitionQuery =
repositoryService.createProcessDefinitionQuery().latestVersion().orderByProcessDefinitionKey().asc();
if (mode == ProcessFlowModeEnum.COMMON.getMode()) {
/*通用流程*/
processDefinitionQuery.processDefinitionWithoutTenantId();
} else if (!securityAuthOperations.isAdministrator()) {
/*定制流程*/
processDefinitionQuery.processDefinitionTenantId(securityAuthOperations.getTenantId());
}
if (Strings.isNotEmpty(category)) {
processDefinitionQuery.processDefinitionCategory(category);
}
List processDefinitionList = processDefinitionQuery
.listPage(Func.toInt((page.getCurrent() - 1) * page.getSize()), Func.toInt(page.getSize()));
List flowProcessList = Colls.list();
processDefinitionList.forEach(processDefinition -> {
String deploymentId = processDefinition.getDeploymentId();
Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult();
PE flowProcess = obtainFlowProcessModel((ProcessDefinitionEntityImpl)processDefinition, flowCategoryNameSupplier);
flowProcess.setDeploymentTime(deployment.getDeploymentTime());
flowProcessList.add(flowProcess);
});
page.setTotal(processDefinitionQuery.count());
page.setRecords(flowProcessList);
return page;
}
@Override
public IPage selectFollowPage(IPage page, String processInstanceId,
String processDefinitionKey, ProcessFlowStartUserSupplier startUserSupplier, FlowCategoryNameSupplier flowCategoryNameSupplier) {
ProcessInstanceQuery processInstanceQuery = runtimeService.createProcessInstanceQuery();
if (Strings.isNotBlank(processInstanceId)) {
processInstanceQuery.processInstanceId(processInstanceId);
}
if (Strings.isNotBlank(processDefinitionKey)) {
processInstanceQuery.processDefinitionKey(processDefinitionKey);
}
List flowList = Colls.list();
List procInsList = processInstanceQuery
.listPage(Func.toInt((page.getCurrent() - 1) * page.getSize()), Func.toInt(page.getSize()));
procInsList.forEach(processInstance -> {
ExecutionEntityImpl execution = (ExecutionEntityImpl)processInstance;
FlowExecution flowExecution = new FlowExecution().setId(execution.getId()).setName(execution.getName())
.setStartUserId(execution.getStartUserId());
TenantUserEntity tenantUser = startUserSupplier.getStartUserByTaskUserId(execution.getStartUserId());
if (tenantUser != null) {
flowExecution.setStartUser(tenantUser.getName());
}
flowExecution.setStartTime(execution.getStartTime()).setExecutionId(execution.getId())
.setProcessInstanceId(execution.getProcessInstanceId())
.setProcessDefinitionId(execution.getProcessDefinitionId())
.setProcessDefinitionKey(execution.getProcessDefinitionKey())
.setSuspensionState(execution.getSuspensionState());
ProcessDefinition processDefinition =
ProcessFlowCacheUtil.getProcessDefinition(execution.getProcessDefinitionId());
flowExecution.setCategory(processDefinition.getCategory()).setCategoryName(
ProcessFlowCacheUtil.getCategoryName(processDefinition.getCategory(), flowCategoryNameSupplier));
flowList.add(flowExecution);
});
page.setTotal(processInstanceQuery.count());
page.setRecords(flowList);
return page;
}
@Override
public List historyFlowList(String processInstanceId, String startActivityId, String endActivityId,
ProcessFlowStartUserSupplier startUserSupplier) {
List flowList = Colls.linkedList();
List historicActivityInstanceList =
historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId)
.orderByHistoricActivityInstanceStartTime().asc().orderByHistoricActivityInstanceEndTime().asc().list();
boolean start = false;
Map activityMap = Colls.map(16);
for (int i = 0; i < historicActivityInstanceList.size(); i++) {
HistoricActivityInstance historicActivityInstance = historicActivityInstanceList.get(i);
/*过滤开始节点前的节点*/
if (Strings.isNotBlank(startActivityId)
&& startActivityId.equals(historicActivityInstance.getActivityId())) {
start = true;
}
if (Strings.isNotBlank(startActivityId) && !start) {
continue;
}
/*显示开始节点和结束节点,并且执行人不为空的任务*/
if (Strings.notBlank(historicActivityInstance.getAssignee())
|| FlowEngineConstants.START_EVENT.equals(historicActivityInstance.getActivityType())
|| FlowEngineConstants.END_EVENT.equals(historicActivityInstance.getActivityType())) {
/*给节点增加序号*/
Integer activityNum = activityMap.get(historicActivityInstance.getActivityId());
if (activityNum == null) {
activityMap.put(historicActivityInstance.getActivityId(), activityMap.size());
}
PlatformProcessFlow flow = new PlatformProcessFlow().setHistoryActivityId(historicActivityInstance.getActivityId())
.setHistoryActivityName(historicActivityInstance.getActivityName())
.setCreateTime(historicActivityInstance.getStartTime())
.setEndTime(historicActivityInstance.getEndTime());
String durationTime =
DateTimes.secondToTime(Func.toLong(historicActivityInstance.getDurationInMillis(), 0L) / 1000);
flow.setHistoryActivityDurationTime(durationTime);
/*获取流程发起人名称*/
if (FlowEngineConstants.START_EVENT.equals(historicActivityInstance.getActivityType())) {
List processInstanceList =
historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId)
.orderByProcessInstanceStartTime().asc().list();
if (processInstanceList.size() > 0) {
if (Strings.isNotBlank(processInstanceList.get(0).getStartUserId())) {
String taskUser = processInstanceList.get(0).getStartUserId();
// User user = UserCache.getUser(ProcessTaskUtil.getUserId(taskUser));
TenantUserEntity tenantUser = startUserSupplier.getStartUserByTaskUserId(
String.valueOf(ProcessTaskUtil.getUserId(taskUser)));
if (tenantUser != null) {
flow.setAssignee(historicActivityInstance.getAssignee());
flow.setAssigneeName(tenantUser.getName());
}
}
}
}
/*获取任务执行人名称*/
if (Strings.isNotBlank(historicActivityInstance.getAssignee())) {
// User user = UserCache.getUser(ProcessTaskUtil.getUserId(historicActivityInstance.getAssignee()));
TenantUserEntity tenantUser = startUserSupplier.getStartUserByTaskUserId(
String.valueOf(ProcessTaskUtil.getUserId(historicActivityInstance.getAssignee())));
if (tenantUser != null) {
flow.setAssignee(historicActivityInstance.getAssignee());
flow.setAssigneeName(tenantUser.getName());
}
}
/*获取意见评论内容*/
if (Strings.isNotBlank(historicActivityInstance.getTaskId())) {
List commentList = taskService.getTaskComments(historicActivityInstance.getTaskId());
if (commentList.size() > 0) {
flow.setComment(commentList.get(0).getFullMessage());
}
}
flowList.add(flow);
}
/*过滤结束节点后的节点*/
if (Strings.notBlank(endActivityId)
&& endActivityId.equals(historicActivityInstance.getActivityId())) {
boolean temp = false;
Integer activityNum = activityMap.get(historicActivityInstance.getActivityId());
/*该活动节点,后续节点是否在结束节点之前,在后续节点中是否存在*/
for (int j = i + 1; j < historicActivityInstanceList.size(); j++) {
HistoricActivityInstance hi = historicActivityInstanceList.get(j);
Integer activityNumA = activityMap.get(hi.getActivityId());
boolean numberTemp = activityNumA != null && activityNumA < activityNum;
boolean equalsTemp =
Strings.eqStr(hi.getActivityId(), historicActivityInstance.getActivityId());
if (numberTemp || equalsTemp) {
temp = true;
}
}
if (!temp) {
break;
}
}
}
return flowList;
}
@Override
public String changeState(String state, String processId) {
try {
if (state.equals(FlowEngineConstants.ACTIVE)) {
repositoryService.activateProcessDefinitionById(processId, true, null);
return Strings.format("激活ID为 [{}] 的流程成功", processId);
} else if (state.equals(FlowEngineConstants.SUSPEND)) {
repositoryService.suspendProcessDefinitionById(processId, true, null);
return Strings.format("挂起ID为 [{}] 的流程成功", processId);
} else {
return "暂无流程变更";
}
} catch (Exception e) {
if (e.getMessage().contains(ALREADY_IN_STATE)) {
return Strings.format("ID为 [{}] 的流程已是此状态,无需操作", processId);
}
return e.getMessage();
}
}
@Override
public boolean deleteDeployment(String deploymentIds) {
Func.toStrList(deploymentIds).forEach(deploymentId -> repositoryService.deleteDeployment(deploymentId, true));
return true;
}
@Override
public boolean deployUpload(List files, String category, List tenantIdList) {
files.forEach(file -> {
// try {
// String fileName = file.getOriginalFilename();
// InputStream fileInputStream = file.getInputStream();
// byte[] bytes = FileUtil.copyToByteArray(fileInputStream);
// if (Func.isNotEmpty(tenantIdList)) {
// tenantIdList.forEach(tenantId -> {
// Deployment deployment =
// repositoryService.createDeployment().addBytes(fileName, bytes).tenantId(tenantId).deploy();
// deploy(deployment, category);
// });
// } else {
// Deployment deployment = repositoryService.createDeployment().addBytes(fileName, bytes).deploy();
// deploy(deployment, category);
// }
// } catch (IOException e) {
// log.error(Exceptions.stackTrace(e));
// }
try {
String fileName = file.getFileName();
InputStream fileInputStream = file.getInputStream();
byte[] bytes = FileUtil.copyToByteArray(fileInputStream);
if (Func.isNotEmpty(tenantIdList)) {
tenantIdList.forEach(tenantId -> {
Deployment deployment =
repositoryService.createDeployment().addBytes(fileName, bytes).tenantId(tenantId).deploy();
deploy(deployment, category);
});
} else {
Deployment deployment = repositoryService.createDeployment().addBytes(fileName, bytes).deploy();
deploy(deployment, category);
}
} catch (IOException e) {
log.error(Exceptions.stackTrace(e));
}
});
return true;
}
@Override
public boolean deployModel(String modelId, String category, List tenantIdList) {
E model = this.getById(modelId);
if (model == null) {
throw new ServiceException("No model found with the given id: " + modelId);
}
byte[] bytes = getBpmnXML(model);
String processName = model.getName();
if (!Strings.endsWithIgnoreCase(processName, FlowEngineConstants.SUFFIX)) {
processName += FlowEngineConstants.SUFFIX;
}
String finalProcessName = processName;
if (Func.isNotEmpty(tenantIdList)) {
tenantIdList.forEach(tenantId -> {
Deployment deployment = repositoryService.createDeployment().addBytes(finalProcessName, bytes)
.name(model.getName()).key(model.getModelKey()).tenantId(tenantId).deploy();
deploy(deployment, category);
});
} else {
Deployment deployment = repositoryService.createDeployment().addBytes(finalProcessName, bytes)
.name(model.getName()).key(model.getModelKey()).deploy();
deploy(deployment, category);
}
return true;
}
@Override
public boolean deleteProcessInstance(String processInstanceId, String deleteReason) {
runtimeService.deleteProcessInstance(processInstanceId, deleteReason);
return true;
}
private boolean deploy(Deployment deployment, String category) {
log.debug("流程部署--------deploy: " + deployment + " 分类---------->" + category);
List list =
repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).list();
StringBuilder logBuilder = new StringBuilder(500);
List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy