OGNL简介

分支节点条件支持Ognl语法,必须是返回值为布尔值的表达式,具体可以参考Ognl的语法官方指引

一、模型介绍:

WorkflowTemplate实体,表示一个工单模版;

WorkflowInstance实体,表示一个工单实例;

WorkNode:工单模版中的节点;

WorkTransition:有prevNodeId和nextNodeId字段,表示两个模版节点之间的流转关系,有一个字段:conditions,如果非null,表示这是一个分支流转,并且conditions是一个ognl表达式,要求表达式返回true|false.

二、流程实例中的参数

(1)表达式中,可以直接调用com.cloudbility.workflow.WorkflowFunction中定义的方法,比如:max,maxOf,sort,equals等。

(2)表达式中,可以通过'#'引用当前流程meta中的变量。

不同类型流程实例会有不同的meta类型。下面举例说明,文件传输审核流程:

  • 文件上传审核meta参数:
{
   "action":"WebUpload",
   "hostId":5,
   "hostPlatform":"windows",
   "hostInnerIp":"192.168.5.64",
   "hostInstanceName":"192.168.5.64",
   "targetDir":"host_disk://9/",
   "fileReady":true,
   "fileItems":[
      {
         "fileName":"激活码.txt",
         "fileSize":3669,
         "relativePath":"激活码.txt",
         "tempUrl":"host_disk_hidden://5/FileTransferAudit/107/激活码.txt"
      },
      {
         "fileName":"阿里云插件-memo.txt",
         "fileSize":300,
         "relativePath":"阿里云插件-memo.txt",
         "tempUrl":"host_disk_hidden://5/FileTransferAudit/107/阿里云插件-memo.txt"
      }
   ],
   "paths":[
      "激活码.txt",
      "阿里云插件-memo.txt"
   ],
   "prepareJobId":-1,
   "targetDirDescription":"主机网盘:/"
}
  • 文件下载审核meta参数:
{
   "action":"WebDownload",
   "hostId":5,
   "hostPlatform":"windows",
   "hostInnerIp":"192.168.5.64",
   "hostInstanceName":"192.168.5.64",
   "srcUrl":"host_disk://9/NOTICE.harmony.txt",
   "locationUrl":"host_disk_hidden://5/FileTransferAudit/108/",
   "prepareJobId":568,
   "fileReady":true,
   "fileItems":[
      {
         "fileName":"NOTICE.harmony.txt",
         "fileSize":171,
         "relativePath":"NOTICE.harmony.txt",
         "tempUrl":"host_disk_hidden://5/FileTransferAudit/108/NOTICE.harmony.txt"
      }
   ],
   "paths":[
      "NOTICE.harmony.txt"
   ],
   "srcDescription":"主机网盘:/NOTICE.harmony.txt"
}

条件:包含txt文件需要进入当前分支审核。对应的ognl表达式可以这么写:

#paths.{? #this.endsWith('.txt')}.size()>0

后面详细介绍ognl的语法结构。

三、Ognl的语法简介

分支节点条件支持Ognl语法,必须是返回值为布尔值的表达式,具体可以参考Ognl的语法官方指引,以下是一些简单的语法介绍;

3.1、映射数组

语法结构:objects.{delegate} ,在delegate子表达式中,可以使用#this表示当前的元素。

比如,假设contenxt是:

{
   "action":"WebUpload",
   "hostId":5,
   "hostPlatform":"windows",
   "hostInnerIp":"192.168.5.64",
   "hostInstanceName":"192.168.5.64",
   "targetDir":"host_disk://9/",
   "fileReady":true,
   "fileItems":[
      {
         "fileName":"激活码.txt",
         "fileSize":3669,
         "relativePath":"激活码.txt",
         "tempUrl":"host_disk_hidden://5/FileTransferAudit/107/激活码.txt"
      },
      {
         "fileName":"阿里云插件-memo.txt",
         "fileSize":300,
         "relativePath":"阿里云插件-memo.txt",
         "tempUrl":"host_disk_hidden://5/FileTransferAudit/107/阿里云插件-memo.txt"
      }
   ],
   "paths":[
      "激活码.txt",
      "阿里云插件-memo.txt"
   ],
   "prepareJobId":-1,
   "targetDirDescription":"主机网盘:/"
}

那么表达式"#fileItems.{#this.fileName}"会返回 java.util.ArrayList:[激活码.txt, 阿里云插件-memo.txt]

"#fileItems.{#this.fileSize}"会返回 java.util.ArrayList:[3669, 300]

上面的例子,{delegate}是取元素的一个属性。如果想把一个数组按照条件过滤(即满足条件的元素一起组成一个新的数组),那么delegate需要写一个布尔表达式,如下:

  • "#fileItems.{?#this.fileName.endsWith('.txt')}"会返回 [{ "fileName": "激活码.txt", "fileSize": 3669, "relativePath": "激活码.txt", "tempUrl": "host_disk_hidden://5/FileTransferAudit/107/激活码.txt" }]

布尔表达式以?开头,后面跟一个子表达式。

objects.{^ expression} 和 objects.{$ expression}分别是过滤数组中的第一个和最后一个满足expression条件的元素,当然,返回的依旧是数组(包含选中的元素)

比如 :

  • "#fileItems.{^ #this.fileName.length()>5}"返回 [{ "fileName": "激活码.txt", "fileSize": 3669, "relativePath": "激活码.txt", "tempUrl": "host_disk_hidden://5/FileTransferAudit/107/激活码.txt" }]

  • "#fileItems.{$ #this.fileName.length()>5}"返回 [{ "fileName": "阿里云插件-memo.txt", "fileSize": 300, "relativePath": "阿里云插件-memo.txt", "tempUrl": "host_disk_hidden://5/FileTransferAudit/107/阿里云插件-memo.txt" }]

映射数组以后,还是数组,所以可以继续对后续数据进行处理,也可以直接用[i]进行元素引用(用[i]引用的时候要保证数组不能为空,否则会出现越界异常),比如:

  • "#fileItems.{#this.fileSize}[1]"返回java.lang.Long:300

  • "sumOf(#fileItems.{#this.fileSize})"返回所有文件大小之和,即java.lang.Double:3969.0 ,这里sumOf是定义在WorkflowFunction中的函数,返回值是java.lang.Double类型。

  • "maxOf(#fileItems.{#this.fileSize})"返回所有文件大小最大值,即java.lang.Long:3669 ,这里maxOf是定义在WorkflowFunction中的函数。

四、其他操作符

(1) Sequence operator :序列操作符:

e1,e2

e1和e2,都会被执行,表达式返回e2的返回值。

(2) 赋值操作:

e1=e2

会调用e2的getValue,调用e1的setValue(e2的返回值)

(3)条件运算:

e1?e2:e3

(4)逻辑运算:

e1&& e2
e1 and e2

(5)相等判定 == ,调用equals

(6)元素e1 是否在数组e2中;

e1 in e2

(7) e1 not in e2

(8) 方法调用:

e.method(args),e.property

五、文件传输审批-ongl条件示例

(1)文件个数超过10个

"#fileItems.size()>10"

(2)文件总大小超过10M

"sumOf(#fileItems.{#this.fileSize})>10*1024*1024"

(3)文件列表中最大文件大小超过1M

"maxOf(#fileItems.{#this.fileSize})>1024*1024"

(4)文件列表中包含.txt结尾的文件

"#fileItems.{? #this.fileName.endsWith('.txt')}.size()>0"

(5)文件列表中,包含.txt或者.pdf文件

"#fileItems.{? fName=#this.fileName,fName.endsWith('.txt') || fName.endsWith('.pdf1')}.size()>0"

或者用以下方式,其中,filterInFormats是定义在WorkflowFunction中的函数,这个函数可以处理大小写,比如fileName='abc.Txt’也能被检测到:

"filterInFormats(#fileItems.{#this.fileName},{'.txt','.pdf'}).size()>0"

(6)文件列表中,包含.txt文件

"filterInFormat(#fileItems.{#this.fileName},'.txt').size()>0"

(7)文件列表中,全部是.txt文件

"filterInFormat(#fileItems.{#this.fileName},'.txt').size()==#fileItems.size()"

(8)文件列表中,全部是txt 或者pdf文件

"filterInFormats(#fileItems.{#this.fileName},{'.txt','.pdf'}).size()==#fileItems.size()"