Merge remote-tracking branch 'origin/REQ-2324' into REQ-2324

This commit is contained in:
yangqicheng 2024-05-11 17:48:44 +08:00
commit c2487725f4
15 changed files with 525 additions and 61 deletions

View File

@ -56,7 +56,14 @@ public interface BpmnConstants {
String FLOW_SERVER_VERSION_130 = "1.3.0";
String CONFIG_NOTICE = "noticeConfig";
String CONFIG_APPROVE = "approveConfig";
String TEMPLATE_NOTICE_MESSAGE_ID = "noticeMessageId";
String TEMPLATE_NOTICE_MESSAGE_CONFIG = "noticeMessageConfig";
String TEMPLATE_NOTICE_MESSAGE_EVENTS = "noticeMessageEvents";
String TEMPLATE_NOTICE_MESSAGE_DESTINATION = "noticeMessageDestination";
String TEMPLATE_NOTICE_MESSAGE_DESTINATION_INITIATOR = "initiator";
String TEMPLATE_NOTICE_MESSAGE_DESTINATION_HISTORIES = "histories";
String TEMPLATE_NOTICE_MESSAGE_DESTINATION_ROLES = "roles";
String TEMPLATE_NOTICE_MESSAGE_DESTINATION_POSITIONS = "positions";
String TEMPLATE_NOTICE_MESSAGE_DESTINATION_ASSIGNERS = "assigners";
String TEMPLATE_PENDING_MESSAGE_ID = "pendingMessageId";
String TEMPLATE_CARBON_COPY_MESSAGE_ID = "carbonCopyMessageId";
String TEMPLATE_SMS_MESSAGE_ID = "smsMessageId";

View File

@ -1,6 +1,6 @@
package cn.axzo.workflow.common.enums;
import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_NOTICE_MESSAGE_ID;
import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_NOTICE_MESSAGE_CONFIG;
import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_PENDING_MESSAGE_ID;
import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_SMS_MESSAGE_ID;
@ -12,7 +12,7 @@ import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_SMS_MESSAG
*/
public enum BpmnNoticeEnum {
notice("notice", TEMPLATE_NOTICE_MESSAGE_ID, "通知模板"),
notice("notice", TEMPLATE_NOTICE_MESSAGE_CONFIG, "通知模板"),
pending("pending", TEMPLATE_PENDING_MESSAGE_ID, "待办模板"),
sms("sms", TEMPLATE_SMS_MESSAGE_ID, "短信模板"),
;

View File

@ -20,7 +20,9 @@ public enum WorkspaceType {
ENT(1, "企业"),
PROJECT(2, "项目"),
GOVERNMENT(3, "政务监管平台"),
OMS(6, "oms工作台");
OMS(6, "oms工作台"),
UN_KNOW(0, "未知"),
;
private Integer code;
private String desc;

View File

@ -23,18 +23,10 @@ import java.util.List;
public class BpmnNoticeProperty implements Serializable {
/**
* 通知消息模板 ID
* 通知的消息模板,该属性目前是由后端进行配置,前端暂可不关心
*/
@ApiModelProperty(value = "通知消息模板 ID")
// @NotBlank(message = "通知消息模板 ID 不能为空")
@ApiModelProperty(value = "通知的消息模板", hidden = true)
private String noticeMessageId;
/**
* 用于前端回显数据, 服务端不解析
*/
@ApiModelProperty(value = "用于前端回显数据, 服务端不解析")
private String viewJson;
/**
* 是否发送消息通知
*/

View File

@ -22,5 +22,5 @@ public class BpmnNoticeReceiver {
* 接收人内容发起人历史审批人不设置该值
*/
@ApiModelProperty(value = "接收人内容,发起人,历史审批人不设置该值")
private String value;
private String viewJson;
}

View File

@ -17,6 +17,7 @@ public enum FlowableEngineRespCode implements IModuleRespCode {
ENGINE_USER_TASK_CALC_ERROR("002", "计算用户任务节点【nodeId:{}】的审批人发生异常, 配置类型:【{}】, 异常信息:【{}】"),
ENGINE_USER_TASK_TYPE_NOT_SUPPORT("003", "审批指定方式暂不支持"),
ENGINE_USER_TASK_PARAM_ERROR("004", "构建后的查询审批人入参为空. 任务节点【nodeId:{}】, 该节点选择的\"审批人所在范围\"是:【{}】"),
ENGINE_NOTICE_CUSTOM_FLOW_ELEMENT_ERROR("005", "查询通知目标用户前参数发生异常,未获取到 WorkspaceType"),
;
private String code;

View File

@ -94,7 +94,14 @@ import static cn.axzo.workflow.common.constant.BpmnConstants.FLOW_SERVER_VERSION
import static cn.axzo.workflow.common.constant.BpmnConstants.SEQUENCE_FLOW_ID;
import static cn.axzo.workflow.common.constant.BpmnConstants.START_EVENT_ID;
import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_CARBON_COPY_MESSAGE_ID;
import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_NOTICE_MESSAGE_ID;
import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_NOTICE_MESSAGE_CONFIG;
import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_NOTICE_MESSAGE_DESTINATION;
import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_NOTICE_MESSAGE_DESTINATION_ASSIGNERS;
import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_NOTICE_MESSAGE_DESTINATION_HISTORIES;
import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_NOTICE_MESSAGE_DESTINATION_INITIATOR;
import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_NOTICE_MESSAGE_DESTINATION_POSITIONS;
import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_NOTICE_MESSAGE_DESTINATION_ROLES;
import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_NOTICE_MESSAGE_EVENTS;
import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_PENDING_MESSAGE_ID;
import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_SMS_MESSAGE_ID;
import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_CONDITION;
@ -345,15 +352,88 @@ public final class BpmnJsonConverterUtil {
noticeConfigElement.setName(CONFIG_NOTICE);
// 通知消息模板配置
if (Objects.nonNull(noticeConf.getNotice()) && Objects.nonNull(noticeConf.getNotice().getNoticeMessageId())) {
if (Objects.nonNull(noticeConf.getNotice()) && noticeConf.getNotice().getSendMessage()) {
ExtensionElement noticeMessage = new ExtensionElement();
noticeMessage.setName(TEMPLATE_NOTICE_MESSAGE_ID);
noticeMessage.setName(TEMPLATE_NOTICE_MESSAGE_CONFIG);
ExtensionAttribute noticeMessageAttribute = new ExtensionAttribute();
noticeMessageAttribute.setName(ELEMENT_ATTRIBUTE_VALUE);
noticeMessageAttribute.setValue(noticeConf.getNotice().getNoticeMessageId());
noticeMessageAttribute.setName(ELEMENT_ATTRIBUTE_CHECKED);
noticeMessageAttribute.setValue(String.valueOf(noticeConf.getNotice().getSendMessage()));
noticeMessage.addAttribute(noticeMessageAttribute);
noticeMessage.setElementText(StringUtils.hasText(noticeConf.getNotice().getViewJson()) ?
noticeConf.getNotice().getViewJson() : "");
ExtensionElement noticeEvents = new ExtensionElement();
noticeEvents.setName(TEMPLATE_NOTICE_MESSAGE_EVENTS);
noticeEvents.setElementText(JSON.toJSONString(noticeConf.getNotice().getTriggerEvents()));
noticeMessage.addChildElement(noticeEvents);
ExtensionElement noticeToObject = new ExtensionElement();
noticeToObject.setName(TEMPLATE_NOTICE_MESSAGE_DESTINATION);
if (Objects.nonNull(noticeConf.getNotice().getInitiator()) && noticeConf.getNotice().getInitiator().getSelected()) {
ExtensionElement initiator = new ExtensionElement();
initiator.setName(TEMPLATE_NOTICE_MESSAGE_DESTINATION_INITIATOR);
ExtensionAttribute initiatorAttribute = new ExtensionAttribute();
initiatorAttribute.setName(ELEMENT_ATTRIBUTE_CHECKED);
initiatorAttribute.setValue(String.valueOf(noticeConf.getNotice().getInitiator().getSelected()));
initiator.addAttribute(initiatorAttribute);
if (StringUtils.hasText(noticeConf.getNotice().getInitiator().getViewJson())) {
initiator.setElementText(noticeConf.getNotice().getInitiator().getViewJson());
}
noticeToObject.addChildElement(initiator);
}
if (Objects.nonNull(noticeConf.getNotice().getHistories()) && noticeConf.getNotice().getHistories().getSelected()) {
ExtensionElement histories = new ExtensionElement();
histories.setName(TEMPLATE_NOTICE_MESSAGE_DESTINATION_HISTORIES);
ExtensionAttribute historiesAttribute = new ExtensionAttribute();
historiesAttribute.setName(ELEMENT_ATTRIBUTE_CHECKED);
historiesAttribute.setValue(String.valueOf(noticeConf.getNotice().getHistories().getSelected()));
histories.addAttribute(historiesAttribute);
if (StringUtils.hasText(noticeConf.getNotice().getHistories().getViewJson())) {
histories.setElementText(noticeConf.getNotice().getHistories().getViewJson());
}
noticeToObject.addChildElement(histories);
}
if (Objects.nonNull(noticeConf.getNotice().getRoles()) && noticeConf.getNotice().getRoles().getSelected()) {
ExtensionElement roles = new ExtensionElement();
roles.setName(TEMPLATE_NOTICE_MESSAGE_DESTINATION_ROLES);
ExtensionAttribute rolesAttribute = new ExtensionAttribute();
rolesAttribute.setName(ELEMENT_ATTRIBUTE_CHECKED);
rolesAttribute.setValue(String.valueOf(noticeConf.getNotice().getRoles().getSelected()));
roles.addAttribute(rolesAttribute);
if (StringUtils.hasText(noticeConf.getNotice().getRoles().getViewJson())) {
roles.setElementText(noticeConf.getNotice().getRoles().getViewJson());
}
noticeToObject.addChildElement(roles);
}
if (Objects.nonNull(noticeConf.getNotice().getPositions())) {
ExtensionElement positions = new ExtensionElement();
positions.setName(TEMPLATE_NOTICE_MESSAGE_DESTINATION_POSITIONS);
ExtensionAttribute positionsAttribute = new ExtensionAttribute();
positionsAttribute.setName(ELEMENT_ATTRIBUTE_CHECKED);
positionsAttribute.setValue(String.valueOf(noticeConf.getNotice().getPositions().getSelected()));
positions.addAttribute(positionsAttribute);
if (StringUtils.hasText(noticeConf.getNotice().getPositions().getViewJson())) {
positions.setElementText(noticeConf.getNotice().getPositions().getViewJson());
}
noticeToObject.addChildElement(positions);
}
if (Objects.nonNull(noticeConf.getNotice().getAssigners())) {
ExtensionElement assigners = new ExtensionElement();
assigners.setName(TEMPLATE_NOTICE_MESSAGE_DESTINATION_ASSIGNERS);
ExtensionAttribute assignersAttribute = new ExtensionAttribute();
assignersAttribute.setName(ELEMENT_ATTRIBUTE_CHECKED);
assignersAttribute.setValue(String.valueOf(noticeConf.getNotice().getAssigners().getSelected()));
assigners.addAttribute(assignersAttribute);
if (StringUtils.hasText(noticeConf.getNotice().getAssigners().getViewJson())) {
assigners.setElementText(noticeConf.getNotice().getAssigners().getViewJson());
}
noticeToObject.addChildElement(assigners);
}
noticeMessage.addChildElement(noticeToObject);
noticeConfigElement.addChildElement(noticeMessage);
}
@ -445,11 +525,11 @@ public final class BpmnJsonConverterUtil {
/**
* 创建对应类型节点并保存在 bpmnModel
*
* @param preNodeIds 上级节点的 Id 结合,用于链接当前创建节点
* @param bpmnJsonNode 前端传入节点数据,不是全数据,而是对应层级
* @param mainProcess Process 对象
* @param bpmnModel 最终的 BPMN model
* @param defaultConditionConnectNode 嵌套网关行为下,缓存的当前网关下的 child,如果当前层级下没有,则是上级网关的 child.
* @param preNodeIds 上级节点的 Id 结合,用于链接当前创建节点
* @param bpmnJsonNode 前端传入节点数据,不是全数据,而是对应层级
* @param mainProcess Process 对象
* @param bpmnModel 最终的 BPMN model
* @param defaultConditionConnectNode 嵌套网关行为下,缓存的当前网关下的 child,如果当前层级下没有,则是上级网关的 child.
* @return 创建的节点的 ID
*/
private static List<String> create(BpmnJsonNode bpmnJsonNode, Process mainProcess,
@ -664,8 +744,10 @@ public final class BpmnJsonConverterUtil {
model.getJsonModel().getButtonConf(), model.getJsonModel().getFieldConf(),
"1.3.1-SNAPSHOT");
getNoticeConfig(bpmnModel.getMainProcess());
BpmnJsonModel bpmnJsonModel = convertToJson(bpmnModel);
// ServiceTask serviceTask = (ServiceTask) bpmnModel.getFlowElement("node_946990365785");
// Optional<List<BpmnCarbonCopyConf>> carbonCopyConfigs = BpmnMetaParserHelper.getCarbonCopyConfigs
// (serviceTask);

View File

@ -1,18 +1,88 @@
package cn.axzo.workflow.core.common.utils;
import cn.axzo.workflow.common.enums.*;
import cn.axzo.workflow.common.enums.ApprovalMethodEnum;
import cn.axzo.workflow.common.enums.ApproverEmptyHandleTypeEnum;
import cn.axzo.workflow.common.enums.ApproverScopeEnum;
import cn.axzo.workflow.common.enums.ApproverSpecifyEnum;
import cn.axzo.workflow.common.enums.BpmnFlowNodeType;
import cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum;
import cn.axzo.workflow.common.enums.CarbonCopyObjectType;
import cn.axzo.workflow.common.model.request.BpmnApproveConf;
import cn.axzo.workflow.common.model.request.bpmn.*;
import cn.axzo.workflow.common.model.request.bpmn.BpmnButtonConf;
import cn.axzo.workflow.common.model.request.bpmn.BpmnButtonMetaInfo;
import cn.axzo.workflow.common.model.request.bpmn.BpmnCarbonCopyConf;
import cn.axzo.workflow.common.model.request.bpmn.BpmnCarbonCopyProperty;
import cn.axzo.workflow.common.model.request.bpmn.BpmnFieldConf;
import cn.axzo.workflow.common.model.request.bpmn.BpmnFieldOptionConf;
import cn.axzo.workflow.common.model.request.bpmn.BpmnNoticeConf;
import cn.axzo.workflow.common.model.request.bpmn.BpmnNoticeProperty;
import cn.axzo.workflow.common.model.request.bpmn.BpmnNoticeReceiver;
import cn.axzo.workflow.common.model.request.bpmn.BpmnPendingProperty;
import cn.axzo.workflow.common.model.request.bpmn.BpmnSmsProperty;
import com.alibaba.fastjson.JSON;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.ExtensionElement;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.*;
import org.flowable.bpmn.model.ReceiveTask;
import org.flowable.bpmn.model.ServiceTask;
import org.flowable.bpmn.model.Task;
import org.flowable.bpmn.model.UserTask;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.impl.util.ProcessDefinitionUtil;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import static cn.axzo.workflow.common.constant.BpmnConstants.*;
import static cn.axzo.workflow.common.constant.BpmnConstants.APPROVE_SUPPORT_BATCH_OPERATION;
import static cn.axzo.workflow.common.constant.BpmnConstants.APPROVE_USER_AGREE_SIGNATURE;
import static cn.axzo.workflow.common.constant.BpmnConstants.CONFIG_APPROVAL_METHOD;
import static cn.axzo.workflow.common.constant.BpmnConstants.CONFIG_APPROVE;
import static cn.axzo.workflow.common.constant.BpmnConstants.CONFIG_APPROVER_EMPTY_HANDLE_TYPE;
import static cn.axzo.workflow.common.constant.BpmnConstants.CONFIG_APPROVER_SCOPE;
import static cn.axzo.workflow.common.constant.BpmnConstants.CONFIG_APPROVER_SPECIFY;
import static cn.axzo.workflow.common.constant.BpmnConstants.CONFIG_BUTTON;
import static cn.axzo.workflow.common.constant.BpmnConstants.CONFIG_BUTTON_META;
import static cn.axzo.workflow.common.constant.BpmnConstants.CONFIG_BUTTON_TYPE_CARBON_COPY;
import static cn.axzo.workflow.common.constant.BpmnConstants.CONFIG_BUTTON_TYPE_CURRENT;
import static cn.axzo.workflow.common.constant.BpmnConstants.CONFIG_BUTTON_TYPE_HISTORY;
import static cn.axzo.workflow.common.constant.BpmnConstants.CONFIG_BUTTON_TYPE_INITIATOR;
import static cn.axzo.workflow.common.constant.BpmnConstants.CONFIG_CARBON_COPIES;
import static cn.axzo.workflow.common.constant.BpmnConstants.CONFIG_CARBON_COPY;
import static cn.axzo.workflow.common.constant.BpmnConstants.CONFIG_CARBON_COPY_OBJECT;
import static cn.axzo.workflow.common.constant.BpmnConstants.CONFIG_CARBON_COPY_SPECIFY;
import static cn.axzo.workflow.common.constant.BpmnConstants.CONFIG_FIELD;
import static cn.axzo.workflow.common.constant.BpmnConstants.CONFIG_FIELD_META;
import static cn.axzo.workflow.common.constant.BpmnConstants.CONFIG_FIELD_OPTION;
import static cn.axzo.workflow.common.constant.BpmnConstants.CONFIG_NODE_TYPE;
import static cn.axzo.workflow.common.constant.BpmnConstants.CONFIG_NOTICE;
import static cn.axzo.workflow.common.constant.BpmnConstants.ELEMENT_ATTRIBUTE_CHECKED;
import static cn.axzo.workflow.common.constant.BpmnConstants.ELEMENT_ATTRIBUTE_CODE;
import static cn.axzo.workflow.common.constant.BpmnConstants.ELEMENT_ATTRIBUTE_DISABLED;
import static cn.axzo.workflow.common.constant.BpmnConstants.ELEMENT_ATTRIBUTE_KEY;
import static cn.axzo.workflow.common.constant.BpmnConstants.ELEMENT_ATTRIBUTE_NAME;
import static cn.axzo.workflow.common.constant.BpmnConstants.ELEMENT_ATTRIBUTE_ORDER;
import static cn.axzo.workflow.common.constant.BpmnConstants.ELEMENT_ATTRIBUTE_TYPE;
import static cn.axzo.workflow.common.constant.BpmnConstants.ELEMENT_ATTRIBUTE_VALUE;
import static cn.axzo.workflow.common.constant.BpmnConstants.FLOW_SERVER_VERSION;
import static cn.axzo.workflow.common.constant.BpmnConstants.SUPPORT_BATCH_OPERATION_DEFAULT_VALUE;
import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_CARBON_COPY_MESSAGE_ID;
import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_NOTICE_MESSAGE_CONFIG;
import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_NOTICE_MESSAGE_DESTINATION;
import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_NOTICE_MESSAGE_DESTINATION_ASSIGNERS;
import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_NOTICE_MESSAGE_DESTINATION_HISTORIES;
import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_NOTICE_MESSAGE_DESTINATION_INITIATOR;
import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_NOTICE_MESSAGE_DESTINATION_POSITIONS;
import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_NOTICE_MESSAGE_DESTINATION_ROLES;
import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_NOTICE_MESSAGE_EVENTS;
import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_PENDING_MESSAGE_ID;
import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_SMS_MESSAGE_ID;
import static cn.axzo.workflow.common.constant.BpmnConstants.USER_AGREE_SIGNATURE_DEFAULT_VALUE;
/**
* 协助解析 BPMN 文件中的自定义扩展字段和属性
@ -62,10 +132,49 @@ public final class BpmnMetaParserHelper {
}
BpmnNoticeConf conf = new BpmnNoticeConf();
elements.get(0).getChildElements().forEach((k, v) -> {
if (TEMPLATE_NOTICE_MESSAGE_ID.equals(k)) {
if (TEMPLATE_NOTICE_MESSAGE_CONFIG.equals(k)) {
BpmnNoticeProperty notice = new BpmnNoticeProperty();
notice.setNoticeMessageId(v.get(0).getAttributeValue(null, ELEMENT_ATTRIBUTE_VALUE));
notice.setViewJson(v.get(0).getElementText());
notice.setSendMessage(Boolean.valueOf(v.get(0).getAttributeValue(null, ELEMENT_ATTRIBUTE_CHECKED)));
String events = v.get(0).getChildElements().getOrDefault(TEMPLATE_NOTICE_MESSAGE_EVENTS, Collections.emptyList())
.get(0).getElementText();
List<BpmnProcessInstanceResultEnum> resultEnums = JSON.parseArray(events, BpmnProcessInstanceResultEnum.class);
notice.setTriggerEvents(resultEnums);
v.get(0).getChildElements().getOrDefault(TEMPLATE_NOTICE_MESSAGE_DESTINATION, Collections.emptyList()).get(0).getChildElements()
.forEach((a, b) -> {
if (Objects.equals(a, TEMPLATE_NOTICE_MESSAGE_DESTINATION_INITIATOR)) {
BpmnNoticeReceiver initiator = new BpmnNoticeReceiver();
initiator.setSelected(Boolean.valueOf(b.get(0).getAttributeValue(null, ELEMENT_ATTRIBUTE_CHECKED)));
initiator.setViewJson(b.get(0).getElementText());
notice.setInitiator(initiator);
}
if (Objects.equals(a, TEMPLATE_NOTICE_MESSAGE_DESTINATION_HISTORIES)) {
BpmnNoticeReceiver histories = new BpmnNoticeReceiver();
histories.setSelected(Boolean.valueOf(b.get(0).getAttributeValue(null, ELEMENT_ATTRIBUTE_CHECKED)));
histories.setViewJson(b.get(0).getElementText());
notice.setHistories(histories);
}
if (Objects.equals(a, TEMPLATE_NOTICE_MESSAGE_DESTINATION_ROLES)) {
BpmnNoticeReceiver roles = new BpmnNoticeReceiver();
roles.setSelected(Boolean.valueOf(b.get(0).getAttributeValue(null, ELEMENT_ATTRIBUTE_CHECKED)));
roles.setViewJson(b.get(0).getElementText());
notice.setRoles(roles);
}
if (Objects.equals(a, TEMPLATE_NOTICE_MESSAGE_DESTINATION_POSITIONS)) {
BpmnNoticeReceiver positions = new BpmnNoticeReceiver();
positions.setSelected(Boolean.valueOf(b.get(0).getAttributeValue(null, ELEMENT_ATTRIBUTE_CHECKED)));
positions.setViewJson(b.get(0).getElementText());
notice.setPositions(positions);
}
if (Objects.equals(a, TEMPLATE_NOTICE_MESSAGE_DESTINATION_ASSIGNERS)) {
BpmnNoticeReceiver assigners = new BpmnNoticeReceiver();
assigners.setSelected(Boolean.valueOf(b.get(0).getAttributeValue(null, ELEMENT_ATTRIBUTE_CHECKED)));
assigners.setViewJson(b.get(0).getElementText());
notice.setAssigners(assigners);
}
});
conf.setNotice(notice);
} else if (TEMPLATE_CARBON_COPY_MESSAGE_ID.equals(k)) {
BpmnCarbonCopyProperty carbonCopy = new BpmnCarbonCopyProperty();

View File

@ -91,11 +91,11 @@ public class CustomCarbonCopyUserSelectorCmd implements Command<List<BpmnTaskDel
ProcessEngineConfigurationImpl processEngineConfiguration =
CommandContextUtil.getProcessEngineConfiguration(commandContext);
RuntimeService runtimeService = processEngineConfiguration.getRuntimeService();
List<Execution> list = new ArrayList<>();
List<Execution> executions = new ArrayList<>();
if (Objects.isNull(execution)) {
list.addAll(runtimeService.createExecutionQuery().processInstanceId(processInstanceId).list());
executions.addAll(runtimeService.createExecutionQuery().processInstanceId(processInstanceId).list());
} else {
list.add((Execution) execution);
executions.add((Execution) execution);
}
List<BpmnTaskDelegateAssigner> assigners = new ArrayList<>();
carbons.forEach(carbon -> {
@ -113,11 +113,11 @@ public class CustomCarbonCopyUserSelectorCmd implements Command<List<BpmnTaskDel
property.setSimpleValue(carbon.getSpecifyValue());
serviceTask.setCustomProperties(Lists.newArrayList(property));
assigners.addAll(engineExecutionStartListener.approverSelect(carbonCopyObjectType.getSimpleType(),
serviceTask, (DelegateExecution) list.get(0), false));
serviceTask, (DelegateExecution) executions.get(0), false));
break;
case approver_relation:
assigners.addAll(getApproverRelationUser(carbon, carbonCopyObjectType,
(DelegateExecution) list.get(0), processEngineConfiguration, processInstanceId));
(DelegateExecution) executions.get(0), processEngineConfiguration, processInstanceId));
break;
case specify_user:
case government_specify_user:

View File

@ -0,0 +1,174 @@
package cn.axzo.workflow.core.engine.cmd;
import cn.axzo.workflow.common.enums.ApproverSpecifyEnum;
import cn.axzo.workflow.common.model.request.bpmn.BpmnNoticeProperty;
import cn.axzo.workflow.common.model.request.bpmn.BpmnNoticeReceiver;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnHistoricTaskInstanceVO;
import cn.axzo.workflow.core.engine.listener.EngineExecutionStartListener;
import cn.axzo.workflow.core.engine.model.NoticeFlowElement;
import cn.axzo.workflow.core.service.converter.BpmnHistoricTaskInstanceConverter;
import com.alibaba.fastjson.JSON;
import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.engine.runtime.Execution;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.variable.api.history.HistoricVariableInstance;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_TASK_RELATION_ASSIGNEE_INFO;
import static cn.axzo.workflow.common.constant.BpmnConstants.NO_ASSIGNEE;
import static cn.axzo.workflow.common.constant.BpmnConstants.OLD_INTERNAL_TASK_RELATION_ASSIGNEE_INFO_SNAPSHOT;
import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.removeDuplicateByPersonId;
/**
* 消息通知,根据模型全局配置查找通知用户
*
* @author wangli
* @since 2024/5/11 09:42
*/
public class CustomNoticeDestinationUserSelectorCmd implements Command<List<BpmnTaskDelegateAssigner>>, Serializable {
private static final long serialVersionUID = 1L;
private final EngineExecutionStartListener engineExecutionStartListener;
private final BpmnHistoricTaskInstanceConverter historicTaskInstanceConverter;
private final String serviceVersion;
/**
* 流程模型对应的工作台类型, 这个值在创建流程时,已经放入到了流程变量中
*/
private final Integer workspaceType;
private final BpmnNoticeProperty noticeProperty;
private final String processInstanceId;
private final BpmnTaskDelegateAssigner initiator;
public CustomNoticeDestinationUserSelectorCmd(EngineExecutionStartListener engineExecutionStartListener, BpmnHistoricTaskInstanceConverter historicTaskInstanceConverter, String serviceVersion, Integer workspaceType, BpmnNoticeProperty noticeProperty, String processInstanceId, BpmnTaskDelegateAssigner initiator) {
this.engineExecutionStartListener = engineExecutionStartListener;
this.historicTaskInstanceConverter = historicTaskInstanceConverter;
this.serviceVersion = serviceVersion;
this.workspaceType = workspaceType;
this.noticeProperty = noticeProperty;
this.processInstanceId = processInstanceId;
this.initiator = initiator;
}
@Override
public List<BpmnTaskDelegateAssigner> execute(CommandContext commandContext) {
if (!noticeProperty.getSendMessage()) {
return Collections.emptyList();
}
ProcessEngineConfigurationImpl processEngineConfiguration =
CommandContextUtil.getProcessEngineConfiguration(commandContext);
List<BpmnTaskDelegateAssigner> assigners = new ArrayList<>();
checkAndBuildInitiator(assigners);
checkAndBuildHistories(assigners, processEngineConfiguration);
checkAndBuildRoles(assigners, processEngineConfiguration);
checkAndBuildPositions(assigners, processEngineConfiguration);
checkAndBuildAssigners(assigners);
return removeDuplicateByPersonId(assigners);
}
private void checkAndBuildAssigners(List<BpmnTaskDelegateAssigner> assigners) {
if (Objects.isNull(noticeProperty.getAssigners()) || !noticeProperty.getAssigners().getSelected()) {
return;
}
assigners.addAll(JSON.parseArray(noticeProperty.getAssigners().getViewJson(), BpmnTaskDelegateAssigner.class));
}
private void checkAndBuildPositions(List<BpmnTaskDelegateAssigner> assigners, ProcessEngineConfigurationImpl processEngineConfiguration) {
if (Objects.isNull(noticeProperty.getPositions()) || !noticeProperty.getPositions().getSelected()) {
return;
}
RuntimeService runtimeService = processEngineConfiguration.getRuntimeService();
List<Execution> executions = runtimeService.createExecutionQuery().processInstanceId(processInstanceId).list();
assigners.addAll(engineExecutionStartListener.approverSelect(ApproverSpecifyEnum.position.getType(),
buildCustomFlowElement(ApproverSpecifyEnum.position, noticeProperty.getPositions()),
(DelegateExecution) executions.get(0), false));
}
private void checkAndBuildRoles(List<BpmnTaskDelegateAssigner> assigners, ProcessEngineConfigurationImpl processEngineConfiguration) {
if (Objects.isNull(noticeProperty.getRoles()) || !noticeProperty.getRoles().getSelected()) {
return;
}
RuntimeService runtimeService = processEngineConfiguration.getRuntimeService();
List<Execution> executions = runtimeService.createExecutionQuery().processInstanceId(processInstanceId).list();
assigners.addAll(engineExecutionStartListener.approverSelect(ApproverSpecifyEnum.role.getType(),
buildCustomFlowElement(ApproverSpecifyEnum.role, noticeProperty.getRoles()),
(DelegateExecution) executions.get(0), false));
}
private NoticeFlowElement buildCustomFlowElement(ApproverSpecifyEnum specifyEnum, BpmnNoticeReceiver receiver) {
NoticeFlowElement noticeFlowElement = new NoticeFlowElement();
noticeFlowElement.setId("noticeFlowElement");
noticeFlowElement.setName("消息推送模拟流程元素");
noticeFlowElement.setWorkspaceType(workspaceType);
noticeFlowElement.setSpecifyEnum(specifyEnum);
noticeFlowElement.setCustomValues(receiver.getViewJson());
return noticeFlowElement;
}
private void checkAndBuildHistories(List<BpmnTaskDelegateAssigner> assigners, ProcessEngineConfigurationImpl processEngineConfiguration) {
if (Objects.isNull(noticeProperty.getHistories()) || !noticeProperty.getHistories().getSelected()) {
return;
}
HistoryService historyService = processEngineConfiguration.getHistoryService();
// 历史真正有同意和驳回动作的人
List<HistoricTaskInstance> taskInstances = historyService.createHistoricTaskInstanceQuery()
.processInstanceId(processInstanceId)
// .includeProcessVariables()
.orderByHistoricTaskInstanceStartTime()
.desc().list();
List<BpmnHistoricTaskInstanceVO> vos =
historicTaskInstanceConverter.toVosSkipSystemOperation(taskInstances,
serviceVersion);
Map<String, HistoricVariableInstance> variableInstanceMap =
// 不能使用框架提供的历史变量 API 查询, BUG
historyService.createNativeHistoricVariableInstanceQuery()
.sql("select * from ACT_HI_VARINST t where t.proc_inst_id_= #{processInstanceId}")
.parameter("processInstanceId", processInstanceId)
.list().stream()
.collect(Collectors.toMap(HistoricVariableInstance::getVariableName,
Function.identity(), (s, t) -> s));
vos.forEach(vo -> {
HistoricVariableInstance assginerSnapshot =
variableInstanceMap.getOrDefault(INTERNAL_TASK_RELATION_ASSIGNEE_INFO + vo.getTaskId(),
null);
if (Objects.isNull(assginerSnapshot)) {
assginerSnapshot =
variableInstanceMap.getOrDefault(OLD_INTERNAL_TASK_RELATION_ASSIGNEE_INFO_SNAPSHOT + vo.getTaskId(), null);
}
if (Objects.nonNull(assginerSnapshot)) {
BpmnTaskDelegateAssigner assigner = BpmnTaskDelegateAssigner.toObjectCompatible(assginerSnapshot.getValue());
if (Objects.nonNull(assigner) && !Objects.equals(assigner.buildAssigneeId(), NO_ASSIGNEE)) {
assigners.add(assigner);
}
}
});
}
/**
* 判断通知对象是否勾选发起人,如勾选则将发起人加入发送目标对象集合中
*
* @param assigners
*/
private void checkAndBuildInitiator(List<BpmnTaskDelegateAssigner> assigners) {
if (Objects.isNull(noticeProperty.getInitiator()) || !noticeProperty.getInitiator().getSelected()) {
return;
}
assigners.add(initiator);
}
}

View File

@ -1,17 +1,18 @@
package cn.axzo.workflow.core.engine.listener;
import cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum;
import cn.axzo.workflow.common.model.request.bpmn.BpmnNoticeConf;
import cn.axzo.workflow.common.enums.WorkspaceType;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
import cn.axzo.workflow.core.common.context.ProcessOperationContext;
import cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper;
import cn.axzo.workflow.core.engine.cmd.CustomNoticeDestinationUserSelectorCmd;
import cn.axzo.workflow.core.engine.event.MessagePushEventBuilder;
import cn.axzo.workflow.core.engine.event.MessagePushEventImpl;
import cn.axzo.workflow.core.engine.event.MessagePushEventType;
import cn.axzo.workflow.core.listener.BpmnProcessEventListener;
import cn.axzo.workflow.core.service.converter.BpmnHistoricTaskInstanceConverter;
import cn.hutool.json.JSONUtil;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEvent;
@ -34,7 +35,6 @@ import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_DELETE_PROCESS_FLAG;
@ -42,7 +42,9 @@ import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_INITIATOR;
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_PROCESS_TYPE_ABORT;
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_PROCESS_TYPE_CANCEL;
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_PROCESS_TYPE_REJECT;
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_PROCESS_WORKSPACE_TYPE;
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.ABORTED;
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.APPROVED;
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.CANCELLED;
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.DELETED;
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.REJECTED;
@ -55,7 +57,12 @@ import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.REJECT
public class EngineProcessInstanceEventListener extends AbstractFlowableEngineEventListener {
@Resource
ObjectProvider<List<BpmnProcessEventListener>> processEventListeners;
@Resource
private EngineExecutionStartListener engineExecutionStartListener;
@Resource
private BpmnHistoricTaskInstanceConverter historicTaskInstanceConverter;
@Resource
private String serviceVersion;
@Resource
@Lazy
private RuntimeService runtimeService;
@ -86,11 +93,10 @@ public class EngineProcessInstanceEventListener extends AbstractFlowableEngineEv
@Override
protected void processCompleted(FlowableEngineEntityEvent event) {
runtimeService.updateBusinessStatus(event.getProcessInstanceId(),
BpmnProcessInstanceResultEnum.APPROVED.getStatus());
runtimeService.updateBusinessStatus(event.getProcessInstanceId(), APPROVED.getStatus());
getOrderedListeners().forEach(i -> i.onCompleted(event));
// 推送站内信
pushNotice(event);
pushNotice(event, APPROVED);
}
@Override
@ -129,10 +135,10 @@ public class EngineProcessInstanceEventListener extends AbstractFlowableEngineEv
}
});
// 推送站内信
pushNotice(event);
pushNotice(event, resultEnum);
}
private void pushNotice(FlowableEngineEvent event) {
private void pushNotice(FlowableEngineEvent event, BpmnProcessInstanceResultEnum resultEnum) {
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
.processInstanceId(event.getProcessInstanceId())
.includeProcessVariables().singleResult();
@ -143,13 +149,20 @@ public class EngineProcessInstanceEventListener extends AbstractFlowableEngineEv
}
ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration();
FlowableEventDispatcher eventDispatcher = processEngineConfiguration.getEventDispatcher();
Optional<BpmnNoticeConf> noticeConfig =
BpmnMetaParserHelper.getNoticeConfig(ProcessDefinitionUtil.getProcess(processInstance.getProcessDefinitionId()));
MessagePushEventImpl messagePushEvent = MessagePushEventBuilder.createEvent(MessagePushEventType.NOTICE,
Lists.newArrayList(assigner), noticeConfig.orElse(null),
processInstance.getProcessInstanceId(), processInstance.getTenantId(), null);
log.info("发送站内信: {}", JSONUtil.toJsonStr(messagePushEvent));
eventDispatcher.dispatchEvent(messagePushEvent, processEngineConfiguration.getEngineCfgKey());
BpmnMetaParserHelper.getNoticeConfig(ProcessDefinitionUtil.getProcess(processInstance.getProcessDefinitionId()))
.ifPresent(config -> {
if (config.getNotice().getTriggerEvents().contains(resultEnum)) {
Integer workspaceType = (Integer) processInstance.getProcessVariables().getOrDefault(INTERNAL_PROCESS_WORKSPACE_TYPE, WorkspaceType.UN_KNOW.getCode());
List<BpmnTaskDelegateAssigner> assigners = processEngineConfiguration.getCommandExecutor()
.execute(new CustomNoticeDestinationUserSelectorCmd(engineExecutionStartListener, historicTaskInstanceConverter,
serviceVersion, workspaceType, config.getNotice(), event.getProcessInstanceId(), assigner));
MessagePushEventImpl messagePushEvent = MessagePushEventBuilder.createEvent(MessagePushEventType.NOTICE,
assigners, config, processInstance.getProcessInstanceId(), processInstance.getTenantId(), null);
log.info("发送通知消息: {}", JSONUtil.toJsonStr(messagePushEvent));
eventDispatcher.dispatchEvent(messagePushEvent, processEngineConfiguration.getEngineCfgKey());
}
});
}
private List<BpmnProcessEventListener> getOrderedListeners() {

View File

@ -0,0 +1,70 @@
package cn.axzo.workflow.core.engine.model;
import cn.axzo.workflow.common.enums.ApproverScopeEnum;
import cn.axzo.workflow.common.enums.ApproverSpecifyEnum;
import cn.axzo.workflow.common.enums.WorkspaceType;
import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
import org.flowable.bpmn.model.FlowElement;
import static cn.axzo.workflow.core.common.code.FlowableEngineRespCode.ENGINE_NOTICE_CUSTOM_FLOW_ELEMENT_ERROR;
/**
* 自定义扩展流程模型中的元素
*
* @author wangli
* @since 2024/5/11 10:32
*/
public class NoticeFlowElement extends FlowElement {
private Integer workspaceType;
private ApproverSpecifyEnum specifyEnum;
private String customValues;
public NoticeFlowElement() {
}
public NoticeFlowElement(Integer workspaceType, ApproverSpecifyEnum specifyEnum, String customValues) {
this.workspaceType = workspaceType;
this.specifyEnum = specifyEnum;
this.customValues = customValues;
}
public void setWorkspaceType(Integer workspaceType) {
this.workspaceType = workspaceType;
}
public ApproverSpecifyEnum getSpecifyEnum() {
return specifyEnum;
}
public void setSpecifyEnum(ApproverSpecifyEnum specifyEnum) {
this.specifyEnum = specifyEnum;
}
public String getCustomValues() {
return customValues;
}
public void setCustomValues(String customValues) {
this.customValues = customValues;
}
public ApproverScopeEnum getProcessor() {
switch (WorkspaceType.getType(workspaceType)) {
case ENT:
case GOVERNMENT:
case OMS:
return ApproverScopeEnum.entWorkspace;
case PROJECT:
return ApproverScopeEnum.projectWorkspace;
default:
throw new WorkflowEngineException(ENGINE_NOTICE_CUSTOM_FLOW_ELEMENT_ERROR);
}
}
@Override
public NoticeFlowElement clone() {
NoticeFlowElement clone = new NoticeFlowElement();
clone.setValues(this);
return clone;
}
}

View File

@ -63,7 +63,8 @@ public interface BpmnProcessInstanceConverter extends EntityConverter<BpmnProces
approveConf.ifPresent(vo::setProcessApproveConf);
category.ifPresent(i -> {
vo.setWorkspaceType(WorkspaceType.getType(Integer.valueOf(i.getWorkspaceTypeCode())));
vo.setCategory(i.getLabel());
vo.setCategoryDesc(i.getLabel());
vo.setCategory(i.getValue());
});
if (!CollectionUtils.isEmpty(runningTasks)) {
vo.setCurrentDefinitionKey(runningTasks.get(0).getTaskDefinitionKey());

View File

@ -10,6 +10,7 @@ import cn.axzo.workflow.core.deletage.BpmnTaskAssigneeSelector;
import cn.axzo.workflow.core.deletage.approverscope.ApproverScopeDTO;
import cn.axzo.workflow.core.deletage.approverscope.ApproverScopeProcessor;
import cn.axzo.workflow.core.engine.listener.EngineExecutionStartListener;
import cn.axzo.workflow.core.engine.model.NoticeFlowElement;
import cn.axzo.workflow.server.common.util.DingTalkUtils;
import cn.hutool.core.lang.Assert;
import cn.hutool.http.HttpStatus;
@ -67,6 +68,9 @@ public abstract class AbstractBpmnTaskAssigneeSelector implements BpmnTaskAssign
assigners.addAll(privateSelector(ApproverScopeEnum.valueOfProcessor(processor), flowElement,
execution, throwException));
}
} else if (flowElement instanceof NoticeFlowElement) {
ApproverScopeEnum processor = ((NoticeFlowElement) flowElement).getProcessor();
assigners.addAll(privateSelector(processor, flowElement, execution, throwException));
}
return assigners.stream().filter(i -> StringUtils.hasText(i.getPersonId())).collect(Collectors.toList());
}
@ -152,6 +156,15 @@ public abstract class AbstractBpmnTaskAssigneeSelector implements BpmnTaskAssign
.stream().map(JSON::parseObject)
.map(i -> i.getString("value"))
.collect(Collectors.toList());
} else if (flowElement instanceof NoticeFlowElement) {
String customValues = ((NoticeFlowElement) flowElement).getCustomValues();
if (StringUtils.hasText(customValues)) {
return JSON.parseArray(customValues, String.class)
.stream().map(JSON::parseObject)
.map(i -> i.getString("value"))
.collect(Collectors.toList());
}
return Collections.emptyList();
} else {
return Collections.emptyList();
}

View File

@ -100,6 +100,8 @@ public class RocketMqMessagePushEventListener extends AbstractBpmnEventListener<
private BpmnHistoricTaskInstanceConverter historicTaskInstanceConverter;
@Resource
private String serviceVersion;
@Value("${workflow.noticeTemplateCode}")
private String noticeTemplateCode;
private static final List<String> REMOVE_KEYS = Lists.newArrayList(
INTERNAL_INITIATOR,
@ -123,14 +125,14 @@ public class RocketMqMessagePushEventListener extends AbstractBpmnEventListener<
public void onNotice(MessagePushEvent event) {
if (Objects.isNull(event.getNoticeConfig())
|| Objects.isNull(event.getNoticeConfig().getNotice())
|| !StringUtils.hasText(event.getNoticeConfig().getNotice().getNoticeMessageId())
|| !event.getNoticeConfig().getNotice().getSendMessage()
|| Objects.isNull(event.getAssigners())) {
return;
}
log.info("RocketMqMessagePushEventListener#onNotice...msgTemplateId: {}, receivePerson: {}",
event.getNoticeConfig().getNotice().getNoticeMessageId(), JSONUtil.toJsonStr(event.getAssigners()));
if (Objects.nonNull(event.getNoticeConfig().getNotice())) {
MessagePushDTO dto = build(event.getNoticeConfig().getNotice().getNoticeMessageId(),
MessagePushDTO dto = build(noticeTemplateCode,
PROCESS_PUSH_NOTICE, event, collectionVariable(event));
sendMessageQueue(dto, PROCESS_PUSH_NOTICE);
}
@ -174,8 +176,6 @@ public class RocketMqMessagePushEventListener extends AbstractBpmnEventListener<
if (isCarbonUsers(instance, bpmnTaskDelegateAssigner)) {
buttons.addAll(buttonConf.getCarbonCopy());
}
});
}
dto.setButtons(buttons);