使用JBPM实现动态会签

原文出处:http://sqz.spaces.live.com/blog/cns!F319B9AFFE33A988!283.entry
目前有很多实现动态会签的文章,但是给人感觉不是很优雅,下面介绍一种实现方式。
1、流程定义文件:
<process-definition
  xmlns="urn:jbpm.org:jpdl-3.1"  name="foreach">
   <start-state name="start">
     <task name="one">
      </task>
      <transition name="a" to="foreachf"></transition>
   </start-state>
   <node name="foreachf">
      <action class="com.framework.workflow.jbpm.ForEachFork">
          <foreach>#{bpm_assignees}</foreach>
            <var>reviewer</var>
       </action>
      <transition name="review" to="review"></transition>
   </node>
   <task-node name="review">
       <task name="reviewTask">
       <assignment class="com.framework.workflow.jbpm.DefaultAssignment">
         <actor>#{reviewer}</actor>
       </assignment>
      </task>
      <transition name="reject" to="endreview">
        <action class="com.framework.workflow.jbpm.JoinEndForkedTokens" />      
      </transition>
      <transition name="approve" to="endreview"></transition>
   </task-node>
   <join name="endreview">
      <transition name="toend" to="end1"></transition>
   </join>
   <end-state name="end1"></end-state>
</process-definition>
在这里我们从node节点动态生成任务节点,会签时当有一个是reject时便结束所有节点。
2、动态派生ForEachFork代码:
public class ForEachFork implements ActionHandler
{
    private Element foreach;
    private String var;
//测试数据
    private static Map map = new HashMap();
    static{
    List list = new ArrayList();
     list.add("1234");
     list.add("2345");
     list.add("3456");
    map.put("bpm_assignees", list);
   }

    /**
     * <p>为每个元素创建一个分支</p>
     *
     * @param executionContext
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    public void execute(final ExecutionContext executionContext)
        throws Exception
    {
   
      
        if (foreach == null)
        {
            throw new WorkflowException("forEach has not been provided");
        }
    
        List forEachColl = null;
        String forEachCollStr = foreach.getTextTrim();
    
        if (forEachCollStr != null)
        {
            if (forEachCollStr.startsWith("#{"))
            {
                String expression = forEachCollStr.substring(2, forEachCollStr.length() -1);
                forEachColl = (List)map.get(expression);
         
            }
         
        }
      
        if (var == null || var.length() == 0)
        {
            throw new WorkflowException("forEach variable name has not been provided");
        }
      
        //
        // 创建分支
        //
      
        Token rootToken = executionContext.getToken();
        Node node = executionContext.getNode();
        List<ForkedTransition> forkTransitions = new ArrayList<ForkedTransition>();
        // 为每一个元素创建一个token
        for (int i = 0; i < node.getLeavingTransitions().size(); i++)
        {
            Transition transition = (Transition) node.getLeavingTransitions().get(i);
            for (int iVar = 0; iVar < forEachColl.size(); iVar++)
            {
                // 为每一个新token创建一个path
                String tokenName = getTokenName(rootToken, transition.getName(), iVar);
                Token loopToken = new Token(rootToken, tokenName);
                loopToken.setTerminationImplicit(true);
                executionContext.getJbpmContext().getSession().save(loopToken);
          
                //赋予一个新变量
                final ExecutionContext newExecutionContext = new ExecutionContext(loopToken);
                newExecutionContext.getContextInstance().createVariable(var, forEachColl.get(iVar), loopToken);
              
                // 记录下每一transition
                ForkedTransition forkTransition = new ForkedTransition();
                forkTransition.executionContext = newExecutionContext;
                forkTransition.transition = transition;
                forkTransitions.add(forkTransition);
            }
        }
        //
        // 转向下一个节点
        //
        for (ForkedTransition forkTransition : forkTransitions)
        {
            node.leave(forkTransition.executionContext, forkTransition.transition);
        }
    }
    /**
     * <p>获得分支token name</p>
     *
     * @param parent
     * @param transitionName
     * @return
     */
    protected String getTokenName(Token parent, String transitionName, int loopIndex)
    {
        String tokenName = null;
        if (transitionName != null)
        {
            if (!parent.hasChild(transitionName))
            {
                tokenName = transitionName;
            }
            else
            {
                int i = 2;
                tokenName = transitionName + Integer.toString(i);
                while (parent.hasChild(tokenName))
                {
                    i++;
                    tokenName = transitionName + Integer.toString(i);
                }
            }
        }
        else
        {
            // 没有转向
            int size = ( parent.getChildren()!=null ? parent.getChildren().size()+1 : 1 );
            tokenName = Integer.toString(size);
        }
        return tokenName + "." + loopIndex;
    }
  
  
  
    /**
     * Fork Transition
     */
    private class ForkedTransition
    {
        private ExecutionContext executionContext;
        private Transition transition;
    }
}
在具体应用中需要灵活的根据业务逻辑需要派生所需要的分支。
3、DefaultAssignment
进行简单的权限操作,这里面主要是将#{reviewer}值作为actorId进行设置
4、JoinEndForkedTokens结束所有节点
public class JoinEndForkedTokens implements ActionHandler
{
 
    public JoinEndForkedTokens()
    {
    }
    /* (non-Javadoc)
     * @see org.jbpm.graph.def.ActionHandler#execute(org.jbpm.graph.exe.ExecutionContext)
     */
    public void execute(ExecutionContext executionContext)
    {
        Token token = executionContext.getToken().getParent();
        Map childTokens = token.getActiveChildren();
        for (Object childToken : childTokens.values())
        {
            cancelToken(executionContext, (Token)childToken);
        }
  
    }
    /**
     * <p>取消 token</p>
     *
     * @param executionContext
     * @param token
     */
    protected void cancelToken(ExecutionContext executionContext, Token token)
    {
      
        Map childTokens = token.getActiveChildren();
        for (Object childToken : childTokens.values())
        {
            cancelToken(executionContext, (Token)childToken);
        }
      
        if (!token.hasEnded())
        {
            token.end(true);
        }
      
      
        cancelTokenTasks(executionContext, token);
    }
    /**
     * <p>结束token关联的任务</p>
     *
     * @param executionContext
     * @param token
     */
    protected void cancelTokenTasks(ExecutionContext executionContext, Token token)
    {
        TaskMgmtInstance tms = executionContext.getTaskMgmtInstance();
        Collection tasks = tms.getUnfinishedTasks(token);
        for (Object task : tasks)
        {
            TaskInstance taskInstance = (TaskInstance)task;
            if (taskInstance.isBlocking())
            {
                taskInstance.setBlocking(false);
            }
            if (taskInstance.isSignalling())
            {
                taskInstance.setSignalling(false);
            }
            if (!taskInstance.hasEnded())
            {
                taskInstance.end();
            }
        }
    }
}
结束所有分支节点任务,流向结束节点。

你可能感兴趣的:(Blog,jbpm)