org.activiti.bpmn
创始人
2024-02-16 08:38:12

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 associations;protected Map textAnnotations;protected Map sequenceFlows;protected List boundaryEvents;protected Map handledFlowElements;protected Map handledArtifacts;protected Map generatedVertices;protected Map generatedSequenceFlowEdges;protected Map generatedAssociationEdges;public BpmnAutoLayout(BpmnModel bpmnModel) {this.bpmnModel = bpmnModel;}public void execute() {// Reset any previous DI informationbpmnModel.getLocationMap().clear();bpmnModel.getFlowLocationMap().clear();// Generate DI for each processfor (Process process : bpmnModel.getProcesses()) {layout(process);// Operations that can only be done after all elements have received// DItranslateNestedSubprocesses(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();handledArtifacts = new HashMap();generatedVertices = new HashMap();generatedSequenceFlowEdges = new HashMap();generatedAssociationEdges = new HashMap();associations = new HashMap(); //Associations are gathered and processed afterwards, because we must be sure we already found source and targettextAnnotations = new HashMap(); // Text Annotations are gathered and processed afterwards, because we must be sure we already found the parent.sequenceFlows = new HashMap(); // Sequence flow are gathered and processed afterwards,because we mustbe sure we already found source and targetboundaryEvents = new ArrayList(); // Boundary events are gathered and processed afterwards, because we must be sure we have its parent// Process all elementsfor (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 artifactsfor (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 elementshandleBoundaryEvents();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 handlingprotected void ensureSequenceFlowIdSet(SequenceFlow sequenceFlow) {// We really must have ids for sequence flow to be able to generate// stuffif (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 stuffif (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// eventif (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 {// NEWprotected 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 mxCell 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 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 swimlaneif (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 visited) {if (visited == null) {visited = new HashSet();}TreeNode node = null; 

在这里插入图片描述

在这里插入图片描述

参考资料和推荐阅读

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

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

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...