`
chenjin
  • 浏览: 159527 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

jbpm 与 工作流模式 鉴别器(Discriminator)

    博客分类:
  • java
阅读更多
鉴别器(Discriminator)
Description :    The discriminator is a point in a workow process that waits for one of the
incoming branches to complete before activating the subsequent activity. From that moment on
it waits for all remaining branches to complete and \ignores" them. Once all incoming branches
have been triggered, it resets itself so that it can be triggered again (which is important
otherwise it could not really be used in the context of a loop).


描述:多分支汇聚的时候,只有一个分支可以激活所属任务,这个任务激活以后,其他分支的
到来都会被忽略。
java 代码
 
  1. /* 
  2.  * JBoss, Home of Professional Open Source 
  3.  * Copyright 2005, JBoss Inc., and individual contributors as indicated 
  4.  * by the @authors tag. See the copyright.txt in the distribution for a 
  5.  * full listing of individual contributors. 
  6.  * 
  7.  * This is free software; you can redistribute it and/or modify it 
  8.  * under the terms of the GNU Lesser General Public License as 
  9.  * published by the Free Software Foundation; either version 2.1 of 
  10.  * the License, or (at your option) any later version. 
  11.  * 
  12.  * This software is distributed in the hope that it will be useful, 
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
  15.  * Lesser General Public License for more details. 
  16.  * 
  17.  * You should have received a copy of the GNU Lesser General Public 
  18.  * License along with this software; if not, write to the Free 
  19.  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 
  20.  * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 
  21.  */  
  22. package org.jbpm.jpdl.patterns;  
  23.   
  24. import junit.framework.TestCase;  
  25.   
  26. import org.jbpm.graph.def.ProcessDefinition;  
  27. import org.jbpm.graph.exe.Token;  
  28. import org.jbpm.graph.node.Join;  
  29.   
  30. /** 
  31.  * http://is.tm.tue.nl/research/patterns/download/swf/pat_9.swf 
  32.  */  
  33. public class Wfp09DiscriminatorTest extends TestCase {  
  34.   
  35.   private static ProcessDefinition discriminatorProcessDefinition = createDiscriminatorProcessDefinition();  
  36.   
  37.   public static ProcessDefinition createDiscriminatorProcessDefinition() {  
  38.     ProcessDefinition pd = createSynchronizingDiscriminatorProcessDefinition();  
  39.       
  40.     // configure the join as a discriminator  
  41.     Join join = (Join) pd.getNode("discriminator");  
  42.     join.setDiscriminator(true);  
  43.       
  44.     return pd;  
  45.   }  
  46.   
  47.   private static ProcessDefinition synchronizingdiscriminatorProcessDefinition = createSynchronizingDiscriminatorProcessDefinition();  
  48.   
  49.   public static ProcessDefinition createSynchronizingDiscriminatorProcessDefinition() {  
  50.     ProcessDefinition processDefinition = ProcessDefinition.parseXmlString(  
  51.       "<process-definition>" +  
  52.       "  <start-state name='start'>" +  
  53.       "    <transition to='a' />" +  
  54.       "  </start-state>" +  
  55.       "  <state name='a'>" +  
  56.       "    <transition to='multichoice' />" +  
  57.       "  </state>" +  
  58.       "  <fork name='multichoice'>" +  
  59.       "    <script>" +  
  60.       "      <variable name='transitionNames' access='write' />" +  
  61.       "      <expression>" +  
  62.       "        transitionNames = new ArrayList();" +  
  63.       "        if ( scenario == 1 ) {" +  
  64.       "          transitionNames.add( \"to b\" );" +  
  65.       "        } else if ( scenario == 2 ) {" +  
  66.       "          transitionNames.add( \"to c\" );" +  
  67.       "        } else if ( scenario >= 3 ) {" +  
  68.       "          transitionNames.add( \"to b\" );" +  
  69.       "          transitionNames.add( \"to c\" );" +  
  70.       "        }" +  
  71.       "      </expression>" +  
  72.       "    </script>" +  
  73.       "    <transition name='to b' to='b' />" +  
  74.       "    <transition name='to c' to='c' />" +  
  75.       "  </fork>" +  
  76.       "  <state name='b'>" +  
  77.       "    <transition to='discriminator' />" +  
  78.       "  </state>" +  
  79.       "  <state name='c'>" +  
  80.       "    <transition to='discriminator' />" +  
  81.       "  </state>" +  
  82.       "  <join name='discriminator'>" +  
  83.       "    <transition to='d' />" +  
  84.       "  </join>" +  
  85.       "  <state name='d' />" +  
  86.       "</process-definition>"  
  87.     );  
  88.             
  89.     return processDefinition;  
  90.   }  
  91.   
  92.   public void testDiscriminatorScenario1() {  
  93.     ProcessDefinition pd = discriminatorProcessDefinition;  
  94.     Token root = Wfp06MultiChoiceTest.executeScenario(pd,1);  
  95.     Token tokenB = root.getChild("to b");   
  96.   
  97.     tokenB.signal();  
  98.     assertSame( pd.getNode("d"), root.getNode() );  
  99.     assertSame( pd.getNode("discriminator"), tokenB.getNode() );  
  100.   }  
  101.     
  102.   public void testDiscriminatorScenario2() {  
  103.     ProcessDefinition pd = discriminatorProcessDefinition;  
  104.     Token root = Wfp06MultiChoiceTest.executeScenario(pd,2);  
  105.     Token tokenC = root.getChild("to c");   
  106.   
  107.     tokenC.signal();  
  108.     assertSame( pd.getNode("d"), root.getNode() );  
  109.     assertSame( pd.getNode("discriminator"), tokenC.getNode() );  
  110.   }  
  111.     
  112.   public void testDiscriminatorScenario3() {  
  113.     ProcessDefinition pd = discriminatorProcessDefinition;  
  114.     Token root = Wfp06MultiChoiceTest.executeScenario(pd,3);  
  115.     Token tokenB = root.getChild("to b");   
  116.     Token tokenC = root.getChild("to c");   
  117.   
  118.     tokenB.signal();  
  119.     assertSame( pd.getNode("d"), root.getNode() );  
  120.     assertSame( pd.getNode("discriminator"), tokenB.getNode() );  
  121.     assertSame( pd.getNode("c"), tokenC.getNode() );  
  122.   
  123.     tokenC.signal();  
  124.     assertSame( pd.getNode("d"), root.getNode() );  
  125.     assertSame( pd.getNode("discriminator"), tokenB.getNode() );  
  126.     assertSame( pd.getNode("discriminator"), tokenC.getNode() );  
  127.   }  
  128.     
  129.   public void testDiscriminatorScenario4() {  
  130.     ProcessDefinition pd = discriminatorProcessDefinition;  
  131.     Token root = Wfp06MultiChoiceTest.executeScenario(pd,4);  
  132.     Token tokenB = root.getChild("to b");   
  133.     Token tokenC = root.getChild("to c");   
  134.   
  135.     tokenC.signal();  
  136.     assertSame( pd.getNode("d"), root.getNode() );  
  137.     assertSame( pd.getNode("b"), tokenB.getNode() );  
  138.     assertSame( pd.getNode("discriminator"), tokenC.getNode() );  
  139.   
  140.     tokenB.signal();  
  141.     assertSame( pd.getNode("d"), root.getNode() );  
  142.     assertSame( pd.getNode("discriminator"), tokenB.getNode() );  
  143.     assertSame( pd.getNode("discriminator"), tokenC.getNode() );  
  144.   }  
  145.   
  146.   public void testDiscriminatorScenario5() {  
  147.     ProcessDefinition pd = synchronizingdiscriminatorProcessDefinition;  
  148.     Token root = Wfp06MultiChoiceTest.executeScenario(pd,5);  
  149.     Token tokenB = root.getChild("to b");   
  150.     Token tokenC = root.getChild("to c");   
  151.   
  152.     tokenB.signal();  
  153.     assertSame( pd.getNode("multichoice"), root.getNode() );  
  154.     assertSame( pd.getNode("discriminator"), tokenB.getNode() );  
  155.     assertSame( pd.getNode("c"), tokenC.getNode() );  
  156.   
  157.     tokenC.signal();  
  158.     assertSame( pd.getNode("d"), root.getNode() );  
  159.     assertSame( pd.getNode("discriminator"), tokenB.getNode() );  
  160.     assertSame( pd.getNode("discriminator"), tokenC.getNode() );  
  161.   }  
  162.   
  163.   public void testDiscriminatorScenario6() {  
  164.     ProcessDefinition pd = synchronizingdiscriminatorProcessDefinition;  
  165.     Token root = Wfp06MultiChoiceTest.executeScenario(pd,3);  
  166.     Token tokenB = root.getChild("to b");   
  167.     Token tokenC = root.getChild("to c");   
  168.   
  169.     tokenC.signal();  
  170.     assertSame( pd.getNode("multichoice"), root.getNode() );  
  171.     assertSame( pd.getNode("b"), tokenB.getNode() );  
  172.     assertSame( pd.getNode("discriminator"), tokenC.getNode() );  
  173.   
  174.     tokenB.signal();  
  175.     assertSame( pd.getNode("d"), root.getNode() );  
  176.     assertSame( pd.getNode("discriminator"), tokenB.getNode() );  
  177.     assertSame( pd.getNode("discriminator"), tokenC.getNode() );  
  178.   }  
  179. }  


流程定义文件

xml 代码
 
  1. <process-definition>  
  2.   <start-state name='start'>  
  3.     <transition to='a' />  
  4.   </start-state>  
  5.   <state name='a'>  
  6.     <transition to='multichoice' />  
  7.   </state>  
  8.   <fork name='multichoice'>  
  9.     <script>  
  10.       <variable name='transitionNames' access='write' />  
  11.       <expression>  
  12.         transitionNames = new ArrayList();  
  13.         if ( scenario == 1 ) {  
  14.           transitionNames.add( \"to b\" );  
  15.         } else if ( scenario == 2 ) {  
  16.           transitionNames.add( \"to c\" );  
  17.         } else if ( scenario >= 3 ) {  
  18.           transitionNames.add( \"to b\" );  
  19.           transitionNames.add( \"to c\" );  
  20.         }  
  21.       </expression>  
  22.     </script>  
  23.     <transition name='to b' to='b' />  
  24.     <transition name='to c' to='c' />  
  25.   </fork>  
  26.   <state name='b'>  
  27.     <transition to='discriminator' />  
  28.   </state>  
  29.   <state name='c'>  
  30.     <transition to='discriminator' />  
  31.   </state>  
  32.   <join name='discriminator'>  
  33.     <transition to='d' />  
  34.   </join>  
  35.   <state name='d' />  
  36. </process-definition>  




testDiscriminatorScenario1()

节点执行顺序

    start --> a --> multichoice --> b --> discriminator --> d

testDiscriminatorScenario2()

节点执行顺序

    start --> a --> multichoice --> c --> discriminator --> d

testDiscriminatorScenario3()

节点执行顺序

    start --> a --> multichoice --> b --> discriminator --> d
                multichoice --> c --> discriminator(废弃)


testDiscriminatorScenario4()

节点执行顺序

    start --> a --> multichoice --> b --> discriminator(废弃) --> d
                multichoice --> c --> discriminator


testDiscriminatorScenario5()

节点执行顺序

    start --> a --> multichoice --> b --> discriminator --> d
                multichoice --> c --> discriminator


testDiscriminatorScenario6()

节点执行顺序

    start --> a --> multichoice --> b --> discriminator --> d
                multichoice --> c --> discriminator
分享到:
评论
4 楼 flyffa 2008-12-07  
sorry,应该是更符合Structured Synchronizing Merge模式
3 楼 flyffa 2008-12-07  
这个模式好像实现的有问题吧,按照workflow pattern的说法,应该是b,c两个分支无论谁先到discriminator,都直接往下走到d,而不是在这里等待吧。你这个做法更符合Multiple Merge模式。
2 楼 lovevirus 2006-12-18  
假如你state是taskNode,那么是否要把taskNode中的taskInstance删掉,按平时的理解,如果废弃,那么看不到废弃那分支的任务了,比如请假流程,如果我请假取消,那么另外一个分支中的核实任务应该取消掉吧
1 楼 coolfish 2006-12-15  
jbpm演示的不错,不过这个流程只执行在内存里.象第9个用到join的isDiscriminator属性,第10个模式用到的nOutOfM 属性都没有持久化,在实际场景中肯定用的麻烦了

相关推荐

Global site tag (gtag.js) - Google Analytics