org.activiti.bpmn

news2025/7/11 18:39:21

org.activiti.bpmn

  • 目录
    • 概述
      • 需求:
    • 设计思路
    • 实现思路分析
      • 1.BpmnAutoLayout
      • 2.BPMNLayout
  • 参考资料和推荐阅读

Survive by day and develop by night.
talk for import biz , show your perfect code,full busy,skip hardness,make a better result,wait for change,challenge Survive.
happy for hardess to solve denpendies.

目录

在这里插入图片描述

概述

org.activiti.bpmn是一个非常常见的需求。

需求:

设计思路

实现思路分析

1.BpmnAutoLayout

 private static final String STYLE_EVENT = "styleEvent";
  private static final String STYLE_GATEWAY = "styleGateway";
  private static final String STYLE_SEQUENCEFLOW = "styleSequenceFlow";
  private static final String STYLE_BOUNDARY_SEQUENCEFLOW = "styleBoundarySequenceFlow";

  protected BpmnModel bpmnModel;

  protected int eventSize = 30;
  protected int gatewaySize = 40;
  protected int taskWidth = 100;
  protected int taskHeight = 60;
  protected int subProcessMargin = 20;

  protected mxGraph graph;
  protected Object cellParent;
  protected Map<String, Association> associations;
  protected Map<String, TextAnnotation> textAnnotations;

  protected Map<String, SequenceFlow> sequenceFlows;
  protected List<BoundaryEvent> boundaryEvents;
  protected Map<String, FlowElement> handledFlowElements;

  protected Map<String, Artifact> handledArtifacts;

  protected Map<String, Object> generatedVertices;
  protected Map<String, Object> generatedSequenceFlowEdges;
  protected Map<String, Object> generatedAssociationEdges;

  public BpmnAutoLayout(BpmnModel bpmnModel) {
    this.bpmnModel = bpmnModel;
  }

  public void execute() {
    // Reset any previous DI information
    bpmnModel.getLocationMap().clear();
    bpmnModel.getFlowLocationMap().clear();

    // Generate DI for each process
    for (Process process : bpmnModel.getProcesses()) {
      layout(process);

      // Operations that can only be done after all elements have received
      // DI
      translateNestedSubprocesses(process);
    }
  }

  protected void layout(FlowElementsContainer flowElementsContainer) {
    graph = new mxGraph();
    cellParent = graph.getDefaultParent();
    graph.getModel().beginUpdate();

 // Subprocesses are handled in a new instance of BpmnAutoLayout, hence they instantiations of new maps here.

    handledFlowElements = new HashMap<String, FlowElement>();
    handledArtifacts = new HashMap<String, Artifact>();
    generatedVertices = new HashMap<String, Object>();
    generatedSequenceFlowEdges = new HashMap<String, Object>();
    generatedAssociationEdges = new HashMap<String, Object>();

    associations = new HashMap<String, Association>(); //Associations are gathered and processed afterwards, because we must be sure we already found source and target
    textAnnotations = new HashMap<String, TextAnnotation>(); // Text Annotations are gathered and processed afterwards, because we must be sure we already found the parent.

    sequenceFlows = new HashMap<String, SequenceFlow>(); // Sequence flow are gathered and processed afterwards,because we mustbe sure we already found source and target
    boundaryEvents = new ArrayList<BoundaryEvent>(); // Boundary events are gathered and processed afterwards, because we must be sure we have its parent

    // Process all elements
    for (FlowElement flowElement : flowElementsContainer.getFlowElements()) {

      if (flowElement instanceof SequenceFlow) {
        handleSequenceFlow((SequenceFlow) flowElement);
      } else if (flowElement instanceof Event) {
        handleEvent(flowElement);
      } else if (flowElement instanceof Gateway) {
        createGatewayVertex(flowElement);
      } else if (flowElement instanceof Task || flowElement instanceof CallActivity) {
        handleActivity(flowElement);
      } else if (flowElement instanceof SubProcess) {
        handleSubProcess(flowElement);
      }

      handledFlowElements.put(flowElement.getId(), flowElement);
    }

    // process artifacts
    for (Artifact artifact : flowElementsContainer.getArtifacts()) {

      if (artifact instanceof Association) {
        handleAssociation((Association) artifact);
      } else if (artifact instanceof TextAnnotation) {
        handleTextAnnotation((TextAnnotation) artifact);
      }

      handledArtifacts.put(artifact.getId(), artifact);
    }

    // Process gathered elements
    handleBoundaryEvents();
    handleSequenceFlow();
    handleAssociations();

    // All elements are now put in the graph. Let's layout them!
    CustomLayout layout = new CustomLayout(graph, SwingConstants.WEST);
    layout.setIntraCellSpacing(100.0);
    layout.setResizeParent(true);
    layout.setFineTuning(true);
    layout.setParentBorder(20);
    layout.setMoveParent(true);
    layout.setDisableEdgeStyle(false);
    layout.setUseBoundingBox(true);
    layout.execute(graph.getDefaultParent());

    graph.getModel().endUpdate();

    generateDiagramInterchangeElements();
  }

  private void handleTextAnnotation(TextAnnotation artifact) {
    ensureArtifactIdSet(artifact);
    textAnnotations.put(artifact.getId(), artifact);
  }

  // BPMN element handling

  protected void ensureSequenceFlowIdSet(SequenceFlow sequenceFlow) {
    // We really must have ids for sequence flow to be able to generate
    // stuff
    if (sequenceFlow.getId() == null) {
      sequenceFlow.setId("sequenceFlow-" + UUID.randomUUID().toString());
    }
  }

  protected void ensureArtifactIdSet(Artifact artifact) {
    // We really must have ids for sequence flow to be able to generate stuff
    if (artifact.getId() == null) {
      artifact.setId("artifact-" + UUID.randomUUID().toString());
    }
  }

  protected void handleAssociation(Association association) {
    ensureArtifactIdSet(association);
    associations.put(association.getId(), association);
  }

  protected void handleSequenceFlow(SequenceFlow sequenceFlow) {
    ensureSequenceFlowIdSet(sequenceFlow);
    sequenceFlows.put(sequenceFlow.getId(), sequenceFlow);
  }

  protected void handleEvent(FlowElement flowElement) {
    // Boundary events are an exception to the general way of drawing an
    // event
    if (flowElement instanceof BoundaryEvent) {
      boundaryEvents.add((BoundaryEvent) flowElement);
    } else {
      createEventVertex(flowElement);
    }
  }

  protected void handleActivity(FlowElement flowElement) {
    Object activityVertex = graph.insertVertex(cellParent, flowElement.getId(), "", 0, 0, taskWidth, taskHeight);
    generatedVertices.put(flowElement.getId(), activityVertex);
  }

  protected void handleSubProcess(FlowElement flowElement) {
    BpmnAutoLayout bpmnAutoLayout = new BpmnAutoLayout(bpmnModel);
    bpmnAutoLayout.layout((SubProcess) flowElement);

在这里插入图片描述在这里插入图片描述

2.BPMNLayout

public class BPMNLayout extends mxGraphLayout {

  // NEW

  protected BpmnAutoLayout bpmnAutoLayout;

  public void setBpmnAutoLayout(BpmnAutoLayout bpmnAutoLayout) {
    this.bpmnAutoLayout = bpmnAutoLayout;
  }

  // NEW

  /**
   * Specifies the orientation of the layout. Default is true.
   */
  protected boolean horizontal;

  /**
   * Specifies if edge directions should be inverted. Default is false.
   */
  protected boolean invert;

  /**
   * If the parent should be resized to match the width/height of the tree. Default is true.
   */
  protected boolean resizeParent = true;

  /**
   * Specifies if the tree should be moved to the top, left corner if it is inside a top-level layer. Default is true.
   */
  protected boolean moveTree = true;

  /**
   * Specifies if all edge points of traversed edges should be removed. Default is true.
   */
  protected boolean resetEdges = true;

  /**
   * Holds the levelDistance. Default is 40.
   */
  protected int levelDistance = 40;

  /**
   * Holds the nodeDistance. Default is 20.
   */
  protected int nodeDistance = 20;

  /**
   *
   * @param graph
   */
  public BPMNLayout(mxGraph graph) {
    this(graph, true);
  }

  /**
   *
   * @param graph
   * @param horizontal
   */
  public BPMNLayout(mxGraph graph, boolean horizontal) {
    this(graph, horizontal, false);
  }

  /**
   *
   * @param graph
   * @param horizontal
   * @param invert
   */
  public BPMNLayout(mxGraph graph, boolean horizontal, boolean invert) {
    super(graph);
    setUseBoundingBox(false);
    this.horizontal = horizontal;
    this.invert = invert;
  }

  public mxGraph getGraph() {
    return (mxGraph) graph;
  }

  /**
   * Returns a boolean indicating if the given <em>mxCell</em> should be ignored as a vertex. This returns true if the cell has no connections.
   *
   * @param vertex
   *          Object that represents the vertex to be tested.
   * @return Returns true if the vertex should be ignored.
   */
  public boolean isVertexIgnored(Object vertex) {
    return super.isVertexIgnored(vertex) || graph.isSwimlane(vertex) || graph.getModel().getGeometry(vertex).isRelative() || graph.getConnections(vertex).length == 0;
  }

  /**
   * @return the horizontal
   */
  public boolean isHorizontal() {
    return horizontal;
  }

  /**
   * @param horizontal
   *          the horizontal to set
   */
  public void setHorizontal(boolean horizontal) {
    this.horizontal = horizontal;
  }

  /**
   * @return the invert
   */
  public boolean isInvert() {
    return invert;
  }

  /**
   * @param invert
   *          the invert to set
   */
  public void setInvert(boolean invert) {
    this.invert = invert;
  }

  /**
   * @return the resizeParent
   */
  public boolean isResizeParent() {
    return resizeParent;
  }

  /**
   * @param resizeParent
   *          the resizeParent to set
   */
  public void setResizeParent(boolean resizeParent) {
    this.resizeParent = resizeParent;
  }

  /**
   * @return the moveTree
   */
  public boolean isMoveTree() {
    return moveTree;
  }

  /**
   * @param moveTree
   *          the moveTree to set
   */
  public void setMoveTree(boolean moveTree) {
    this.moveTree = moveTree;
  }

  /**
   * @return the resetEdges
   */
  public boolean isResetEdges() {
    return resetEdges;
  }

  /**
   * @param resetEdges
   *          the resetEdges to set
   */
  public void setResetEdges(boolean resetEdges) {
    this.resetEdges = resetEdges;
  }

  /**
   * @return the levelDistance
   */
  public int getLevelDistance() {
    return levelDistance;
  }

  /**
   * @param levelDistance
   *          the levelDistance to set
   */
  public void setLevelDistance(int levelDistance) {
    this.levelDistance = levelDistance;
  }

  /**
   * @return the nodeDistance
   */
  public int getNodeDistance() {
    return nodeDistance;
  }

  /**
   * @param nodeDistance
   *          the nodeDistance to set
   */
  public void setNodeDistance(int nodeDistance) {
    this.nodeDistance = nodeDistance;
  }

  public void execute(Object parent) {
    mxIGraphModel model = graph.getModel();
    List<Object> roots = graph.findTreeRoots(parent, true, invert);
    // if (getGraph().isOrganizationElement(parent)) {
    // roots = asList(graph.getSelectionCells());
    // }
    for (Object root : roots) {
      parent = model.getParent(root);

      if (isBoundaryEvent(root)) {
        parent = model.getParent(parent);
      }
      model.beginUpdate();

      try {
        TreeNode node = dfs(root, parent, null);

        if (node != null) {
          layout(node);

          double x0 = graph.getGridSize();
          double y0 = x0;

          if (!moveTree || parent == graph.getDefaultParent() || parent == graph.getCurrentRoot()) {
            mxGeometry g = model.getGeometry(root);
            if (g.isRelative()) {
              g = model.getGeometry(model.getParent(root));
            }
            if (g != null) {
              x0 = g.getX();
              y0 = g.getY();
            }
          }

          mxRectangle bounds = null;

          if (horizontal) {
            bounds = horizontalLayout(node, x0, y0, null);
          } else {
            bounds = verticalLayout(node, null, x0, y0, null);
          }

          if (bounds != null) {
            double dx = 0;
            double dy = 0;

            if (bounds.getX() < 0) {
              dx = Math.abs(x0 - bounds.getX());
            }

            if (bounds.getY() < 0) {
              dy = Math.abs(y0 - bounds.getY());
            }

            if (parent != null) {
              mxRectangle size = graph.getStartSize(parent);
              dx += size.getWidth();
              dy += size.getHeight();

              // Resize parent swimlane
              if (resizeParent && !graph.isCellCollapsed(parent)) {
                mxGeometry g = model.getGeometry(parent);

                if (g != null) {
                  double width = bounds.getWidth() + size.getWidth() - bounds.getX() + 2 * x0;
                  double height = bounds.getHeight() + size.getHeight() - bounds.getY() + 2 * y0;

                  g = (mxGeometry) g.clone();

                  if (g.getWidth() > width) {
                    dx += (g.getWidth() - width) / 2;
                  } else {
                    g.setWidth(width);
                  }

                  if (g.getHeight() > height) {
                    if (horizontal) {
                      dy += (g.getHeight() - height) / 2;
                    }
                  } else {
                    g.setHeight(height);
                  }

                  model.setGeometry(parent, g);
                }
              }
            }
            if (model.getParent(node.cell) != graph.getCurrentRoot() && model.getParent(node.cell) != graph.getDefaultParent()) {
              moveNode(node, dx, dy);
            }
          }
        }
      } finally {
        model.endUpdate();
      }
    }
  }

  protected boolean isBoundaryEvent(Object obj) {
    if (obj instanceof mxCell) {
      mxCell cell = (mxCell) obj;
      return cell.getId().startsWith("boundary-event-");
    }
    return false;
  }

  /**
   * Moves the specified node and all of its children by the given amount.
   */
  protected void moveNode(TreeNode node, double dx, double dy) {
    node.x += dx;
    node.y += dy;
    apply(node, null);

    TreeNode child = node.child;

    while (child != null) {
      moveNode(child, dx, dy);
      child = child.next;
    }
  }

  /**
   * Does a depth first search starting at the specified cell. Makes sure the specified swimlane is never left by the algorithm.
   */
  protected TreeNode dfs(Object cell, Object parent, Set<Object> visited) {
    if (visited == null) {
      visited = new HashSet<Object>();
    }

    TreeNode node = null;

在这里插入图片描述

在这里插入图片描述

参考资料和推荐阅读

[1]. https://www.activiti.org/

欢迎阅读,各位老铁,如果对你有帮助,点个赞加个关注呗!~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/36664.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Mybatis概述

1 概述 原来是Apache的一个开源项目&#xff0c;叫iBatis, 2010年6月这个项目由 Apache Software Foundation 迁移到了 Google Code&#xff0c;随着开发团队转投Google Code 旗下&#xff0c;从 iBatis3.0正式更名为MyBatis。 MyBatis 是一款优秀的持久层框架&#xff0c;对j…

容器卷挂载的秘密

什么是容器卷 数据卷 &#xff08;Data Volumes &#xff09;是一个可供容器使用的特殊目录&#xff0c;它将主机操作系统目录直接映射进容器&#xff0c;类似于 Linux 中的 mount 行为。 容器挂载原理 containerd创建的容器里的数据存储在下面的目录中 [rootmaster01 httpb…

【C/C++】万字图文详解C语言文件操作 完美装饰课设大作业

目标导航 写在前面 为什么使用文件&#xff1f; 什么是文件&#xff1f; 程序文件 数据文件 认识文件名 文件的打开和关闭 文件指针 文件的打开和关闭 1.以"r"&#xff08;只读&#xff09;的方式打开文件 2.以"w"&#xff08;只写&#xff09;…

Java#24(常见API--2)

目录 一.Rantime Runtime表示当前虚拟机的运行环境 Runtime常用方法 扩展:对象克隆 二.Objects Objects是一个对象工具类,提供了一些操作对象的方法 一.Rantime Runtime表示当前虚拟机的运行环境 Runtime常用方法 方法名 作用 publi…

葡萄糖-聚乙二醇-链霉亲和素|Streptavidins-PEG-Glucose|链霉亲和素-PEG-葡萄糖

链霉亲和素(streptavidin下称SA)是与亲和素(avidin下称AV)是一种蛋白质&#xff0c;链霉亲和素是四聚体蛋白&#xff0c;大小为66KDa。一分子链霉亲和素可以高度特异性地与四分子生物素结合&#xff0c;两者之间的亲和力较为强烈。链霉亲和素分子由4条相同的肽链组成&#xff0…

delete-by-query和复合查询

根据term&#xff0c;match等查询方式去删除大量的文档 Ps&#xff1a;如果你需要删除的内容&#xff0c;是index下的大部分数据&#xff0c;推荐创建一个全新的index&#xff0c;将保留的文档内容&#xff0c;添加到全新的索引 # delete-by-query POST /sms-logs-index/sms-lo…

毕业设计-基于机器视觉的颜色目标识别

目录 前言 课题背景和意义 实现技术思路 什么是彩色空间 怎么利用彩色空间 颜色识别的过程 读取图片进行hsv色域转换 对图片特定颜色识别 本地摄像头对视频流进行颜色识别 实现效果图样例 前言 &#x1f4c5;大四是整个大学期间最忙碌的时光,一边要忙着备考或实习为毕业后…

Python基础-面向对象编程之特性(property)

Python面向对象编程之特性(property) 一、统一访问原则 通常&#xff0c;我们访问实例或类的属性时&#xff0c;将返回所存储的相关值。而特性&#xff08;property&#xff09;是一种特殊的属性&#xff0c;访问它时会计算它的值。 请看下面的例子&#xff1a; import mat…

基于android的个性闹铃的设计与开发(闹铃,日历,计时器,备忘录)

目 录 摘 要 2 Abstract 2 1 选题的背景和意义 5 1.1 选题的背景 5 1.2 国内外研究现状 5 1.2.1 国内外手机系统现状 5 1.2.2 国内外手机应用现状 7 1.2.3 发展趋势 7 2 需求分析 9 2.1 系统需求 9 2.2 需求分析 9 2.3 约束与限制 10 3 总体设计 11 3.1 系统结构图 11 3.2 总体…

【数论】约数

文章目录一、试除法求n的所有约数二、约数个数三、约数之和四、最大公约数&#xff08;欧几里得算法/辗转相除法&#xff09;一、试除法求n的所有约数 vector<int> getDivisors(int n) {vector<int> ans;for (int i 2; i < n / i; i) {if (n % i 0) {ans.pus…

深度学习Week8-咖啡豆识别(Pytorch)

目录 一、前期准备 1.设置GPU 2. 导入数据 3. 划分数据集 二、手动搭建VGG-16模型 1. 搭建模型​编辑 2. 查看模型详情 三、 训练模型 1. 编写训练函数 2. 编写测试函数 4. 正式训练 四、 结果可视化 1. Loss与Accuracy图 2. 指定图片进行预测 3. 模型评估 *五、优…

[附源码]java毕业设计中达小区物业管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

学生家乡网页设计作品静态HTML网页模板源码 广西旅游景点网页设计 大学生家乡主题网站制作 简单家乡介绍网页设计成品

家乡旅游景点网页作业制作 网页代码运用了DIV盒子的使用方法&#xff0c;如盒子的嵌套、浮动、margin、border、background等属性的使用&#xff0c;外部大盒子设定居中&#xff0c;内部左中右布局&#xff0c;下方横向浮动排列&#xff0c;大学学习的前端知识点和布局方式都有…

Packet Tracer - 配置 IPv4 和 IPv6 接口

地址分配表 设备 接口 IPv4 地址 子网掩码 默认网关 IPv6 地址/前缀 R1 G0/0 172.16.20.1 255.255.255.128 不适用 G0/1 172.16.20.129 255.255.255.128 不适用 S0/0/0 209.165.200.225 255.255.255.252 不适用 PC1 NIC 172.16.20.10 255.255.255.128 1…

微服务架构的环境搭建及简单测试

目录 一、系统架构的演变过程 1.0 前言 1.1 单体应用架构 1.2 垂直应用架构 1.3 分布式架构 1.4 SOA架构 1.5 微服务架构 二、微服务架构搭建 2.1 微服务架构简介 2.2 微服务案例准备 2.3 创建父工程、基础模块 2.4 创建微服务 一、系统架构的演变过程 1.0 前言 随着互联网的…

【Queue】- 从源码分析PriorityQueue及其常用方法

文章目录PriorityQueue基础知识概述PriorityQueue内部结构PriorityQueue扩容操作PriorityQueue队列的构造方法PriorityQueue队列的常用方法public boolean offer(E e)public E peek()public boolean remove(Object o)public boolean contains(Object o)public Object[] toArray…

【SU-03T离线语音模块】:学习配置使用

前言 时不可以苟遇&#xff0c;道不可以虚行。 一、介绍 1、什么是语音识别模块 语音识别模块是在一种基于嵌入式的语音识别技术的模块&#xff0c;主要包括语音识别芯片和一些其他的附属电路&#xff0c;能够方便的与主控芯片进行通讯&#xff0c;开发者可以方便的将该模块嵌…

Node.js 入门教程 3 如何安装 Node.js

Node.js 入门教程 Node.js官方入门教程 Node.js中文网 本文仅用于学习记录&#xff0c;不存在任何商业用途&#xff0c;如侵删 文章目录Node.js 入门教程3 如何安装 Node.js3 如何安装 Node.js Node.js 可以通过多种方式安装。 所有主流平台的官方软件包都可以在 http://node…

终于见识到了微服务的天花板:阿里内部SpringCloud全线手册,太强了

后台都是在问微服务架构的面试题怎么答&#xff0c;想聊聊微服务架构了。微服务架构一跃成为 IT 领域炙手可热的话题也就这两年的事&#xff0c;大量一线互联网公司因为庞大的业务体量和业务需求&#xff0c;纷纷投入了微服务架构的建设中&#xff0c;像阿里巴巴、百度、美团等…

226. 翻转二叉树

文章目录1.题目2.示例3.答案①递归②迭代1.题目 给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 2.示例 输入&#xff1a;root [4,2,7,1,3,6,9] 输出&#xff1a;[4,7,2,9,6,3,1]输入&#xff1a;root [4,2,7,1,3,6,9] 输出&#xf…