Flowable流程图有效性检验,可自定义规则
针对符合Bpmn规范的流程图(本质为xml文件)进行一些规则校验,例如:必须包含UserTask节点、指定节点审核人不能少于两人、必须设置某某属性等,具体规则自行定义。
1、主要方法
package com.lc.workflow.common.utils;
import com.lc.common.core.exception.CustomException;
import com.lc.common.core.utils.StringUtils;
import org.flowable.bpmn.converter.BpmnXMLConverter;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.validation.ProcessValidator;
import org.flowable.validation.ProcessValidatorFactory;
import org.flowable.validation.ValidationError;
import org.flowable.validation.validator.ValidatorSet;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.List;
/**
* flowable流程图xml校验
*
* @author lsy
* @date 2022/06/16 11:20
**/
public class FlowableModelValidateUtil {
public static Object validateModel(String xmlStr) {
if (StringUtils.isBlank(xmlStr)) {
throw new CustomException("xmlStr不能为空");
}
try {
// 把xml转换成BpmnModel对象
InputStream inputStream = new ByteArrayInputStream(xmlStr.getBytes());
XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(inputStream);
BpmnXMLConverter bpmnXMLConverter = new BpmnXMLConverter();
BpmnModel bpmnModel = bpmnXMLConverter.convertToBpmnModel(xmlStreamReader);
// 模板验证
ProcessValidator validator = new ProcessValidatorFactory().createDefaultProcessValidator();
ValidatorSet validatorSet = new ValidatorSet("My Validator");
// new MyFlowableValidator()为自定义实现的规则校验器
validatorSet.addValidator(new MyFlowableValidator());
validator.getValidatorSets().add(validatorSet);
List<ValidationError> errorList = validator.validate(bpmnModel);
if (errorList.isEmpty()) {
return true;
} else {
return errorList;
}
} catch (XMLStreamException e) {
throw new CustomException(e.getMessage());
}
}
}
2、自定义规则校验器
package com.lc.workflow.common.validator;
import com.lc.common.core.utils.StringUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.StartEvent;
import org.flowable.bpmn.model.UserTask;
import org.flowable.validation.ValidationError;
import org.flowable.validation.validator.ProcessLevelValidator;
import java.util.List;
/**
* 自定义规则校验器
*
* @author lsy
* @date 2022/06/16 14:30
**/
public class MyFlowableValidator extends ProcessLevelValidator {
@Override
protected void executeValidation(BpmnModel bpmnModel, Process process, List<ValidationError> errors) {
List<UserTask> userTaskList = process.findFlowElementsOfType(UserTask.class);
if (CollectionUtils.isEmpty(userTaskList)) {
errors.add(validationErrorFactory(null, null, "can not find UserTask", true));
} else {
userTaskList.stream().filter(task -> StringUtils.isBlank(task.getName())).forEach(s -> {
errors.add(validationErrorFactory(s.getId(), s.getName(), "UserTask missing name", true));
});
userTaskList.stream().filter(task -> StringUtils.isBlank(task.getAssignee())
&& CollectionUtils.isEmpty(task.getCandidateUsers())
&& CollectionUtils.isEmpty(task.getCandidateGroups())).forEach(s -> {
errors.add(validationErrorFactory(s.getId(), s.getName(), "can not find UserTask recipient", false));
});
}
List<StartEvent> startEventList = process.findFlowElementsOfType(StartEvent.class);
if (CollectionUtils.isEmpty(startEventList)) {
errors.add(validationErrorFactory(null, null, "can not find StartEvent", true));
}
}
private ValidationError validationErrorFactory(String activityId, String activityName, String msg, boolean warning) {
ValidationError validationError = new ValidationError();
validationError.setActivityId(activityId);
validationError.setActivityName(activityName);
validationError.setDefaultDescription(msg);
validationError.setWarning(warning);
return validationError;
}
}