粗览Activiti Modeler操作和源代码

Activiti Model Editor组件

我的 了解ActivitiExplorer及其Vaadin实现方式博文里提到ActivitiExplorer使用的是Vaadin架构,但是Activiti 模型编辑器组件却没用使用Vaadin架构,而是采用Angular.JS的MVC模式。Activiti模型编辑器组件的客户端代码位于Activiti\modules\activiti-webapp-explorer2\src\main\webapp\editor-app\。

该目录下的editor.html是Activiti Modeler Editor的主界面HTML代码 
 
其中palette区是通过Angular.JS使用stencilsets\bpmn2.0\icons下多个子目录内的PNG图像形成的多组列表。其节点层次关系获取相关代码为:

  1. stencil-controller.js
  2. Activiti\modules\activiti-modeler\src\main\java\org\activiti\rest\editor\main\StencilsetRestResource.java
  3. Activiti\modules\activiti-webapp-explorer2\src\main\resources\stencilset.json

 
editor.html中的视图与两个控制器进行了绑定:

  • stencil-controller.js:处理对canvas中BPMN元素的操作,很多处理是通过editor目录下的QRYX库完成的
  • toolbar-controller.js:处理对工具栏的操作,很多处理由configuration\toolbar-default-actions.js完成

保存模型操作

保存模型操作,是通过toolbar-default-actions.js中的SaveModel方法完成的,它需要将三部分信息传给服务器:

  • 模型的元数据:例如模型名称、分类、创建时间、最后一次更新时间等等
  • 模型JSON数据:将canvas内的图像数据转换成JSON数据UTF8字符串
    {"resourceId": 53,"properties": {"process_id": "process","name": "","documentation": "","process_author": "","process_version": "","process_namespace": "http://www.activiti.org/processdef","executionlisteners": "","eventlisteners": ""},"stencil": {"id": "BPMNDiagram"},"childShapes": [{"resourceId": "sid-4F7484B9-11EC-4FCE-8950-FEFFB723D88B","properties": {"overrideid": "","name": "","documentation": "","executionlisteners": "","initiator": "","formkeydefinition": "","formproperties": ""},"stencil": {"id": "StartNoneEvent"},"childShapes": [],"outgoing": [{"resourceId": "sid-B589A0D9-FA79-4C12-95B7-253E72480384"}],"bounds": {"lowerRight": {"x": 259,"y": 139},"upperLeft": {"x": 229,"y": 109}},"dockers": []},{"resourceId": "sid-1A762474-62B9-4F3D-A81C-1ADD46AF7D2F","properties": {"overrideid": "","name": "","documentation": "","asynchronousdefinition": "false","exclusivedefinition": "false","executionlisteners": "","multiinstance_type": "None","multiinstance_cardinality": "","multiinstance_collection": "","multiinstance_variable": "","multiinstance_condition": "","isforcompensation": "false","usertaskassignment": "","formkeydefinition": "","duedatedefinition": "","prioritydefinition": "","formproperties": "","tasklisteners": ""},"stencil": {"id": "UserTask"},"childShapes": [],"outgoing": [{"resourceId": "sid-4134C10E-B589-42FF-AACC-463D35D52016"}],"bounds": {"lowerRight": {"x": 746,"y": 172},"upperLeft": {"x": 646,"y": 92}},"dockers": []},{"resourceId": "sid-B22A5CAB-94D0-419E-BB1E-E8538C6A7283","properties": {"overrideid": "","name": "","documentation": "","executionlisteners": ""},"stencil": {"id": "EndNoneEvent"},"childShapes": [],"outgoing": [],"bounds": {"lowerRight": {"x": 1089,"y": 138},"upperLeft": {"x": 1061,"y": 110}},"dockers": []},{"resourceId": "sid-B589A0D9-FA79-4C12-95B7-253E72480384","properties": {"overrideid": "","name": "","documentation": "","conditionsequenceflow": "","executionlisteners": "","defaultflow": "false"},"stencil": {"id": "SequenceFlow"},"childShapes": [],"outgoing": [{"resourceId": "sid-1A762474-62B9-4F3D-A81C-1ADD46AF7D2F"}],"bounds": {"lowerRight": {"x": 645.5626565925471,"y": 131.10730365650525},"upperLeft": {"x": 259.12484340745283,"y": 124.26769634349473}},"dockers": [{"x": 15,"y": 15},{"x": 50,"y": 40}],"target": {"resourceId": "sid-1A762474-62B9-4F3D-A81C-1ADD46AF7D2F"}},{"resourceId": "sid-4134C10E-B589-42FF-AACC-463D35D52016","properties": {"overrideid": "","name": "","documentation": "","conditionsequenceflow": "","executionlisteners": "","defaultflow": "false"},"stencil": {"id": "SequenceFlow"},"childShapes": [],"outgoing": [{"resourceId": "sid-B22A5CAB-94D0-419E-BB1E-E8538C6A7283"}],"bounds": {"lowerRight": {"x": 1060.676003953202,"y": 130.93202152143962},"upperLeft": {"x": 746.595480421798,"y": 124.30235347856038}},"dockers": [{"x": 50,"y": 40},{"x": 14,"y": 14}],"target": {"resourceId": "sid-B22A5CAB-94D0-419E-BB1E-E8538C6A7283"}}],"bounds": {"lowerRight": {"x": 1200,"y": 1050},"upperLeft": {"x": 0,"y": 0}},"stencilset": {"url": "stencilsets/bpmn2.0/bpmn2.0.json","namespace": "http://b3mn.org/stencilset/bpmn2.0#"},"ssextensions": []}
  • 模型的SVG图像数据:将canvas中的SVG图像数据经过过滤处理而得

服务器侧保存模型的代码位于Activiti\modules\activiti-modeler\src\main\java\org\activiti\rest\editor\model\ModelSaveRestResource.java。

  • 通过RepositoryService的saveModel方法将模型的元数据存入数据库的ACT_RE_MODEL表
  • 通过RepositoryService的addModelEditorSource方法将模型JSON数据UTF8字符串存入数据库的ACT_GE_BYTEARRAY表
  • 通过Apache™ BatikSVGToolkit将模型的SVG图像数据转换成PNG格式,通过RepositoryService的addModelEditorSourceExtra方法将PNG图像存入数据库的ACT_GE_BYTEARRAY表

Activiti Explorer操作已保存模型

对模型的编辑操作是在Activiti Model Editor组件里实现的,对已保存模型的其他操作还是在ActivitiExplorer里基于Vaadin架构实现的。 
客户端代码位于:Activiti\modules\activiti-explorer\src\main\java\org\activiti\editor\ui\。 
下图的HTML界面由EditorProcessDefinitionDetailPanel.java实现。 

显示已保存模型

  1. 选择模型,会调用EditorProcessDefinitionPage类的showProcessDefinitionDetail方法
  2. EditorProcessDefinitionDetailPanel类的initUI方法调用initProcessDefinitionInfo方法,它会加入EditorProcessDefinitionInfoComponent实例
  3. 在构造EditorProcessDefinitionInfoComponent实例时,其initImage方法会被调用,通过RepositoryService的getModelEditorSourceExtra方法获得PNG格式图像,最终被显示到浏览器界面上。

部署已保存模型

EditorProcessDefinitionDetailPanel类的deployModel方法处理部署已保存模型的操作。

  1. 通过RepositoryService的getModelEditorSource方法获得模型JSON数据的UTF8字符串
  2. 通过FasterXML/jackson-databind转换成Java对象树
  3. 通过Activiti\modules\activiti-json-converter\src\main\java\org\activiti\editor\language\json\converter\BpmnJsonConverter.java将模型JSON数据的Java对象树转换成BpmnModel实例
  4. 通过Activiti\modules\activiti-bpmn-converter\src\main\java\org\activiti\bpmn\converter\BpmnXMLConverter.java将BpmnModel实例转成BPMN XML数据
  5. 通过RepositoryService的createDeployment方法将BPMN XML数据进行部署

导出已保存模型

EditorProcessDefinitionDetailPanel类的exportModel方法处理导出已保存模型的操作。

  1. 通过RepositoryService的getModelEditorSource方法获得模型数据的JSON字符串
  2. 通过FasterXML/jackson-databind转换成Java对象树
  3. 通过Activiti\modules\activiti-json-converter\src\main\java\org\activiti\editor\language\json\converter\BpmnJsonConverter.java将模型JSON数据的Java对象树转换成BpmnModel实例
  4. 通过Activiti\modules\activiti-bpmn-converter\src\main\java\org\activiti\bpmn\converter\BpmnXMLConverter.java将BpmnModel实例转成BPMN XML数据

编辑已保存模型

EditorProcessDefinitionDetailPanel类内注册了EditModelClickListener监听器用于处理导入BPMN模型操作。 
EditModelClickListener的showModeler会生成访问模型编辑器组件的URL地址,打开指定的模型。

  1. Activiti\modules\activiti-webapp-explorer2\src\main\webapp\editor-app\app.js中的监听器处理$includeContentLoaded事件,调用了fetchModel方法
  2. Activiti\modules\activiti-modeler\src\main\java\org\activiti\rest\editor\model\ModelEditorJsonRestResource.java处理该REST请求,返回由RepositoryService的getModel和getModelEditorSource方法获得Activiti模型元数据和JSON数据

导入BPMN模型

EditorProcessDefinitionDetailPanel类内注册了ImportModelClickListener监听器用于处理导入BPMN模型操作。 
ImportPopupWindow界面完成BPMN模型操作后,ImportUploadReceiver类的deployUploadedFile方法处理上传的BPMNXML数据。

  1. 通过Activiti\modules\activiti-bpmn-converter\src\main\java\org\activiti\bpmn\converter\BpmnXMLConverter.java将BPMN XML数据转换成BpmnModel实例
  2. 通过BpmnModel实例生成模型的元数据,通过RepositoryService的saveModel方法将模型的元数据存入数据库的ACT_RE_MODEL表
  3. 通过Activiti\modules\activiti-json-converter\src\main\java\org\activiti\editor\language\json\converter\BpmnJsonConverter.java将BpmnModel实例转换成模型JSON数据的Java对象树,通过RepositoryService的addModelEditorSource方法将模型JSON数据UTF8字符串存入数据库的ACT_GE_BYTEARRAY表

一些疑惑和想法:

    • 这里BpmnXMLConverter和BpmnJsonConverter用的比较频繁,而且成对出现。为什么不跳过中间的BpmnModel?
    • 导入BPMN模型为什么不生成PNG图像?
    • 数据库存储的模型数据不采用BPMNXML格式而是采用JSON格式,很灵活,可以随意添加Activiti扩展内容。但是如果没有现成的JSONschema,分析起来够麻烦。
时间: 2025-01-15 12:27:18

粗览Activiti Modeler操作和源代码的相关文章

基于Metronic的Bootstrap开发框架经验总结(9)--实现Web页面内容的打印预览和保存操作

在前面介绍了很多篇相关的<Bootstrap开发框架>的系列文章,这些内容基本上覆盖到了我这个Bootstrap框架的各个主要方面的内容,总体来说基本达到了一个稳定的状态,随着时间的推移可以会引入一些更好更新的内容进行完善,本篇继续这个系列,主要介绍如何实现Web页面内容的打印预览和保存操作. 1.Web页面打印的问题 在此之前,我一般使用比较好用的LODOP来执行打印的操作,这个在我之前有很多文章都有涉及,这个控件是一个ActiveX的控件,需要下载安装后就可以在页面是进行打印的排版设计,预

集成新版(5.17+)Activiti Modeler与Rest服务

声明: 此教程适合Activiti 5.17+版本. 本博客所涉及的内容均可在kft-activiti-demo中找到. 在线demo可以访问 http://demo.kafeitu.me:8080/kft-activiti-demo 菜单路径:管理模块 -> 流程管理 -> 模型工作区,可以『创建』或者『编辑』模型 1. 简介 上一篇介绍整合Activiti Modeler<整合Activiti Modeler到业务系统(或BPM平台)>已经有2年多时间了,自从Activiti

C#操作PowerDesigner代码

首先,程序的界面如下: 这里一定要使用OpenFileDialog控件,然后该页面代码如下: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Xml; namespace DBDesign {

[转]计算机视觉、机器学习相关领域论文和源代码大集合

计算机视觉.机器学习相关领域论文和源代码大集合--持续更新…… [email protected] http://blog.csdn.net/zouxy09 注:下面有project网站的大部分都有paper和相应的code.Code一般是C/C++或者Matlab代码. 最近一次更新:2013-3-17 一.特征提取Feature Extraction: ·         SIFT [1] [Demo program][SIFT Library] [VLFeat] ·         PCA

android中RadioGroup、RadioButton、Spinner、EditText用法详解(含示例截图和源代码)

为了保护版权.尊重原创,转载请注明出处:http://blog.csdn.net/u013149325/article/details/43237757,谢谢! 今天在项目中用到了android中常用的RadioGroup.RadioButton.Spinner.EditText等控件,在此介绍一下它们的用法,希望对需要的朋友有帮助. 一.RadioGroup和RadioButton的使用 RadioButton就是我们常见的单选按钮,一个RadioGroup可以包含多个单选按钮,但是每次只能选

PHP日期操作类代码-农历-阳历转换、闰年、计算天数等

这是一个实用的PHP日期时间操作类,里面包括了公历-农历转换.转换成中文日期格式.计算农历相隔天数.根据阴历年获取生肖.获取阴历月份的天数.获取农历每年的天数.获取闰月.计算阴历日期与正月初一相隔的天数.计算2个公历(阳历)日期之间的天数.根据距离正月初一的天数计算阴历日期.获取天干地支纪年等,PHP日期操作类:Lunar.class.php代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27

数据结构-线性表的一些基础操作 c++代码

//线性表的顺序存储结构 template <class T> class Linearlist { public: Linearlist(int MaxListSize == 10); ~Linearlist() { delete []element; } bool IsEmpty() const { return length == 0; } bool IsFull() const { return length == MaxSize; } int Length() const { ret

android widget 开发实例 : 桌面便签程序的实现具体解释和源代码 (上)

如有错漏请不吝拍砖指正,转载请注明出处,很感谢 桌面便签软件是android上经常使用软件的一种,比方比較早的Sticky Note,就曾很流行, Sticky Note的介绍能够參见 http://www.tompda.com/c/article/11778/ 而实际上使用android平台对widget开发的支持,桌面便签类软件是很易于开发的. 本文通过逐步实现一个简单的桌面便签软件,和大家分享进行widget开发的过程和方法. 1.MyNote的终于实现效果 为了提起大家阅读本文的兴趣,先

EasyUI中datagrid实现显示、增加、 删除、 修改、 查询操作(后台代码C#)

2datagrid加载数据.代码如下所示 一.数据的显示 1新建HtmlPage2.html页面,引入相关文件.如下所示 <script src="easyui/js/jquery-1.8.2.min.js"></script>  <script src="easyui/js/jquery.easyui.min.js"></script>  <link href="easyui/css/themes/d