hoho,今天完成了选择路由的实现,完成了配置文件的读写和解析,流程定义文件还是决定采用xml文件,不过与其他工作流引擎采用的xml完全不同,因为是基于petri网的,因此引入了place的概念,比如下面这个4个节点的顺序路由的流程:
并行路由和选择路由引入了and-split,and-join,or-split,or-join四种transition,比如and-split,它就有多个输出place:
Place和Transition都有条件,用于决定操作是否执行,Transition额外指定了驱动的资源以及回调的handler,这一点非常重要,资源可能是用户、用户组、某个时间点定时事件、特定消息等等。
今天额外发现的一个好处就是,引入Place之后,我可以轻易地将不同的流程连接起来组织成一个更复杂的流程,仅仅是需要修改各个流程的开始和结束的节点的输入输出库所,从而实现了层次化的Petri网,,类似代码:
<
workflow
maxCases
="100"
>
< node type ="start" name ="start" id ="0" >
< inputs >
< place id ="1" />
</ inputs >
< outputs >
< place id ="2" />
</ outputs >
</ node >
< node name ="hello" id ="1" resource ="user" >
< conditions type ="and" >
< condition
class ="net.rubyeye.insect.workflow.impl.NullHandler" value ="false"
variable-name ="name" />
</ conditions >
< handler
class ="net.rubyeye.insect.workflow.test.HelloWorldHandler" />
< inputs >
< place id ="2" />
</ inputs >
< outputs >
< place id ="3" />
</ outputs >
</ node >
< node name ="calc" id ="2" resource ="user" >
< conditions type ="and" >
< condition variable-name ="num" >
< exp >
<![CDATA[ num<=1000 ]]>
</ exp >
</ condition >
< conditions type ="or" >
< condition variable-name ="num" >
< exp >
<![CDATA[ num>=10 ]]>
</ exp >
</ condition >
< condition
class ="net.rubyeye.insect.workflow.impl.NullHandler" value ="false"
variable-name ="name" />
</ conditions >
</ conditions >
< handler
class ="net.rubyeye.insect.workflow.test.CalculateHandler" />
< inputs >
< place id ="3" />
</ inputs >
< outputs >
< place id ="4" />
</ outputs >
</ node >
< node type ="end" name ="hello" id ="3" >
< inputs >
< place id ="4" />
</ inputs >
< outputs >
< place id ="5" />
</ outputs >
</ node >
</ workflow >
< node type ="start" name ="start" id ="0" >
< inputs >
< place id ="1" />
</ inputs >
< outputs >
< place id ="2" />
</ outputs >
</ node >
< node name ="hello" id ="1" resource ="user" >
< conditions type ="and" >
< condition
class ="net.rubyeye.insect.workflow.impl.NullHandler" value ="false"
variable-name ="name" />
</ conditions >
< handler
class ="net.rubyeye.insect.workflow.test.HelloWorldHandler" />
< inputs >
< place id ="2" />
</ inputs >
< outputs >
< place id ="3" />
</ outputs >
</ node >
< node name ="calc" id ="2" resource ="user" >
< conditions type ="and" >
< condition variable-name ="num" >
< exp >
<![CDATA[ num<=1000 ]]>
</ exp >
</ condition >
< conditions type ="or" >
< condition variable-name ="num" >
< exp >
<![CDATA[ num>=10 ]]>
</ exp >
</ condition >
< condition
class ="net.rubyeye.insect.workflow.impl.NullHandler" value ="false"
variable-name ="name" />
</ conditions >
</ conditions >
< handler
class ="net.rubyeye.insect.workflow.test.CalculateHandler" />
< inputs >
< place id ="3" />
</ inputs >
< outputs >
< place id ="4" />
</ outputs >
</ node >
< node type ="end" name ="hello" id ="3" >
< inputs >
< place id ="4" />
</ inputs >
< outputs >
< place id ="5" />
</ outputs >
</ node >
</ workflow >
并行路由和选择路由引入了and-split,and-join,or-split,or-join四种transition,比如and-split,它就有多个输出place:
<
node
name
="split"
type
="and-split"
id
="1"
resource
="user"
>
< inputs >
< place id ="2" />
</ inputs >
< outputs >
< place id ="3" />
< place id ="4" />
</ outputs >
</ node >
< inputs >
< place id ="2" />
</ inputs >
< outputs >
< place id ="3" />
< place id ="4" />
</ outputs >
</ node >
Place和Transition都有条件,用于决定操作是否执行,Transition额外指定了驱动的资源以及回调的handler,这一点非常重要,资源可能是用户、用户组、某个时间点定时事件、特定消息等等。
今天额外发现的一个好处就是,引入Place之后,我可以轻易地将不同的流程连接起来组织成一个更复杂的流程,仅仅是需要修改各个流程的开始和结束的节点的输入输出库所,从而实现了层次化的Petri网,,类似代码:
WorkFlow sequence
=
wm.getWorkFlow(
"
sequence
"
);
WorkFlow concurrency = wm.getWorkFlow( " concurrency " );
WorkFlow choose = wm.getWorkFlow( " choose " );
// 组合流程
composite = new WorkFlow();
composite.setName( " composite " );
composite.setId( 100 );
wm.saveWorkFlow(composite);
// 修改开始结束节点的输入输出库所
sequence.getEnd().setType(TransitionType.NORMAL);
sequence.getEnd().setOutputs(concurrency.getStart().getInputs());
concurrency.getEnd().setType(TransitionType.NORMAL);
concurrency.getEnd().setOutputs(choose.getStart().getInputs());
composite.setStart(sequence.getStart());
composite.setEnd(choose.getEnd());
List < Transition > transitions = new ArrayList < Transition > ();
transitions.addAll(sequence.getTransitions());
transitions.addAll(concurrency.getTransitions());
transitions.addAll(choose.getTransitions());
composite.setTransitions(transitions);
WorkFlow concurrency = wm.getWorkFlow( " concurrency " );
WorkFlow choose = wm.getWorkFlow( " choose " );
// 组合流程
composite = new WorkFlow();
composite.setName( " composite " );
composite.setId( 100 );
wm.saveWorkFlow(composite);
// 修改开始结束节点的输入输出库所
sequence.getEnd().setType(TransitionType.NORMAL);
sequence.getEnd().setOutputs(concurrency.getStart().getInputs());
concurrency.getEnd().setType(TransitionType.NORMAL);
concurrency.getEnd().setOutputs(choose.getStart().getInputs());
composite.setStart(sequence.getStart());
composite.setEnd(choose.getEnd());
List < Transition > transitions = new ArrayList < Transition > ();
transitions.addAll(sequence.getTransitions());
transitions.addAll(concurrency.getTransitions());
transitions.addAll(choose.getTransitions());
composite.setTransitions(transitions);