现在的位置: 首页 > 综合 > 正文

[原创]JWFDv0.96工作流引擎设计-自动运行控制器结构说明

2013年01月23日 ⁄ 综合 ⁄ 共 8504字 ⁄ 字号 评论关闭

       

           JWFDv0.96---工作流引擎设计

               

                              --自动运行控制器结构说明

 


 

 

注:这篇文章中所使用的“函数”就是指JAVA语言中的方法

 

作者 comsci   2010.12.12   四川。成都

 

 

 

 

总体设计思路

 

 

  通过建立JWFD开源工作流系统自定义的流程拓扑数学模型,并在此模型的基础上面构建一系列的SQL-API原子操作函数,同时结合图形广度优先遍历算法的变异体,构建出一个流程自动运行控制器


 

  用户对一个流程实例的操控均建立在这个自动运行控制器的基础上面,至于客户端,呵呵,各位朋友就自己实现吧,越俎代庖的事情我就不做了,开源项目要避免和商业产品形成竞争,毕竟这个行业的整体发展主要要靠广大的商业软件企业,JWFD和comsci仅仅是一个衬托,呵呵

 

 

 

 

 

实现的技术与方法

 

 

蓝色字体标注的函数均为JWFD自定义的流程基础操作函数,这些函数的详细说明请参考

 

 

JWFDv0.96 工作流系统开发包简易说明.doc

 

JWFDv0.96 工作流引擎设计-数据库结构说明.doc

 

JWFDv0.96 流程XML结构说明.doc

 

 

 

这个算法中使用的原子操作函数,均是JWFD对流程拓扑结构进行数据库建模之后,在这个模型基础上形成的基础操作函数,关于这些函数的详细说明和数据库结构说明请参考JWFD开发API简易说明JWFD工作流引擎数据库结构说明文档,下载地址 在 http://www.cnblogs.com/comsci/favorite/260690.html


 

 

 

 下面我们就来分析这个运行控制器的结构,并试图划分出几个主要的功能模块,然后对此进行理解和再构造,在这之前,需要先回顾一下JWFDV0.94引擎的DFS自动运行控制器的算法结构,事实上DFS是一个全自动的运行控制器,而SAN是一个半自动的控制器,所谓全自动既指流程在运行过程中的流转过程全部由计算机通过DFS算法来控制,中间不需要人为地干预,而半自动的意思是流程在流转过程中,需要通过节点操作者的触发来推动流程的流转,但是SAN算法却在并行控制和条件会签,单步回退这些功能上面均实现了自动化的处理,所有这些复杂的逻辑判断均不需要人工来处理,所以这里的自动化是指流程的流转的控制是由机器来控制还是由人和机器共同控制,但是要真正做到全自动化流程控制,引擎系统就需要采用人工智能的模型,目前我们的技术水平还没有达到这个程度,但是这是我们努力的方向,争取JWFD能够在1.0版本的时候使用人工智能技术设计流程引擎

 

 

SAN算法的前身是Jwfd v0.94版本的运行控制器 DFS算法,该算法所在的类模块是JWFDv0.94代码包org.jwfd.workflowEngines.GXLFlowControlModule.java  这个DFS算法的结构大体如下,

为方便理解SAN算法,我把DFS算法的结构也写出来

 

 

----------------------------DFS伪码算法------------------------------- 


     for(int i =0  i <  当前节点的邻接点个数){

 

        if (该点是个前驱路由点) {

            if (该点没有被访问过) {

                  设置访问次数加(从递归方法中获得的循环控制变量)

                  返回

              }

            else if( 如果已经访问过,但是访问次数<它的前驱节点总数){

                   设置访问次数加(从递归方法中获得的循环控制变量+1)

                   返回

              }

            else if(总计访问次数=它的前驱节点总数){

               递归进入下一个节点的访问(把大循环体的,循环变量带进去递归方法中)

              }

 

              }

            else if(如果是普通节点){

               设置访问标志

               递归进入下一个节点的访问(把大循环体的,循环变量带进去递归方法中)

              }

              }

       }

 

 ---------------------------------------------------------------------------------------------

 

需要注意的是,这个DFS控制器算法的主要模块均是通过条件判断来划分的,因此这种结构和规则引擎的设计思路有些类似,可以说是规则引擎的简化实现,一个流程引擎的运行控制器可以依赖规则引擎来构建,但是如果朋友们愿意自己动手DIY,那么用最底层的JAVA语言来构建一个运行控制器,将大大有利于今后的长远发展。。。。 


 

DFS算法的模块主要是由节点的属性-是否是汇聚或者普通节点来划分,而SAN算法则是由节点的处理状态来划分的

 

 

SAN基础架构仍然采用图论中的广度优先算法的变异结构,但是这个版本中增加了引擎自动对流程的条件汇聚的判断和处理,增加了自动并行分支和节点单步回退的功能模块,所以这个算法的语句要比DFS算法语句多出一倍,但是整体的逻辑结构基本上还是可以划分为三个主要的状态判断和处理逻辑单元,第一个单元式当前节点的未处理状态,第二个单元是当前节点的正在处理的状态,第三个单元式当前节点的处理完毕的状态,下面的代码解释中,用红色的字体划分了这三个主要的单元部分

 

 

这个运行控制器的整个结构大体如下伪码所表示的,一个FOR循环体内部嵌入三个IF判断体,每个判断中包括若干个对应的处理模块和一个递归模块,其中递归模块是用来推动流程向前流转的动力源,由于这个版本中加入了回退处理和条件汇聚的处理模块,所以判断处理单元的结构相对DFS算法要复杂一些,请对比v0.94DFS算法结构,这样更加便于读者理解JWFD流程自动运行控制器的设计思路,并由此设计出自己的引擎控制模块

 

 

----------------------------------------------SAN伪码描述----------------------------------------------------- 


 

FOR循环体(循环控制变量为存储节点的链表容量)

 

IF  当前节点尚未处理

    嵌入处理过程

    递归前进  

 

ELSE IF 当前节点处理完毕

    嵌入处理过程

    递归前进

 

ELSE IF 当前节点正在处理    

    嵌入处理过程

    递归前进

 

 

---------------------------------------------------------------------------------------------------

 

   下面是SAN自动控制器代码的说明,如果朋友们懒得看这些代码,可以直接打开JWFDv0.96 for Eclipse的代码,直接运行这个SAN

函数(具体位置在org.jwfd.workflowEngines.Algorithm.TopologyAnalysis.java),只需要按照下面的提示进行操作,就可以简略的体会一下运行一个流程实例的过程

 

 * 1: 使用流程设计器画出流程
 * 2: 将流程图导入到数据库中(默认MYSQL)
 * 3: 使用数据库管理工具查看流程数据是否正确导入
 * 4: 参考数据库设计文档,了解数据库结构
 * 5: 把流程实例名导入下面的方法中
 * 6: 启动流程调试函数action()

 

如果大家需要深入的学习和了解这个运行控制器的结构,那抽空看看代码和说明,相信会有所感悟

 

 SAN算法具体的实现代码如下,每行均带有详细的说明 

 

 ------------------------------------------------算法开始-----------------------------------------------------


 

 public void SAN (java.util.ArrayList ln, String graphid,String prestep) {   

 

 

SAN函数的三个参数分别是:存储当前流程节点的链表ln,当前流程图实例id-graphid, 当前流程节点的前驱节prestep

  

 java.util.ArrayList lln = new java.util.ArrayList() ;   新创建一个流程节点链表存储

if (!ln.isEmpty()) {      

 

 

  这句的含义是判断当前节点变量链表存储器是否为空 ,ln链表数据是从SAN函数中传递过来的,该链表用于存储正在处于待处理的流程节点

 

 

 

      for (int i = 0; i < ln.size(); i++) {   

      这一句是用一个FOR循环作为流程引擎的串行和并行处理的关键控制语句这个循环贯穿整个运行控制器算法

      控制条件ln.size()中存储的是当前需要处理的流程所有节点,SAN算法是按需读取节点数据,引擎每走一步

      就读取流程图中一组的节点,为什么需要用一个数组来作为控制条件呢?因为流程图下一步中的节点不只一个

      而是会出现单个节点或者多个节点,而多个节点同时作为控制条件的情况是用来处理下一步处理过程中需要面对

      分支并行处理的情况下,这个ln.size()数组中就会出现多个并行的节点,而这些节点需要被客户端同步被处理, 

 

      正因为需要同时同步的被处理,所以客户端在这个时候就会同时弹出几个节点的处理窗口,这同实际情况是一致的

 

 

-----------------------------------------------------------------------------------------------------


下面这个if判断是整个运行控制器的三个关键判断单元的第一个,这个判断和判断体的处理部分是判断当前流程节点是否处于尚未处理的状态,然后根据这个判断来进行一系列的处理


-----------------------------------------------------------------------------------------------------

 

      if (stm.is_notactived_steps(ln.get(i).toString(), graphid)) {  

 

 

这句的含义是判断当前流程节点是否处于尚未处理的状态,以此作为是否进入下一步流程节点操作环节的               依据,这个判断和判断体的处理过程是整个运行控制器算法的第一个关键部分

         

       ftc.set_startup_time(ln.get(i).toString(), graphid);   

这句是时间设置函数,用于设置当前节点的初始操作时间点,该时间参数可以作为引擎系统对流程进行统计的时间控制参数和依据

 

 

       stm.set_active_step(ln.get(i).toString(), graphid);   

这句的含义是将节点设置为正在活动状态,既激活当前节点,使之成为待处理节点     

     

      stm.set_visited_times(ln.get(i).toString(),graphid,stm.get_visited_times(ln.get(i).toString(), graphid) +1);这句的含义是设置节点的被流程引擎访问的次数(取节点表中的访问次数值+1)

         

        

          if (stm.is_actived_steps(ln.get(i).toString(), graphid)) {  

            上面这句用于判断当前节点是否已经被处理

           

            System.out.println(ln.get(i).toString() + "调用客户端");

 

        上面这句是个屏幕显示输出,用于流程调试的时候使用

 

 

 

            this.action_step(ln,ln.get(i).toString(),graphid,prestep,this);  

 

这一句用来调用节点处理界面,用户在该界面中对节点进行操作,该节点对应的后台数据库的状态值就发生变化..action_step()函数是一个SWING的简易流程运行处理界面

           }

 

         }

 


 

----------------------------------------------------------------------------------------------------------------

 

下面这个if判断是整个运行控制器的三个关键判断单元的第二个,这个判断和判断体的处理部分是判断当前流程节点是否处于已经处理完毕的状态,然后根据这个判断来进行一系列的处理

----------------------------------------------------------------------------------------------------------------

 

 

           else if (stm.is_overactived_steps(ln.get(i).toString(), graphid)) { 

  这一句用于判断节点是否已经是处理完成的状态,这个判断和判断体的处理过程是整个运行控制器算法的第二个关键部分

 

    

           if (stm.return_preSteps(graphid, ln.get(i).toString()).size() > 1) {

                      上面这句用于判断当前节点是否是汇聚节点

 

       

            if (join_less(ln.get(i).toString(), graphid)) {     

这里是个重要的汇聚处理过程,判断汇聚点的汇聚次数是否小于已处理的次数,以此作为流程流程到下一节点的依据join_less()函数的结构,请参考JWFD流程运行控制器API说明


 

            if(prestep.equals(ln.get(i).toString())){     

 这句表示这个地方增加个控制条件,如果前驱与当前点一致,那么就意味着引擎对该节点重复访问了,需要进行阻塞控制

               

                 System.out.println(ln.get(i).toString() + "空操作");   

             上面这句是个屏幕显示输出,用于流程调试的时候使用

 

                  这个IF控制体是输出空操作---用于防止汇聚点自循环访问

                    

               }else{


 

        System.out.println(ln.get(i).toString() + "汇聚点再次调用客户端");

    上面这句是个屏幕显示输出,用于流程调试的时候使用


 

        下面这句表示将汇聚点作为当期节点参数送入节点处理界面进行处理

        run_action(ln,ln.get(i).toString(),graphid,prestep,this);       

                }

            }

 


 

---------------------------------------------------------------------------------------------------------------------- 

下面这个if判断是整个运行控制器的三个关键判断单元的第三个,这个判断和判断体的处理部分是判断当前流程节点是否处于正在处理状态,然后根据这个判断来进行一系列的处理

---------------------------------------------------------------------------------------------------------------------- 

        

 

   else  if (stm.is_actived_steps(ln.get(i).toString(), graphid)) {  

判断当前流程节点是否处于正在处理状态,这个判断和判断体的处理过程是整个运行控制器算法的第三个

关键部分is_actived_steps()函数的操作在

org.jwfd.workflowDesigner.UItools.Database.mysql.FlowsSqlControlModule.java类的695行的详细说明

 

                                                                                     

 

        判断当前节点的是否是汇聚节点

        if (stm.return_preSteps(graphid, ln.get(i).toString()).size() > 1) {  

        

        如果汇聚的次数和处理的次数相等,那么执行一次空处理                    

           if (join_equals(ln.get(i).toString(), graphid)) {  

           

              System.out.println("空控制体");

          这句是屏幕显示输出,用于流程调试的时候使用

 

             }

 

             else if(join_less(ln.get(i).toString(), graphid))    

             如果处理次数少于汇聚次数,则引擎需要再次对流程的汇聚进行处理,然后才能进入递归调用

             {

             System.out.println(ln.get(i).toString() + "汇聚点再次处理");

         上面这句是个屏幕显示输出,用于流程调试的时候使用


 

            run_action(ln,ln.get(i).toString(),graphid,prestep,this);

             这句的意思前面已经介绍过,既是再次调用流程节点处理客户端

 

            }

          }

        }

      }

    }

 

  }

 

 

-------------SAN算法结束------------

 

可以这样认为,这个SAN算法是JWFD流程系统的一个核心部分,正是由于有这个算法的存在,才使得JWFD和其它的流程系统不太一样,JWFD可以轻易的部署到最终用户那里,也就是说JWFD不需要用户进行二次开发就可以直接使用,由于有SAN算法的自动控制机制才使得最终用户完全不需要考虑流程如何流转,仅仅是需要使用设计器设计出一个流程,SAN算法及其附属模块就可以自动控制流程的流转。虽然目前这个算法还不是很完善,但是毕竟为我们开发出自动流程系统提供了一个很好的参考和方向


 

这个SAN算法在处理比较复杂的流程图的时候,还存在明显的缺点,比如说一个流程图的拓扑结构如果比较复杂,那么在控制器遍历和递归的过程中,可能出现访问次序不确定的错误,控制器没有按照流程的既定顺序去访问节点,而是以另外的顺序去访问其它节点,这就会导致流程运行过程中的一系列的问题,这些缺点,仅仅依赖技术手段来处理是不容易处理得很完美的,这些问题需要流程管理系统从前端设计器部分和后台运行控制器的部分一起下手处理,当然如果有朋友在运行过程中遇到什么问题,欢迎和我讨论,我们大家一起来处理这些问题。。。。。。。。。 

 

 

 

 

 

 

 


 


抱歉!评论已关闭.