Written in reply to a forum post.
This is a more complex example of a flow.
There are 3 participants involved : role-alpha, role-bravo, role-charly. Each of the participant receives the workitem, does its job with it and by setting the field 'agreed' and/or 'end' determine
Since OpenWFE 1.6.1, a 'cursor' expression does the job. Simply write
<cursor> <participant ref="role-alpha" /> <participant ref="role-bravo" /> <participant ref="role-charly" /> </cursor>
Please note the "/" slash in front of "participant_list", it indicates that this is a global variable (that the whole flow instance shares).
As implemented, once the flow touches participant n, it cannot rewind to participant n-2, ie if flow reached role-charly, it will not be possible to reach role-alpha again by 'unagreeing'...
Further down this page, Reject nodes (v2) fixes this problem.
<?xml version="1.0" encoding="UTF-8"?>
<process-definition name="flow_with_reject_nodes" revision="0.01" >
<!-- body -->
<sequence>
<!-- some initialization -->
<set variable="participant_list" value="role-alpha, role-bravo, role-ch
arly" />
<set variable="node_participant" value="" />
<set field="agreed" value="true" type="boolean" />
<set field="end" value="false" type="boolean" />
<!-- launch the thing -->
<node/>
<!-- equivalent to :
<subprocess ref="node" />
-->
</sequence>
<!-- subprocesses -->
<process-definition name="node">
<sequence>
<set variable="prev_participant" value="${node_participant}" />
<set variable="node_participant" value="${call:car(${participant_li
st})}" />
<if>
<not>
<equals variable-value="node_participant" other-value="" />
</not>
<!-- then -->
<participant ref="${node_participant}" />
</if>
<if>
<equals field-value="agreed" other-value="true" />
<!-- then -->
<set variable="/participant_list" value="${call:cdr(${participa
nt_list})}" />
<!-- else -->
<set variable="/participant_list" value="${prev_participant}, $
{participant_list}" />
</if>
<!-- some debugging -->
<set field="(debug) participant list" value="${participant_list}" /
>
<if>
<and>
<not>
<equals field-value="end" other-value="true" />
</not>
<not>
<equals variable-value="node_participant" other-value="
" />
</not>
</and>
<!-- then continue processing -->
<node/>
</if>
<!-- exit flow -->
</sequence>
</process-definition>
</process-definition>This second version keeps a variable position indicating where in the sequence of nodes the flow is located.
It is thus possible to revert to the first role in the sequence of nodes if all the participants disagree with the workitem.
<?xml version="1.0" encoding="UTF-8"?>
<process-definition name="flow_with_reject_nodes" revision="0.02" >
<!-- body -->
<sequence>
<!-- some initialization -->
<set variable="participant_list" value="role-alpha, role-bravo, role-ch
arly" />
<set variable="/position" value="0" />
<set field="agreed" value="true" type="boolean" />
<set field="end" value="false" type="boolean" />
<!-- launch the thing -->
<node/>
<!-- equivalent to :
<subprocess ref="node" />
-->
</sequence>
<!-- subprocesses -->
<process-definition name="node">
<sequence>
<set variable="node_participant" value="${call:elt('${position}', '
${participant_list}')}" />
<if>
<not>
<equals variable-value="node_participant" other-value="" />
</not>
<!-- then -->
<sequence>
<participant ref="${node_participant}" />
<if>
<equals field-value="agreed" other-value="false" />
<!-- then -->
<inc variable="/position" value="-1" />
<!-- else -->
<inc variable="/position" value="1" />
</if>
<if>
<lesser-than variable-value="//position" other-value="0
" />
<!-- then enforce low limit at 0 -->
<set variable="/position" value="0" />
</if>
<!--<set field="(debug) position" value="${//position}" />-
->
<if>
<not>
<equals field-value="end" other-value="true" />
</not>
<!-- then -->
<node />
</if>
</sequence>
</if>
<!-- exit flow -->
</sequence>
</process-definition>
</process-definition>