第五章 工作流图形定义工具(八)-- 递归算法的使用

本文档详细介绍了如何在工作流图形定义工具中开发递归算法,涉及节点删除、编辑属性和保存流程到数据库的操作。在删除节点时,针对不同类型的逻辑节点,如AndSplit和OrJoin,进行了特殊的处理。此外,还提供了检查和编辑节点属性的机制,确保流程的正确性和完整性。最后,讲述了流程和节点保存到数据库的过程,以及检查模型完整性的递归算法,包括AndSplit和OrSplit的嵌套约束检查。
摘要由CSDN通过智能技术生成

5.7 开发工作流图形定义工具

5.7.6 图形工具主界面程序   

......(接前页)

        //删除节点
        private void menuItem1_Click(object sender, System.EventArgs e)
        {

            //如果右键选择了节点
            if(R_pickednode != null)
            {

                //定义临时节点

                NodeClass editednode = null;
                //如果删除的是逻辑节点,首先要设置相应的任务节点的processlogic属性为空
                if(R_pickednode.NodeType == nodetypedefine.andsplit || R_pickednode.NodeType

                        == nodetypedefine.orsplit)
                {

                   //如果存在指向逻辑节点的迁移
                   if(transitionarray.GetToNodeTransition(R_pickednode.NodeName) != null)

                   //获取分支节点的前驱任务节点

                   editednode = nodearray.GetNode(transitionarray

                       .GetToNodeTransition(R_pickednode.NodeName).GetTransition(0).FromNode);

                   //考虑具有双重逻辑属性的节点

                   if(editednode.ProcessLogic == "AndJoin&OrSplit")

                        editednode.ProcessLogic = "AndJoin";

                   ......

                   else//如果只包含单重逻辑属性的

                        editednode.ProcessLogic="";
                 }
                 if(R_pickednode.NodeType == nodetypedefine.andjoin || R_pickednode.NodeType

                        == nodetypedefine.orjoin)
                 {

                     //如果存在从合并节点引出的迁移
                     if(transitionarray.GetFromNodeTransition(R_pickednode.NodeName) != null)

                     {

                          editednode = nodearray.GetNode(transitionarray.GetFromNodeTransition

                                (R_pickednode.NodeName).GetTransition(0).ToNode);

                          //考虑具有双重逻辑属性的节点

                          if(editednode.ProcessLogic == "AndJoin&OrSplit")

                               editednode.ProcessLogic = "OrSplit";

                          ......

                          else//如果只包含单重逻辑属性的

                               editednode.ProcessLogic="";

                     }

                 }
                 //删除节点和关联的迁移
                 transitionarray.DeleteTransition(R_pickednode.NodeName);
                 nodearray.DeleteNode(R_pickednode);    
                 //只有一个节点时,删除后不消失(不知什么原因),增加了下面语句
                 g=panel1.CreateGraphics();
                 g.FillRectangle(new SolidBrush(this.BackColor),0,0,this.Width,this.Height);
                 g.Dispose();
                 R_pickednode=null;    
                 repaint();
             }//如果右键选择了节点
         }

         //编辑节点属性
         private void menuItem2_Click(object sender, System.EventArgs e)
         {
             if(R_pickednode != null)
             {
                if( R_pickednode.NodeType == nodetypedefine.tasknode)
                {
                   //记录节点原名称
                   string oldname=R_pickednode.NodeName;

                   //初始化节点编辑窗
                   EditNode editnode=new EditNode();
                   editnode.setNameText(R_pickednode.NodeName);
                   editnode.ShowDialog();
                   if(editnode.nodename == "")
                       MessageBox.Show("节点名称不能为空!");
                   else
                   {
                       //判断输入的节点名程是否与其它节点重复
                       //先把当前节点名置为空,以便只检查其它节点
                       string tempstr=R_pickednode.NodeName;
                       R_pickednode.NodeName="";
                       if(nodearray.GetNode(editnode.nodename.Trim()) != null)
                       {
                           R_pickednode.NodeName=tempstr;
                           MessageBox.Show("节点名称重复!");
                       }
                       else
                       {
                           R_pickednode.NodeName=editnode.nodename.Trim();
                           //按照原名称获取所有指向所选节点的迁移
                           TransitionRecords pretransitions=transitionarray

                                 .GetToNodeTransition(oldname);
                           //如果存在指向所选节点的迁移
                           if(pretransitions != null)
                           {
                               for(int i=0;i<pretransitions.Count;i++)
                                   pretransitions.GetTransition(i).ToNode

                                       =R_pickednode.NodeName;
                           }
                           TransitionRecords nexttransitions=transitionarray

                                .GetFromNodeTransition(oldname);
                           //如果存在从所选节点引出的迁移
                           if(nexttransitions != null)
                           {
                               for(int i=0;i<nexttransitions.Count;i++)
                                   nexttransitions.GetTransition(i).FromNode

                                        =R_pickednode.NodeName;
                           }
                       }//else
                   }//else
                }//if( R_pickednode.NodeType == nodetypedefine.tasknode)
                R_pickednode=null;
            }//if(R_pickednode != null)
        }

        //绘图面板重画事件处理函数

        private void Panel_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
             repaint();
              

        //把流程及节点保存到数据库
        private void menuItem5_Click(object sender, System.EventArgs e)
        {
            //检查节点数组的正确性
            if(! CheckProcessModel())
                 return;

            //编辑过程属性
            ProcessForm processform=new ProcessForm();
            processform.ShowDialog();
            if(processform.processDes == "")
            {
                 MessageBox.Show("流程名称不能为空!");
                 return;
            }

            else if(processform.duedate == "")
            {
               MessageBox.Show("承诺期限不能为空!");
               return;
            }
            else
            {
                 if(processform.processDes.Length > 50)
                 {
                      MessageBox.Show("流程名称太长!");
                      return;
                 }
                 DataAccess database=new DataAccess();
                 //判断流程名称是否已经存在
                 string strSql="select ProcessID from ProcessDefinition where  

                                ProcessName=@ProcessName";

                 SqlCommand cmd=new SqlCommand(strSql);
                 cmd.Parameters.Add("@ProcessName",SqlDbType.VarChar,50);
                 cmd.Parameters["@ProcessName"].Value=processform.processDes;
                 if(database.IfExistRecord(cmd))
                 {
                      MessageBox.Show("流程名称已经存在!");
                      return;
                    
    
                 //保存流程
                 //获得该流程关联的业务表的标识字段名
                 string tablename=processform.relatedTableName;
                 string tablealias=processform.tableAlias;
                 strSql="Select name from syscolumns Where ID=OBJECT_ID('"+tablename+"')  and

                           autoval is not null";
                 DataSet ds=database.SQLExeDataSet(strSql);
                 if(ds == null)
                 {
                      MessageBox.Show("获取业务表标识字段名失败!");
                      return;
                 }
                 if(ds.Tables[0].Rows.Count<1 )
                 {
                      MessageBox.Show("数据表"+tablename+"没有定义标识字段,不能进行流程关联.流

                           程定义无法继续进行.");
                      return;
                 }
                 string identityfield=ds.Tables[0].Rows[0]["name"].ToString();

                 //保存过程和节点
                 int processid=nodearray.SaveProcess(processform.processDes,tablename,

                                tablealias,identityfield,processform.duedate);
                 if( processid == -1)
                        return;
                 //保存迁移
                 if(! transitionarray.SaveTransitions(nodearray,processid))
                        return;
    
             }//else
         }
         //检查节点数组的正确性
         private bool CheckProcessModel()
         {
             //检查模型的正确性
             //至少要包含开始、结束和2个任务节点
             if(nodearray.Count < 3)
             {
                 MessageBox.Show("流程至少要包含开始、结束和任务节点!");
                 return false;
             }
             //是否有开始节点
             bool hasstartnode=false;
             for(int i=0;i<nodearray.Count;i++)
             {
                 if(nodearray.GetNode(i).NodeType == nodetypedefine.start)
                 {
                     hasstartnode=true;
                     break;
                 }
             }
             if(! hasstartnode)
             {
                 MessageBox.Show("没有开始节点!");
                 return false;
             }
             //是否有结束节点
             bool hasendnode=false;
             for(int i=0;i<nodearray.Count;i++)
             {
                 if(nodearray.GetNode(i).NodeType == nodetypedefine.end)
                 {
                     hasendnode=true;
                     break;
                 }
             }
             if(! hasendnode)
             {
                 MessageBox.Show("没有结束节点!");
                 return false;
             }
             //除了开始节点,所有节点都必须存在前驱;除了结束节点,所有节点都必须存在后继。
             //检查前驱
             bool prenode=true;
             for(int i=0;i<nodearray.Count;i++)
             {
                 if(nodearray.GetNode(i).NodeType != nodetypedefine.start)
                 {
                     if(transitionarray.GetToNodeTransition(nodearray.GetNode(i).NodeName)

                               == null)
                     {
                         prenode=false;
                         break;
                     }
                 }
             }
             if(! prenode)
             {
                 MessageBox.Show("除开始节点外还存在没有前驱的节点!");
                 return false;
             }
             //检查后继
             bool nextnode=true;
             for(int i=0;i<nodearray.Count;i++)
             {
                 if(nodearray.GetNode(i).NodeType != nodetypedefine.end)
                 {
                    if(transitionarray.GetFromNodeTransition(nodearray.GetNode(i).NodeName)

                           == null)
                    {
                        nextnode=false;
                        break;
                    }
                 }
              }
              if(! nextnode)
              {
                  MessageBox.Show("除结束节点外还存在没有后继的节点!");
                  return false;
              }
              //过程的连通性检查已没必要,有了画图时的迁移的单向性检查,以及过程的完整性检查和

              //过程嵌套约束,已经可以满足连通性;“或分支最多只能包含一个旁路”的约束不必检

              //查,因为在画图时已经检查了“两个节点(包括或分支与或连接节点)间只能有一个迁

              //移”的约束。

              //或分支至少要有一个路径包含任务节点
              bool includetask=true;
              NodeClass tempnode=null;
              TransitionRecords temparray=null;
              for(int i=0;i<nodearray.Count;i++)
              {
                  tempnode=nodearray.GetNode(i);

                  //如果第i个节点是或分支节点
                  if(tempnode.NodeType == nodetypedefine.orsplit)
                  {
                      includetask=false;

                      //获取从或分支节点引出的所有迁移
                      temparray=transitionarray.GetFromNodeTransition(tempnode.NodeName);
                      for(int j=0;j<temparray.Count;j++)
                      {
                          if(nodearray.GetNode(temparray.GetTransition(j).ToNode).NodeType

                                 == nodetypedefine.tasknode)
                          {
                              includetask=true;
                              break;
                          }
                      }
                  }

                  //如果有或分支没有任何路径包含任务节点(只有一个旁路)
                  if(! includetask)
                       break;    
               }//外层for循环
               if(! includetask)
               {
                   MessageBox.Show("或分支至少要有一个包含任务节点的分支!");
                   return false;
                
               //过程逻辑的嵌套约束:每一个And Split分支节点的第一个后继过程逻辑节点只能是

               //And Join连接节点
               bool nested=false;
               tempnode=null;
               temparray=null;
               //遍历节点数组,检查每一个andsplit节点
               for(int i=0;i<nodearray.Count;i++)
               {
                   if(nodearray.GetNode(i).NodeType == nodetypedefine.andsplit)
                   {
                      //获取andsplit的所有后继迁移
                      temparray=transitionarray.GetFromNodeTransition(nodearray.GetNode(i)

                                  .NodeName);
                      if(temparray != null)
                      {

                          //循环检查andsplit的每一个分支
                          for(int j=0;j<temparray.Count;j++)
                               
                              tempnode=nodearray.GetNode(temparray.GetTransition(j).ToNode);
                              //调用递归函数检查。如果存在嵌套或不对称,则终止当前循环
                              if(AndNestedCheck(tempnode))
                              {
                                  nested=true;
                                  break;
                              }
                               
                      }
                      //如果发现了嵌套或不对称则退出外层循环,不再继续检查下一个andsplit节点
                      if(nested == true)
                           break;
                  }
              }//遍历节点数组的for循环
              //如果存在嵌套或不对称则返回检查结果
              if(nested)
              {
                  MessageBox.Show("存在过程逻辑嵌套或者过程逻辑不对称!");
                  return false;
              }

              //orsplit过程逻辑的嵌套约束:每一个Or Split分支节点的第一个后继过程逻辑节点只能

              //是Or Join连接节点
              nested=false;
              tempnode=null;
              temparray=null;
              //遍历节点数组,检查每一个orsplit节点
              for(int i=0;i<nodearray.Count;i++)
              {
                  if(nodearray.GetNode(i).NodeType == nodetypedefine.orsplit)
                  {
                      //获取orsplit的所有后继迁移
                      temparray=transitionarray.GetFromNodeTransition(nodearray.GetNode(i)

                                     .NodeName);
                      if(temparray != null)
                      {

                          //检查orsplit的每一个分支
                          for(int j=0;j<temparray.Count;j++)
                               
                              tempnode=nodearray.GetNode(temparray.GetTransition(j).ToNode);
                              //递归检查分支的后继节点。如果存在嵌套或不对称,则终止当前循环
                              if(OrNestedCheck(tempnode))
                              {
                                  nested=true;
                                  break;
                              }
                              
                       }
                       //如果发现了嵌套或不对称则退出外层循环,不再继续检查下一个orsplit节点
                       if(nested == true)
                            break;
                    }
                }//外层for循环
                //如果存在嵌套或不对称则返回检查结果
                if(nested)
                {
                    MessageBox.Show("存在过程逻辑嵌套或者过程逻辑不对称!");
                    return false;
                }
                return true;
          }//CheckProcessModel()

          ......(待续)

          

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值