package com.vci.web.dao.impl;
import com.vci.common.utility.ObjectUtility;
import com.vci.constant.WFVariablesKeyConstant;
import com.vci.corba.common.PLException;
import com.vci.corba.common.data.UserEntityInfo;
import com.vci.corba.omd.data.BusinessObject;
import com.vci.corba.omd.data.LinkObject;
import com.vci.corba.wf.WFServicePrx;
import com.vci.corba.wf.data.*;
import com.vci.corba.workflow.data.FlowApproveHistoryInfo;
import com.vci.dto.ProcessTemplateVO;
import com.vci.model.ProcessInstance;
import com.vci.model.ProcessTask;
import com.vci.model.WFProcessClassifyDO;
import com.vci.model.WFProcessTemplateDO;
import com.vci.omd.utils.ObjectTool;
import com.vci.pagemodel.*;
import com.vci.starter.web.constant.QueryOptionConstant;
import com.vci.starter.web.exception.VciBaseException;
import com.vci.starter.web.pagemodel.DataGrid;
import com.vci.starter.web.pagemodel.PageHelper;
import com.vci.starter.web.util.BeanUtilForVCI;
import com.vci.starter.web.util.VciBaseUtil;
import com.vci.starter.web.util.VciDateUtil;
import com.vci.web.dao.WebProcessDaoI;
import com.vci.web.service.SmUserQueryServiceI;
import com.vci.web.service.WebBoServiceI;
import com.vci.web.service.WebLifeCycleServiceI;
import com.vci.web.service.WebLoServiceI;
import com.vci.web.util.PlatformClientUtil;
import com.vci.web.util.WebUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;
import static com.vci.constant.FrameWorkBusLangCodeConstant.DATA_OID_NOT_EXIST;
/**
* 流程的数据层
* @author weidy
*/
@Repository
public class WebProcessDaoImpl implements WebProcessDaoI {
/**
* 日志
*/
private Logger logger = LoggerFactory.getLogger(getClass());
/**
* 多语言的前缀
*/
private final String msgCodePrefix = "com.vci.web.flow.";
@Resource
private WebBoServiceI boService;
@Resource
private WebLoServiceI loService;
@Resource
private WebLifeCycleServiceI lifeCycleService;
/**
* 用户查询服务
*/
@Autowired
private SmUserQueryServiceI userQueryService;
/**
* 平台的流程服务
*/
private WFServicePrx wfService = null;
/**
* 平台调用客户端
*/
@Autowired
private PlatformClientUtil platformClientUtil;
/***
* 流程分类主键和类型的映射
*/
private Map categoryMap = new HashMap();
private final String workitemBtmType = "workitem";
private final String workIntanceBtmType = "workflowinstance";
private final String processDataLink ="input";
private final String taskDataLink = "input";
/**
* 获取流程分类的映射
* @throws VciBaseException
*/
private void getCategory() throws VciBaseException {
try {
ProcessCategoryInfo[] pcia = getWFService().getProcessCategories("root");
if(pcia!=null&&pcia.length>0){
for(ProcessCategoryInfo pci : pcia){
categoryMap.put(pci.name.toLowerCase(), pci.id);
}
}
} catch (PLException e) {
WebUtil.getVciBaseException(e);
}
}
/**
* 获取某个分类下的所有流程模版
* @param type 分类信息
* @param filterTemplate 指定模板
* @param showAll 是否显示所有版本的
* @return
* @throws
*/
@Override
public List getTemplatesByType(String type, String filterTemplate, boolean showAll)
throws VciBaseException {
WebUtil.alertNotNull(type,"模板分类");
ProcessDefinitionInfo[] allFlowInType = null;
if(StringUtils.isBlank(filterTemplate)) {
//无指定模板情况下,获取模板分类下的所有模板
type = type.toLowerCase();
if (categoryMap.isEmpty() || !categoryMap.containsKey(type)) {
getCategory();
}
String typeOid = "" ;
if (categoryMap.containsKey(type)) {
typeOid = categoryMap.get(type);
} else {
throw new VciBaseException(msgCodePrefix + "typeNotExist", new String[]{type});
}
try {
allFlowInType = getWFService().getProcessDefinitions(typeOid);
} catch (PLException e) {
throw WebUtil.getVciBaseException(e);
}
}else{
List infoList = new ArrayList<>();
List templateList = VciBaseUtil.str2List(filterTemplate);
if(!CollectionUtils.isEmpty(templateList)){
templateList.forEach(name->{
/*try {*/
String nameUnRev = name;
String revision = "";
if(name.contains("-")){
nameUnRev = name.substring(0,name.lastIndexOf("-"));
revision = name.substring(name.lastIndexOf("-")+1);
}
ProcessDefinitionInfo[] definition = null;//getWFService()().getProcessDefinitionByProcessDefinitionName(nameUnRev, "");
if(definition!=null){
if(StringUtils.isBlank(revision)) {
Collections.addAll(infoList, definition);
}else{
//过滤版本
String finalRevision = revision;
infoList.addAll(Arrays.stream(definition).filter(s -> finalRevision.equalsIgnoreCase(String.valueOf(s.version))).collect(Collectors.toList()));
}
}
/*} catch (PLException e) {
throw WebUtil.getVciBaseException(e);
}*/
});
}
allFlowInType = infoList.toArray(new ProcessDefinitionInfo[0]);
}
return swapProcessTemplate(allFlowInType, type, showAll);
}
/**
* 根据部署主键,获取流程模板对象
* @param deployId 部署主键
* @return
* @throws VciBaseException
*/
@Override
public ProcessTemplateVO getTemplateByDeployId(String deployId) throws VciBaseException {
WebUtil.alertNotNull(deployId,"流程部署主键");
ProcessDefinitionInfo pdi = null;
try {
pdi = getWFService().getProcessDefinitionByDeployId(deployId.trim());
} catch (PLException e) {
throw new VciBaseException(msgCodePrefix + "deployIdNotExist", new String[]{deployId});
}
List proTemplates = swapProcessTemplate(new ProcessDefinitionInfo[]{pdi},"",false);
if(proTemplates == null || proTemplates.size() == 0){
throw new VciBaseException(msgCodePrefix + "deployIdNotExist", new String[]{deployId});
}
return proTemplates.get(0);
}
private List swapProcessTemplate(ProcessDefinitionInfo[] allFlowInType, String type, boolean showAll){
List allTemplate = new ArrayList();
if(allFlowInType!=null&&allFlowInType.length>0){
for(ProcessDefinitionInfo pd : allFlowInType){
//status = 0 表示停用, status = 1表示启用
if("1".equalsIgnoreCase(pd.status) || showAll){
ProcessTemplateVO pt = new ProcessTemplateVO();
pt.setOid(pd.id);
pt.setCategroyOid(pd.categroyId);
pt.setDeploymentId(pd.jbpmDeploymentId);
pt.setKey(pd.key);
pt.setName(pd.name);
pt.setStatus(pd.status);
pt.setTaskType(type);
pt.setVersion((int) pd.version);
allTemplate.add(pt);
}
}
}
return allTemplate;
}
/**
* 获取流程的所有节点
* @param processOid
*/
@Override
public List getAllProcessNode(String processOid)
throws VciBaseException{
WebUtil.alertNotNull(processOid,"流程主键");
String deploymentId = getJbpmDeploymentId(processOid);
if(StringUtils.isBlank(deploymentId)){
throw new VciBaseException(msgCodePrefix + "processTemplateNotExist",new String[]{processOid});
}
String[] allTaskNames = getAllProcessNodeNameByDeploy(deploymentId);
List allNode = new ArrayList();
for(String taskName : allTaskNames){
ProcessNodeVO pn = getNodePresideUsersByDeploy(deploymentId, taskName);
allNode.add(pn);
}
return allNode;
}
/**
* 获取流程中的第一个节点的名称
* @param deployId 部署主键
* @return
* @throws VciBaseException
*/
@Override
public String getFirstNodeName(String deployId) throws VciBaseException {
WebUtil.alertNotNull(deployId,"部署主键");
try {
ProcessTaskInfo firstProcessTask = getWFService().getFirstProcessTask(deployId);
if(firstProcessTask!=null){
return firstProcessTask.taskName;
}
} catch (PLException e) {
throw WebUtil.getVciBaseException(e);
}
return null;
}
/**
* 获取流程的所有节点名称
* @param processOid
*/
@Override
public String[] getAllProcessNodeName(String processOid) throws VciBaseException{
if(StringUtils.isEmpty(processOid)){
WebUtil.alertNotNull(processOid);
}
String deploymentId = getJbpmDeploymentId(processOid);
if(StringUtils.isEmpty(deploymentId)){
throw new VciBaseException(msgCodePrefix + "processTemplateNotExist",new String[]{processOid});
}
return getAllProcessNodeNameByDeploy(deploymentId);
}
/**
* 获取流程中的所有节点名称
* @param deploymentId 流程引擎中的部署id
* @return
* @throws VciBaseException
*/
@Override
public String[] getAllProcessNodeNameByDeploy(String deploymentId) throws VciBaseException{
String[] allTaskNames = null;
try {
allTaskNames = getWFService().getAllTaskNames(deploymentId);
} catch (PLException e) {
throw WebUtil.getVciBaseException(e);
}
return allTaskNames;
}
/**
* 获取流程模板在流程引擎中的部署主键
* @param processOid
*/
@Override
public String getJbpmDeploymentId(String processOid) throws VciBaseException{
WebUtil.alertNotNull(processOid,"流程模板主键");
return null;//getWFService()().getDeploymentID(processOid);
}
/**
* 获取流程模板对应的引擎里的部署主键
* @param executionId
* @return
* @throws VciBaseException
*/
@Override
public String getJbpmDeploymentIdByExecutionId(String executionId) throws VciBaseException{
WebUtil.alertNotNull(executionId,"流程执行主键");
try {
return getWFService().getDeploymentIdByExecutionId(executionId);
} catch (PLException e) {
throw WebUtil.getVciBaseException(e);
}
}
/**
* 获取模板中节点设置的负责人
* @param deploymentId 引擎中的部署主键
* @param taskName 任务节点名称
* @return
* @throws VciBaseException
*/
@Override
public ProcessNodeVO getNodePresideUsersByDeploy(String deploymentId, String taskName) throws VciBaseException{
WebUtil.alertNotNull(taskName,"流程任务名称",deploymentId,"流程引擎中的部署主键");
ProcessNodeVO pn = new ProcessNodeVO();
pn.setName(taskName);
try {
String[] nodePresideUsers = getWFService().getCurCandidates(deploymentId, taskName, "", "");
if(nodePresideUsers!=null&& nodePresideUsers.length>0){
for(String preUsers : nodePresideUsers){
//平台存储的方式是用户;角色;部门;自定义....
if(StringUtils.isNotEmpty(preUsers)){
String[] preUsersSplit = preUsers.split("\\;");
if(preUsersSplit!=null && preUsersSplit.length>0){
if(StringUtils.isNotEmpty(preUsersSplit[0])){
pn.setUsers(preUsersSplit[0]);
}
if(preUsersSplit.length>1 && StringUtils.isNotEmpty(preUsersSplit[1])){
pn.setRoles(preUsersSplit[1]);
}
if(preUsersSplit.length>2 && StringUtils.isNotEmpty(preUsersSplit[2])){
pn.setDepts(preUsersSplit[2]);
}
if(preUsersSplit.length>3 && StringUtils.isNotEmpty(preUsersSplit[3])){
pn.setCustomClass(preUsersSplit[3]);
}
}
}
}
}
} catch (PLException e) {
throw WebUtil.getVciBaseException(e);
}
return pn;
}
/**
* 获取流程模板中某个节点的处理人
* @param processOid
* @param taskName
* @return
* @throws VciBaseException
*/
@Override
public ProcessNodeVO getNodePresideUsers(String processOid, String taskName) throws VciBaseException{
WebUtil.alertNotNull(taskName,"流程任务节点名称",processOid,"流程主键");
String deploymentId = getJbpmDeploymentId(processOid);
if(StringUtils.isEmpty(deploymentId)){
throw new VciBaseException(msgCodePrefix + "processTemplateNotExist",new String[]{processOid});
}
return getNodePresideUsersByDeploy(deploymentId,taskName);
}
/**
* 获取任务的处理人
* @param executionid 执行主键
* @param taskName 任务名称
* @return
* @throws VciBaseException
*/
@Override
public List getNodePresideUsersByTask(String executionid, String taskName)
throws VciBaseException{
WebUtil.alertNotNull(executionid,"流程执行任务",taskName,"任务名称");
if("结束".equalsIgnoreCase(taskName)){
return null;
}
//不能使用workitem去查询,因为可能任务还没到
String users = getWFService().getNextTaskAssigner(executionid, taskName);
List allProUser = new ArrayList();
if(StringUtils.isNotEmpty(users)){
String userIds = users.replace("user:", "");//现在只支持设置用户
List allUser = userQueryService.listUserByUserIds(WebUtil.str2List(userIds));
if(allUser!=null && allUser.size()>0){
for(SmUserVO user : allUser){
ProcessUserVO pu = new ProcessUserVO();
BeanUtils.copyProperties(user, pu);
pu.setType("user");
allProUser.add(pu);
}
}
}
return allProUser;
}
/**
* 查询待办任务
*/
@Override
public DataGrid getUndoTask(
Map conditionMap, PageHelper ph, String userId)
throws VciBaseException {
return getProcessTask(conditionMap,ph,userId,1);
}
/**
* 使用流程实例获取所有的待办信息
* @param processInstanceId 流程的实例主键
* @return 待办的任务
*/
@Override
public DataGrid getUndoTaskByInstanceId(String processInstanceId, long mill){
Map conditionMap = new HashMap<>();
conditionMap.put("executionid",processInstanceId+"*");
if(mill>0) {
conditionMap.put("ts", QueryOptionConstant.MORETHAN + VciDateUtil.date2Str(new Date(mill), VciDateUtil.DateTimeMillFormat));
}
return getProcessTask(conditionMap,new PageHelper(-1),null,8);
}
/**
* 查询流程任务
* @param conditionMap 查询条件
* @param ph 分页信息,没有排序
* @param userId 用户名
* @param doTaskType 用户类型,1-待办任务,2-已办任务
* @return
* @throws VciBaseException
*/
private DataGrid getProcessTask(Map conditionMap, PageHelper ph, String userId,int doTaskType) throws VciBaseException,VciBaseException{
if(conditionMap == null) {
conditionMap = new HashMap();
}
String btmType = "";
if(doTaskType== 1){//待办任务
WebUtil.alertNotNull(userId,"用户名");
conditionMap.put("businesstype", "5");//本项目没有实际的意义
conditionMap.put("principal", userId);
conditionMap.put("lcstatus", "Executing");
btmType = workitemBtmType;
//ph.addSort("createtime",ph.desc);
}else if(doTaskType == 2){//已办任务
WebUtil.alertNotNull(userId,"用户名");
conditionMap.put("taskoid", QueryOptionConstant.IN +" ( select ht.DBID_ FROM JBPM4_HIST_TASK ht left join PLFLOWAPPROVEOPINION op on ht.DBID_ = op.PLTASKID where DECODE(op.plassgin, null, ht.ASSIGNEE_, op.plassgin) = '" + userId + "') ");
conditionMap.put("lcstatus","Completed");
btmType = workitemBtmType;
}else if(doTaskType == 3){//完成的流程
if(StringUtils.isNotEmpty(userId)) {//为空表示查询所有的
conditionMap.put("creator", userId);
}
conditionMap.put("lcstatus", "Completed");
btmType = workIntanceBtmType;
}else if(doTaskType == 4){//被终止的流程
if(StringUtils.isNotEmpty(userId)) {
conditionMap.put("creator", userId);
}
conditionMap.put("lcstatus", "Obsoleted");
btmType = workIntanceBtmType;
}else if(doTaskType ==5){//被挂起的流程
if(StringUtils.isNotEmpty(userId)) {
conditionMap.put("creator", userId);
}
conditionMap.put("lcstatus", "Suspended");
btmType = workIntanceBtmType;
}else if(doTaskType == 6){//执行中的流程
if(StringUtils.isNotEmpty(userId)) {
conditionMap.put("creator", userId);
}
conditionMap.put("lcstatus", "Executing");
btmType = workIntanceBtmType;
}else if(doTaskType ==7){
WebUtil.alertNotNull(userId,"用户名");
conditionMap.put("creator", userId);
}else if(doTaskType ==8){
//流程获取所有待处理的任务
conditionMap.put("lcstatus", "Executing");
btmType = workitemBtmType;
}else{
throw new VciBaseException(msgCodePrefix+"doTaskTypeError",new String[]{doTaskType+""});
}
List causeList = new ArrayList();
causeList.add("*");
causeList.add("creator_name");
if(doTaskType!= 1){
ph.addSort("ts",ph.desc);
}
ph.addSort("createtime",ph.desc);
return boService.queryGridByBo(btmType, conditionMap, ph,causeList);
}
@Override
public DataGrid getDoneProcess(Map conditionMap, PageHelper ph, String userId) throws VciBaseException {
return getProcessTask(conditionMap,ph,userId,2);
}
@Override
public DataGrid getCompletedProcess(Map conditionMap, PageHelper ph, String userId) throws VciBaseException {
return getProcessTask(conditionMap,ph,userId,3);
}
@Override
public DataGrid getObsoledtedProcess(Map conditionMap,
PageHelper ph, String userId) throws VciBaseException {
return getProcessTask(conditionMap,ph,userId,4);
}
@Override
public DataGrid getSuspendedProcess(Map conditionMap,
PageHelper ph, String userId) throws VciBaseException {
return getProcessTask(conditionMap,ph,userId,5);
}
@Override
public DataGrid getExecutingProcess(Map conditionMap,
PageHelper ph, String userId) throws VciBaseException {
return getProcessTask(conditionMap,ph,userId,6);
}
@Override
public DataGrid getCreateProcess(Map conditionMap,
PageHelper ph, String userId) throws VciBaseException {
return getProcessTask(conditionMap,ph,userId,7);
}
@Override
public List getTaskByOid(String oid) throws VciBaseException{
WebUtil.alertNotNull(oid,"待办任务主键");
List tasks = boService.selectByOidCollection(VciBaseUtil.str2List(oid),ProcessTask.class);
return processTaskDO2VOs(tasks);
}
/**
* 还有任务的主键获取任务CBO对象
* @param oid 主键
* @return CBO对象
* @throws VciBaseException 查询出错会抛出异常
*/
@Override
public List