首页 > 编程语言 >java实现用一个变量表示多个属性的状态

java实现用一个变量表示多个属性的状态

时间:2024-08-09 14:17:47浏览次数:16  
标签:java String getCode CONTRACTAPPROVE Integer import 属性 cn 变量

1、流程启动及状态流转举例(场景:同一份数据在多个流程中流转,确定各流程自己的状态)

1.发起流程核心代码

/**
    * 二进制方式
    * @param orgId
    * @param node
    * @param contractIds
    */
   private void startWithPosition(String orgId, String node, List<String> contractIds){
      CONTRACTAPPROVE currentNode = CONTRACTAPPROVE.valueOf(node);
      ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
         .processDefinitionKey(currentNode.getDefKey())
         .latestVersion()
         .singleResult();
      if(processDefinition == null) {
         throw new BusinessException(BusinessCode.CLIENT_ERROR.getCode(), "流程定义不存在");
      }
      //全局流程中所有处于未审批和执行中的流程状态int值
      List<Integer> allNoPermitState = Arrays.stream(CONTRACTAPPROVE.values())
         .map(e -> Arrays.asList(ApprovalState.WAIT.getCode(), ApprovalState.EXECUTE.getCode())
            .stream()
            .map(s -> Integer.valueOf(s) << e.getStateIndex())
            .collect(Collectors.toList()))
         .flatMap(Collection::stream)
         .collect(Collectors.toList());
      List<ContractEntity> contractList = contractMapper.selectBatchIds(contractIds);
      Map<String, ContractEntity> collect = contractList.stream()
         .filter(e -> e.getApprovalState() != null && allNoPermitState.contains(Integer.valueOf(e.getApprovalState())))
         .collect(Collectors.toMap(ContractEntity::getId, e -> e));
      if(CollUtil.isNotEmpty(collect)) {
         throw new BusinessException(BusinessCode.CLIENT_ERROR.getCode(),
            "以下合同已存在进行中的审批:" + JSON.toJSONString(collect.keySet()));
      }

      String processDefinitionId = processDefinition.getId();
      for(ContractEntity contract : contractList) {
         String approvalNode = contract.getApprovalNode() == null ? CONTRACTAPPROVE.CONTRACT_PRICE_APPROVE.getCode() : contract.getApprovalNode();
         CONTRACTAPPROVE dbNode = CONTRACTAPPROVE.getByCode(approvalNode);
         Assert.isTrue(currentNode.getCode().compareTo(dbNode.getCode()) >= 0, () -> {
            throw new BusinessException(BusinessCode.CLIENT_ERROR.getCode(), String.format(
               "合同%s当前所处的阶段【%s】不支持逆向流程发起!!!,正常顺序\n(价格报批0000 0001->合同会签0000 0011->合同发布0000 0111->合同变更 0000 1111->合同终止 0001 1111)",
               contract.getId(), approvalNode));
         });
         contract.setApprovalNode(node);
         String approvalState = contract.getApprovalState();
         Integer approvalStateNumber = StringUtils.isNotEmpty(approvalState)? Integer.valueOf(approvalState): 0;
         Map<String, Object> map = BeanUtil.beanToMap(contract);
         map.put("beanName", "contractFlowEventListener");
         flowDefinitionService.startProcessInstanceById(processDefinitionId, currentNode.getCode(), "true", map);
         String waitCode = ApprovalState.WAIT.getCode();
         Integer currentNodeState = Integer.valueOf(waitCode)<<currentNode.getStateIndex();
         Integer globalState = currentNodeState | approvalStateNumber;
         contract.setApprovalState(String.valueOf(globalState));
         contractMapper.updateById(contract);
      }
   }
View Code

2.获取多个流程

   private List<Map<String, String>> positionList() {
      return Arrays.stream(CONTRACTAPPROVE.values()).map(e -> new LinkedHashMap<String, String>() {{
         put(e.name(), e.getName() + "," + e.getCode());
      }}).collect(Collectors.toList());
   }
View Code

3、流程组装成枚举

package cn.togeek.geekbidder.crm.contract.service;

import cn.togeek.foundation.web.api.BusinessCode;
import cn.togeek.foundation.web.exception.BusinessException;

import java.util.Arrays;
import java.util.Optional;
import org.springframework.util.Assert;

public enum CONTRACTAPPROVE {
   /**
    * 价格报批0000 0001,合同会签0000 0011、合同发布0000 0111、合同变更 0000 1111、合同终止 0001 1111
    */
   CONTRACT_PRICE_APPROVE("价格报批", "0000 0001", 0,"Process_lzkpuzut") {
      @Override
      CONTRACTAPPROVE[] getNearNode() {
         return new CONTRACTAPPROVE[]{null, CONTRACT_SIGN_APPROVE};
      }
   },
   CONTRACT_SIGN_APPROVE("合同会签", "0000 0011", 3,"Process_lzl5psyn") {
      @Override
      CONTRACTAPPROVE[] getNearNode() {
         return new CONTRACTAPPROVE[]{CONTRACT_PRICE_APPROVE, CONTRACT_PUBLISH_APPROVE};
      }
   },
   CONTRACT_PUBLISH_APPROVE("合同发布", "0000 0111", 6,"Process_lzl5r66s") {
      @Override
      CONTRACTAPPROVE[] getNearNode() {
         return new CONTRACTAPPROVE[]{CONTRACT_SIGN_APPROVE, CONTRACT_CHANGE_APPROVE};
      }
   },
   CONTRACT_CHANGE_APPROVE("合同变更", "0000 1111",9,"Process_lzl5tu36") {
      @Override
      CONTRACTAPPROVE[] getNearNode() {
         return new CONTRACTAPPROVE[]{CONTRACT_PUBLISH_APPROVE, CONTRACT_TERMINATE_APPROVE};
      }
   },
   CONTRACT_TERMINATE_APPROVE("合同终止", "0001 1111", 12,"Process_lzl5t5h6") {
      @Override
      CONTRACTAPPROVE[] getNearNode() {
         return new CONTRACTAPPROVE[]{CONTRACT_CHANGE_APPROVE, null};
      }
   };

   private final String name;
   private final String code;
   //状态所在二进制位左移的位数
   private final Integer stateIndex;
   private final String defKey;

   public String getName() {
      return name;
   }

   public String getCode() {
      return code;
   }

   public Integer getStateIndex() {
      return stateIndex;
   }

   public String getDefKey() {
      return defKey;
   }

   CONTRACTAPPROVE(String name, String code, Integer stateIndex, String defKey) {
      this.name = name;
      this.code = code;
      this.stateIndex = stateIndex;
      this.defKey = defKey;
   }

   /**
    *
    * 获取当前节点的相邻节点
    * @return
    */
   abstract CONTRACTAPPROVE[] getNearNode();

   public static CONTRACTAPPROVE getByCode(String code) {
      Optional<CONTRACTAPPROVE> any =
         Arrays.stream(CONTRACTAPPROVE.values()).filter(n -> n.getCode().equals(code)).findAny();
      Assert.isTrue(any.isPresent(), () -> {
         throw new BusinessException(BusinessCode.CLIENT_ERROR.getCode(), "流程编码错误!!!");
      });
      return any.get();
   }
}
View Code

4、监听回调

package cn.togeek.geekbidder.crm.contract.service;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import lombok.AllArgsConstructor;

import cn.togeek.foundation.util.DateTimeHelper;
import cn.togeek.foundation.web.api.BusinessCode;
import cn.togeek.foundation.web.exception.BusinessException;
import cn.togeek.geekbidder.crm.contract.entity.ContractEntity;
import cn.togeek.geekbidder.crm.contract.enums.ApprovalState;
import cn.togeek.geekbidder.crm.contract.mapper.ContractNewMapper;
import cn.togeek.maple.process.api.enums.FlowCommentEnum;
import cn.togeek.maple.process.api.model.ListenerEvent;
import cn.togeek.maple.process.api.model.ListenerEventSource;

import java.time.LocalDate;
import java.util.Map;
import java.util.Objects;

import org.flowable.engine.RuntimeService;
import org.flowable.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

/**
 * @author hanle
 * @description
 * @date 2024/8/6 13:44
 * @Company 西安图迹信息科技有限公司
 */
@Component
@AllArgsConstructor
public class ContractFlowEventListener implements ApplicationListener<ListenerEventSource> {

   @Autowired
   private RuntimeService runtimeService;
   @Autowired
   private ContractNewMapper contractNewMapper;

   /**
    * 流程结束监听
    *
    * @param event
    */
   @Override
   public void onApplicationEvent(ListenerEventSource event) {
      callBackWithStateCal(event);
   }

   /**
    * 二进制操作方式
    * @param event
    */
   public void callBackWithPositionCal(ListenerEventSource event){
      ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
         .processInstanceId(event.getListenerEvent().getProcessInstanceId())
         .singleResult();

      if(Objects.isNull(processInstance)) {
         return;
      }

      Map<String, Object> processVariables = processInstance.getProcessVariables();
      String id = String.valueOf(processVariables.get("id"));
      ListenerEvent listenerEvent = event.getListenerEvent();
      String approvalResults = listenerEvent.getApprovalResults();
      LambdaUpdateWrapper<ContractEntity> wrapper = new LambdaUpdateWrapper<ContractEntity>().eq(ContractEntity::getId, id);
      ContractEntity contractEntity = contractNewMapper.selectById(id);
      Assert.notNull(contractEntity, () -> {
         throw new BusinessException(BusinessCode.CLIENT_ERROR.getCode(), String.format(
            "合同id为"+ id + "的合同不存在,可能已被删除,请检查!!!"));
      });
      CONTRACTAPPROVE dbNode = CONTRACTAPPROVE.getByCode(contractEntity.getApprovalNode());
      CONTRACTAPPROVE nextNode = dbNode.getNearNode()[1];
      //上一个流程节点结束时将全局流程节点改为下一个节点
      if(nextNode!=null) {
         contractEntity.setApprovalNode(nextNode.getCode());
      }
      Integer dbFinalState = Integer.valueOf(contractEntity.getApprovalState());
      String state = Integer.toString(dbFinalState, 2);
      //向左偏移量
      Integer offsetLft = dbNode.getStateIndex();
      //3个bit位代表状态
      int bitPoint = 3;
      state = StrUtil.padPre(state, bitPoint + offsetLft, "0");
      String statePre = state.substring(state.length() - offsetLft, state.length());
      Integer preStateInt = Integer.valueOf(StringUtils.hasLength(statePre) ? statePre : "0", 2);
      if(FlowCommentEnum.NORMAL.getType().equals(approvalResults)) {
         // 审批通过
         Integer pass = Integer.valueOf(ApprovalState.CHANGE.getCode());
         int curNodeState = pass << offsetLft;
         int globalNodeState = curNodeState | preStateInt;
         contractEntity.setContractState(String.valueOf(globalNodeState));
      }
      else if(FlowCommentEnum.REJECT.getType().equals(approvalResults)) {
         // 审批驳回
         Integer reject = Integer.valueOf(ApprovalState.TERMINATION.getCode());
         int curNodeState = reject << offsetLft;
         int globalNodeState = curNodeState | preStateInt;
         contractEntity.setContractState(String.valueOf(globalNodeState));
      }
      contractNewMapper.updateById(contractEntity);
   }

   /**
    * 常规操作
    * @param event
    */
   public void callBackWithStateCal(ListenerEventSource event){
      ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
         .processInstanceId(event.getListenerEvent().getProcessInstanceId())
         .singleResult();

      if(Objects.isNull(processInstance)) {
         return;
      }

      Map<String, Object> processVariables = processInstance.getProcessVariables();
      String id = String.valueOf(processVariables.get("id"));
      ListenerEvent listenerEvent = event.getListenerEvent();
      String approvalResults = listenerEvent.getApprovalResults();
      ContractEntity contractEntity = contractNewMapper.selectById(id);
      Assert.notNull(contractEntity, () -> {
         throw new BusinessException(BusinessCode.CLIENT_ERROR.getCode(), String.format(
            "合同id为"+ id + "的合同不存在,可能已被删除,请检查!!!"));
      });
      ContractApproveGlobal dbNode = ContractApproveGlobal.getByCode(contractEntity.getApprovalNode());
      ContractApproveGlobal nextNode = dbNode.getNearNode()[1];
      //上一个流程节点结束时将全局流程节点改为下一个节点
      if(nextNode!=null) {
         contractEntity.setApprovalNode(nextNode.getCode());
      }
      if(FlowCommentEnum.NORMAL.getType().equals(approvalResults)) {
         // 审批通过
         contractEntity.setContractState(null);
      }
      else if(FlowCommentEnum.REJECT.getType().equals(approvalResults)) {
         // 审批驳回
         contractEntity.setContractState(ApprovalState.TERMINATION.getCode());
      }
      contractNewMapper.updateById(contractEntity);
   }
}
View Code

 

标签:java,String,getCode,CONTRACTAPPROVE,Integer,import,属性,cn,变量
From: https://www.cnblogs.com/g177w/p/18350668

相关文章

  • Java入门学习——Day02Java工具
    一、Javac1.1Java1(1996年)        Java编译器 javac 在Java1.0版本中首次发布。它将Java源代码(.java 文件)编译成中间字节码(.class 文件)。这个字节码可以在Java虚拟机(JVM)上运行,实现了Java的“编写一次,处处运行”的理念。1.2Java2(1998年)        在Java......
  • JavaScript -- 总结 10 (小白)
    MouseEvent属性<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0"><title>Document<......
  • JAVA多线程的使用和创建的几种方式
    Thrad创建和使用创建实体类,继承Thread实现run()方法调用start()方法publicclassThreadDemoextendsThread{Loggerlogger=LoggerFactory.getLogger(ThreadDemo.class);privateStringtaskName;publicStringgetTaskName(){return......
  • JAVA修饰符、运算符、循环语句
    JAVA修饰符修饰符用来定义类、方法或者变量,通常放在语句的最前端一、访问修饰符1、default默认访问修饰符:在同一包内可见,不使用任何修饰符,使用对象为类、接口、变量、方法,访问级别是包级别(package-level),即只能被同一包中的其他类访问2、private私有访问修饰符:最严格的访问级......
  • JavaScript toLocaleString() 方法
    定义和用法:toLocaleString()方法可根据本地时间把Date对象转换为字符串,并返回结果。语法:dateObject.toLocaleString()返回值dateObject的字符串表示,以本地时间区表示,并根据本地规则格式化。问题//Javascript中newDate().toLocaleString()在不同浏览器中的结果不一致的解决......
  • Java enum(枚举)
    在Java中,enum(枚举)是一种特殊的数据类型,允许你定义一组命名的常量。这些常量通常代表一个固定的、有限的集合。例如,一年中的季节、交通信号灯的状态,或者一副扑克牌的花色。基本用法一个基本的enum定义如下:publicenumSeason{WINTER,SPRING,SUMMER,FALL}这里,Season......
  • java 面向对象2
    1.对类的命名要起到见名知意的效果。对于属性成员最好用private修饰提高权限,使得数据的存储更加安全。一般来说对于类用大驼峰命名法每个单词首字母都是大写如图2.在java中没有指针的概念,但是存在引用所以this在使用的时候就可以通过'.'来访问成员。3.与c++类似不存在空参构造......
  • Java Optional
    Optional是Java8引入的一个容器类,用于处理可能为空(null)的值。它旨在减少NullPointerException(空指针异常)的发生,并提供一种更具表现力和安全的方式来处理可选值。Optional的基本概念Optional<T>:Optional是一个泛型类,可以包含类型为T的值,或者为空。非空值:Optional可以......
  • Java Stream
    JavaStream是Java8引入的一种强大工具,旨在简化数据处理操作。它允许开发者以声明性方式对集合或其他数据源执行一系列复杂的操作,如过滤、映射、规约等,从而提高代码的简洁性和可读性。以下是关于JavaStreamAPI的更详细的概述和示例,帮助你更好地理解其工作原理和应用场景。......
  • Java计算机毕业设计江理工大学生创新创业项目管理系统的设计与实现(开题+源码+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景在当今社会,创新创业已成为推动经济发展、促进社会进步的重要力量。高校作为人才培养的摇篮,肩负着培养具有创新精神和实践能力的高素质人才的重任。江......