工作流系统之三十七 自由流的实现(续)

三十七. geotrellis使用 COG 基础介绍 前言 Geotrellis 已经迭代到了 2.0 版本(截止写作此文时为 2.0.0-SNAPSHOT 版),2.0 版多了很多新的特性,其中最重要的应该就是 COG,COG 是什么鬼?刚看到时我也是一脸懵,认认真真的学习了一天,稍有体会,本文对此进行简单介绍。 一、COG 简介 1.1 什么是 COG COG 是 Cloud Optimized GeoTIFF's 的简称,从这个名字就能大概猜出他的意义——云端优化的 GeoTIFF。GDAL 官方 WIKI 定义如下:... 阅读详情

工作流系统的自由流实现了不按照流程预定义的轨迹流转,即需要在节点之间任意的跳转。上一篇自由流的实现主要说明了跳转规律,如果是单节点间的跳转,只要有当前的节点,以及跳转到的节点,就ok了。但是当当前节点和任意跳转到的节点之间有分支并发线路后,就不是简单的跳转了,当分支套分支,分支主干等之间的跳转就更复杂了。


如果是这种串行路由,就很简单了。

但是这样的多路分支,分支嵌套分支的,就很复杂了。

因此在实现的时候,必需找出,当前节点到跳转到的节点之间的轨迹线路。又因为分支之间是可以嵌套的,所以必需用递归来遍历这之间的轨迹。

由当前节点开始,查找这个节点的动作结果节点是否为跳转到的节点,如果是,则找到之间的轨迹,返回。
如果不是,则将当前这个节点的动作结果节点作为当前节点,继续调用这个函数,查找,直到找到后退出。

因为流程定义的轨迹,可以是循环的轨迹,即一个节点的动作结果可以返回到前面的节点,如:

当返回到前面的节点时,用递归调用的话,就永远也退不出循环了。因此,将处理过的节点放到traceNodeList中,每次调用递归函数前,均判断一下,此节点是否在traceNodeList中,如果在,就不用处理了。不在的继续处理。


eworkflow自定义工作流系统有.net版和java版,两个版本的实现过程完全一样,只是一个是c#语言的一个是java语言的。


c#的递归函数:

  private ArrayList getJoinsAndSplitsBwteenStep(WorkflowDescriptor wd,IDictionary orgNodeMap,ResultDescriptor theResult,ArrayList traceNodeList)
  {                                
   ArrayList tagList = new ArrayList();
   string nodeType =(System.String)orgNodeMap["node_type"];
   AbstractDescriptor node = (AbstractDescriptor)orgNodeMap["node"];
     
   ArrayList results = new ArrayList();
   if (nodeType.Equals("join"))
   {  
    JoinDescriptor join = (JoinDescriptor)node;
    results.Add(join.Result);
   }
   if (nodeType.Equals("split"))
   {
    SplitDescriptor split = (SplitDescriptor)node;
    results.AddRange(split.Results);
   }
   if (nodeType.Equals("subflow"))
   {
    SubflowDescriptor subflow = (SubflowDescriptor)node;
    results.Add(subflow.unconditionalResult);
    results.AddRange(subflow.conditionalResults);
   }
   if (nodeType.Equals("step"))
   {
    StepDescriptor step = (StepDescriptor)node;
    ArrayList actions = step.actions;
    for (IEnumerator iter = actions.GetEnumerator();iter.MoveNext();)
    {
     ActionDescriptor action =(ActionDescriptor)iter.Current;
     ResultDescriptor result = action.UnconditionalResult;
     results.Add(result);
     results.AddRange(action.ConditionalResults);
    }       
   }
   bool bFind=false;
   for (IEnumerator it = results.GetEnumerator();it.MoveNext();)
   {
    ResultDescriptor result = (ResultDescriptor)it.Current;
    if (result.Id==theResult.Id)
    {//找到跳转到的节点,退出
     bFind = true;
     break;
    }
   }
   if (bFind) return tagList;
   //将当前处理节点 存入traceNodeList中
   traceNodeList.Add(node); 
        
   for (IEnumerator iterator = results.GetEnumerator();iterator.MoveNext();)
   {
      
    ResultDescriptor resultDesc = (ResultDescriptor)iterator.Current;
    int joinid = resultDesc.join;
    int splitid = resultDesc.Split;
    int stepid = resultDesc.Step;
    int subflowid = resultDesc.subflow;
    int traceid = 0;
    IDictionary orgMap = new Hashtable();//记录节点信息
    if (joinid>0)
    {
     IDictionary m = new Hashtable();
     m["join"] = joinid;//new Integer(joinid);
     tagList.Add(m);
     JoinDescriptor join = wd.getJoin(joinid);
        
     orgMap["node_type"] = "join";
     orgMap["node"] = join;
     traceid = joinid;
    }
    if (splitid>0)
    {
     SplitDescriptor split = wd.getSplit(splitid);
     orgMap["node_type"] = "split";
     orgMap["node"] = split;
     IDictionary m = new Hashtable();
     m["split"] = splitid;// new Integer(splitid));
    
     for (int i=0;i<split.Results.Count;i++)
     {
      tagList.Add(m);    
     }
     traceid = splitid;
    }
    if (stepid>0)
    {
     StepDescriptor step = wd.getStep(stepid);
     orgMap["node_type"] = "step";
     orgMap["node"] = step;
     traceid = stepid;
    }
    if (subflowid>0)
    {
     SubflowDescriptor subflow = wd.getSubflow(subflowid);
     orgMap["node_type"] = "subflow";
     orgMap["node"] = subflow;    
     traceid = subflowid;
    }
    //判断 关联到的节点 是否处理过
    bool inTrace = false;
    for (IEnumerator itrace=traceNodeList.GetEnumerator();itrace.MoveNext();)
    {
     AbstractDescriptor trace = (AbstractDescriptor)itrace.Current;
     if (trace.Id==traceid)
     {//已经处理过的了
      inTrace = true;
      break;
     }    
    }
    if (!inTrace)
     tagList.AddRange(getJoinsAndSplitsBwteenStep(wd,orgMap,theResult,traceNodeList));
      
   }

   return tagList;

 


java的递归函数:

    private List getJoinsAndSplitsBwteenStep(WorkflowDescriptor wd,Map orgNodeMap,ResultDescriptor theResult,List traceNodeList) throws WorkflowException{

     List tagList =new ArrayList();
     String nodeType =(String)orgNodeMap.get("node_type");
     AbstractDescriptor node = (AbstractDescriptor)orgNodeMap.get("node");
     
     List results = new ArrayList();
     if (nodeType.equals("join")){
      JoinDescriptor join = (JoinDescriptor)node;
      results.add(join.getResult());
     }
     if (nodeType.equals("split")){
      SplitDescriptor split = (SplitDescriptor)node;
      results.addAll(split.getResults());
     }
     if (nodeType.equals("subflow")){
      SubflowDescriptor subflow = (SubflowDescriptor)node;
      results.add(subflow.getUnconditionalResult());
      results.addAll(subflow.getConditionalResults());
     }
     if (nodeType.equals("step")){
      StepDescriptor step = (StepDescriptor)node;
      List actions = step.getActions();
         for (Iterator iter = actions.iterator();iter.hasNext();){
          ActionDescriptor action =(ActionDescriptor)iter.next();
          ResultDescriptor result = action.getUnconditionalResult();
          results.add(result);
          results.addAll(action.getConditionalResults());
         }       
     }
     boolean bFind=false;
     for (Iterator it = results.iterator();it.hasNext();){
      ResultDescriptor result = (ResultDescriptor)it.next();
      if (result.getId()==theResult.getId()){//找到跳转到的节点,退出
       bFind = true;
       break;
       //return tagList;
      }
     }
     if (bFind) return tagList;
     //将当前处理节点 存入traceNodeList中
     traceNodeList.add(node); 
     
  for (Iterator iterator = results.iterator();iterator.hasNext();){
   
   ResultDescriptor resultDesc = (ResultDescriptor)iterator.next();
   int joinid = resultDesc.getJoin();
   int splitid = resultDesc.getSplit();
   int stepid = resultDesc.getStep();
   int subflowid = resultDesc.getSubflow();
   int traceid = 0;
   Map orgMap = new HashMap();//记录节点信息
   if (joinid>0){
    Map m = new HashMap();
    m.put("join", new Integer(joinid));
    tagList.add(m);
    JoinDescriptor join = wd.getJoin(joinid);
    
    orgMap.put("node_type", "join");
    orgMap.put("node", join);    
    traceid = joinid;
   }
   if (splitid>0){
    SplitDescriptor split = wd.getSplit(splitid);
    orgMap.put("node_type", "split");
    orgMap.put("node", split);
    Map m = new HashMap();
    m.put("split", new Integer(splitid));
    //tagList.add(m);
    for (int i=0;i<split.getResults().size();i++){
     tagList.add(m);    
    }
    traceid = splitid;
   }
   if (stepid>0){
    StepDescriptor step = wd.getStep(stepid);
    orgMap.put("node_type", "step");
    orgMap.put("node", step);
    traceid = stepid;
   }
   if (subflowid>0){
    SubflowDescriptor  subflow = wd.getSubflow(subflowid);
    orgMap.put("node_type", "subflow");
    orgMap.put("node", subflow);    
    traceid = subflowid;
   }
   //判断 关联到的节点 是否处理过
   boolean inTrace = false;
   for (Iterator itrace=traceNodeList.iterator();itrace.hasNext();){
    AbstractDescriptor trace = (AbstractDescriptor)itrace.next();
    if (trace.getId()==traceid){//已经处理过的了
     inTrace = true;
     break;
    }    
   }
   if (!inTrace)
    tagList.addAll(getJoinsAndSplitsBwteenStep(wd,orgMap,theResult,traceNodeList));
   
  }

     return tagList;
    }

StarFlow 工作流--自由流 NULL 博文链接:https://melin.iteye.com/blog/574121 立即下载

相关推荐

一个简单C#工作流的实现

一个简单C#工作流的实现

工作流系统之三十六 晒自由流实现代码,欢迎多提改进意见

工作流系统的自由流实现了不按照流程预定义的轨迹流转,即需要在节点之间任意的跳转。上一篇自由流的实现主要说明了跳转规律,如果是单节点间的跳转,只要有当前的节点,以及跳转到的节点,就ok了。但是当当前节点和任意跳转到的节点之间有分支并发线路后,就不是简单的跳转了,当分支套分支,分支主干等之间的跳转就更复杂了。  如果是这种串行路由,就很简单了。   但是这样的多路分支,分支嵌套分支的,就很复...

专注于web工作流管理系统开发 307

C# 工作流设计器代码

使用c#.net编写的workflow desinger 例程

工作流系统之三十五 自由流的实现

工作流系统在给业务流程建模的时候,按照流程引擎的设计,将业务流程定义出来。这个业务流程的每个流程实例,就按照流程建模时定义好的线路流转。 自由流是指流程实例在运行时,不按照预先定义好的线路流转,而是自由的跳转,由流程实例的操作人员来选择下一个到达的节点。通常这种都是不正常的流转,和回退流一样,破坏了流程的正常定义。但是自由流又很有“特色”,符合一定的业务需求。例如,当一份申请单提交审核后,需要部...

weixin_34348174的博客 390

jBPM4.4 自由流之退回

源码 实现自由流的退回操作 如果想进一步了解 可以给我留言。 我愿意与大家分享更多关于自由流的实例。

c语言播放背景音乐

相信很多童鞋都在为大学课设而伤透头脑,而背景音乐的使用无疑会成为其中的一个亮点(总比没有好吧(╯▽╰)),故接下来我将介绍一下如何用C播放音乐。我用的编译器是CodeBlocks16.01接下来新建一个C文件建立完后是这样滴然后添加其中mciSendString()函数是由&lt;mmsystem.h&gt;库提供的供播放音乐(MP3)的函数第一个参数是歌曲所在的绝对路径 打开音乐所在位置 复制这...

qq_41443987的博客 3万+

工作流模式分析

1.    流程起点模型任何事物都有由头有尾,一个流程也不例外,那么现在我们就从流程的“头”——流程起点说起。一个工作流能够运行,就需要一系列条件来激活。而这个激活的位置,就是“起点”(Start Node)。需要说明的是,起点也是一种任务节点(Task Node)。这个特殊的任务节点也许会执行一定的操作,也许仅仅只是一些数据状态的改变。但是,不论什么原因,最终会导致一个流程实例的产生——流程被激

李小强(leaderbird)的专栏 1061

(MIUI)小米手机录音文件深度寻踪:从系统缓存到数据目录的实战解析

本文深入解析了MIUI系统中录音文件丢失的常见原因及解决方案,包括系统升级兼容性问题、应用缓存机制异常和存储权限变动。通过实战操作指南,详细介绍了如何从系统目录、数据库层面恢复录音文件,并提供了预防措施和自动化备份方案,帮助小米手机用户有效找回重要录音数据。

weixin_42699679的博客 518

工作流系统之三十七 工作流软件中的那些人

如果我们把预定义的流程比喻成一条从起点到终点的公交线路,那么流程定义中的步骤,就表示车站。汽车到站后人员有上车下车等行为,这就可以认为是流程中的动作。流程定义完后,就按照预定义好的线路往下走,当然业务流程的规则是比公交线路更复杂。   业务流程的流转离不开人员的参与,工作流软件的定义就是:自动运作的业务过程部分或整体,表现为参与者对文件、信息或任务按照规程采取行动,并令其在参与者之间传递。...

专注于web工作流管理系统开发 106

倍福TwinCAT3 OPC UA配置全流程:从安装到无密码访问(附常见问题解决)

本文提供了倍福TwinCAT3 OPC UA配置的完整实战指南,重点讲解如何实现无密码游客访问。从软件安装、授权配置、服务器初始化到深度排错,详细解析了配置流程中的关键步骤与常见陷阱,帮助工程师高效打通PLC与上位系统的数据通讯通道。

vulkan6gpu的博客 473

VASPKIT绘制平面平均电荷差分密度

平面平均密度差(planar-averaged electron density difference)是密度差的衍生。密度差是个三维空间函数,经常通过绘制平面图、等值面图方式图形化考察。虽然这两种图很直观,但平面图会受到截面选取的影响,而等值面图会受到等值面数值(isovalue)选取的影响,因此都有一定任意性,也不容易定量讨论。对于电子转移有比较明确方向的情况,可以绘制平面平均密度差曲线,由此可以清楚地考察垂直于选取的方向上每个截面上的密度差积分值,在定量讨论、对比上比较便利。

weixin_43948934的博客 1万+

第三十七周学习周报

今日学习围绕CFD仿真,涵盖从几何前处理、网格划分、求解计算到后处理的完整流程,并深入探讨了空气动力学中等熵流动公式在边界条件设置中的关键应用。几何与基准模型:采用NACA 0012这一对称翼型作为标准几何,弦长1米,使其结果易于与经典理论和公开实验数据对比验证。流动条件:来流马赫数0.7,攻角1.55°。这定义了一个典型的高亚音速/跨音速流动场景,翼型表面可能出现局部超音速区及激波,是检验求解器对可压缩流和激波捕捉能力的常用条件。

weixin_63333209的博客 667

Pdu Router(PduR)模块

1. PduR路由基本功能 2. PduR总线网关功能 3. PduR缓存机制 4. 总结

weixin_43759043的博客 3850

第三十七章:文生图的炼金术:Stable Diffusion完整工作流深度解析

为什么Stable Diffusion能将一句文字Prompt,转化为栩栩如生的图像?本文将为你深度解剖Stable Diffusion的完整工作流。我们将把之前学到的CLIP Text Encoder、U-Net、VAE和调度器等所有核心组件,像拼图一样,系统性地整合起来。你将一步步追踪数据从原始Prompt输入,经过文本编码、潜在空间去噪、最终图像解码的全过程。本章提供一个完整的、可直接运行的PyTorch脚本,让你亲手驱动这个强大的文生图引擎,并理解**CFG(Classifier-Free Guid

qq_35899016的博客 1457

【LAMMPS学习】五、LAMMPS命令(8) Pair_style 势

所有LAMMPS pair_style命令如下表所示。有些样式有加速版本。这由括号中的附加字母表示:g = GPU, i = INTEL, k = KOKKOS, o = OPENMP, t = OPT。

荷塘阅色 3016

SerDes系列之 SSC扩频时钟技术

扩频时钟,又称展频(SSC-Spread Spectrum Clocking),当前PCIE、DDR、USB等几乎所有的高速接口都支持SSC的功能。电子工程师在日常的电气测试中经常与之接触,在电磁传导和辐射发射验证过程中,经常需要使用到芯片的SSC功能,它的物理表现形式,就是信号的比特率会在一个很小的范围内浮动,多见于周期性变化的时钟信号。

一只豌豆象的博客 3443

Dify 从入门到精通(第 37/100 篇):Dify 的自动化工作流优化

Dify 的自动化工作流通过 Workflow 节点、触发器(如 Webhook)和外部 API 集成,实现任务自动化。结合条件逻辑和循环节点,支持复杂业务流程。核心功能触发器:通过 Webhook 或定时任务启动。条件逻辑:If/Else 节点处理分支。循环处理:批量处理数据。适用场景订单处理:自动更新订单状态。客户支持:自动分配工单。数据同步:实时更新外部系统。

haolove527的专栏 1778

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Kinsta 博客中文翻译(一百三十七)

总而言之,组织和员工必须非常认真地对待在家工作的安全风险。即使在家工作被证明是成功的、更高效的、更方便的,如果不采取适当的网络安全措施,它也可能变成员工和企业的真正噩梦。但是,如果您遵循上面讨论的安全提示,您将享受到安全高效的远程工作体验。关于在家工作时如何保护数据安全,您还有什么问题吗?我们在评论区讨论这个吧!让你所有的应用程序数据库和WordPress 网站在线并在一个屋檐下。在 MyKinsta 仪表盘中轻松设置和管理24/7 专家支持。

龙哥盟 1197

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

最新计算机专业开题报告案例40:基于大数据分析的OA办公系统的应用与实现

一、选题依据计算机毕业设计100套需要可以滴滴我一、选题依据1.1研究意义随着大数据技术的迅速发展,各行各业纷纷借助大数据分析实现信息的深度挖掘和智能化决策。在企业管理领域,办公自动化OA系统作为信息管理和流程优化的重要工具,其在提高工作效率、优化资源配置等方面具有巨大潜力。企业在发展中不断增加业务,传统OA系统在应对大规模数据和多变业务流程上显露出一定的不足。办公自动化OA。

平姐设计的博客 1572

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Octopus 博客中文翻译(三十七)

Opsera 的一个强大功能是其可视化和编排管道工作流的能力:这个工作流代表了一个基于 Java 的项目:通过命令行构建源代码→将工件推送到 Nexus repository →通过 Octopus Deploy 部署到 IIS。Opsera 显示工作流程的每个步骤;每个步骤代表一个工具和一个要执行的操作。编辑配置使您能够自定义其步骤包含的属性和操作:这一步表示通过 Octopus Deploy 部署到 IIS。Opsera UI 公开了渠道、项目和角色等资源,提供了跨其支持的平台的一致体验。

龙哥盟 1064

AIGC 创意猎人(三十七)

Role]你是一个拥有2000w粉丝的social media influencer,作为小红书的爆款写作专家,你拥有消费心理学+市场营销双phd. 你是小红书的重度用户,你拥有卓越的互联网网感。有着丰富的撰写经验,擅长将陶瓷企业的企业发展和产品生产等调研结果用报告的形式表达出来,让看的人能迅速了解该家陶瓷企业的产品和历史发展。记住,不满意直接回复我,我可是很心善的。我现在有一份作业,是对中国某家陶瓷企业的管理工作进行调研分析,然后把结果用报告的形式展现出来,我需要你帮助我协助完成这项工作,完成作业。

龙哥盟 259

第三十七章:ReactFlow实战案例:物联网

1.背景介绍 物联网(Internet of Things,简称IoT)是指通过互联网将物体、设备、人工智能等连接起来,实现互联互通的大型系统。物联网技术在各个行业中发挥着越来越重要的作用,例如智能家居、智能交通、智能制造、智能医疗等。ReactFlow是一个用于构建流程图、工作流程和数据流的开源库,可以用于物联网系统的设计和开发。在本章中,我们将介绍ReactFlow实战案例:物联网,涵盖背景...

AI天才研究院 1010

三十七、并发编程之有界阻塞队列 ArrayBlockingQueue 原理探究

一、 ArrayBlockingQueue简介 基于数组的阻塞队列实现,在ArrayBlockingQueue内部,维护了一个定长数组,以便缓存队列中的数据对象,这是一个常用的阻塞队列,除了一个定长数组外,ArrayBlockingQueue内部还保存着两个整形变量,分别标识着队列的头部和尾部在数组中的位置。 ArrayBlockingQueue在生产者放入数据和消费者获取数据,都是共用同一个锁对...

白夜行悟空 358
上一篇: 工作流系统之三十六 工作流软件中的那些人
下一篇: 工作流系统之三十八 工作流软件中的定时器处理
LikeLaura
博客等级 码龄19年 50粉丝 0原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值