[jbpm-commits] JBoss JBPM SVN: r2457 - in projects/spec/trunk/modules: cts and 4 other directories.

do-not-reply at jboss.org do-not-reply at jboss.org
Wed Oct 1 09:18:18 EDT 2008


Author: thomas.diesler at jboss.com
Date: 2008-10-01 09:18:18 -0400 (Wed, 01 Oct 2008)
New Revision: 2457

Added:
   projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ComplexGatewayImpl.java
   projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ExclusiveGatewayImpl.java
   projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/InclusiveGatewayImpl.java
   projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ParallelGatewayImpl.java
Modified:
   projects/spec/trunk/modules/api/src/main/java/org/jbpm/api/model/builder/ProcessBuilder.java
   projects/spec/trunk/modules/cts/pom.xml
   projects/spec/trunk/modules/cts/src/test/java/org/jbpm/test/cts/gateway/exclusive/ExclusiveGatewayMergeTest.java
   projects/spec/trunk/modules/cts/src/test/java/org/jbpm/test/cts/gateway/exclusive/ExclusiveGatewaySplitTest.java
   projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ExpressionImpl.java
   projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/GatewayImpl.java
   projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/NodeImpl.java
   projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/builder/GatewayBuilderImpl.java
   projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/builder/ProcessBuilderImpl.java
   projects/spec/trunk/modules/impl/src/main/resources/jbpm-cfg-beans.xml
Log:
Gateway split tests - pass

Modified: projects/spec/trunk/modules/api/src/main/java/org/jbpm/api/model/builder/ProcessBuilder.java
===================================================================
--- projects/spec/trunk/modules/api/src/main/java/org/jbpm/api/model/builder/ProcessBuilder.java	2008-10-01 03:42:57 UTC (rev 2456)
+++ projects/spec/trunk/modules/api/src/main/java/org/jbpm/api/model/builder/ProcessBuilder.java	2008-10-01 13:18:18 UTC (rev 2457)
@@ -24,7 +24,9 @@
 //$Id$
 
 import org.jbpm.api.model.Message;
+import org.jbpm.api.model.Node;
 import org.jbpm.api.model.Process;
+import org.jbpm.api.model.Property;
 import org.jbpm.api.model.Assignment.AssignTime;
 import org.jbpm.api.model.Event.EventDetailType;
 import org.jbpm.api.model.Expression.ExpressionLanguage;

Modified: projects/spec/trunk/modules/cts/pom.xml
===================================================================
--- projects/spec/trunk/modules/cts/pom.xml	2008-10-01 03:42:57 UTC (rev 2456)
+++ projects/spec/trunk/modules/cts/pom.xml	2008-10-01 13:18:18 UTC (rev 2457)
@@ -71,15 +71,10 @@
         <configuration>
           <excludes>
             <exclude>org/jbpm/test/cts/gateway/exclusive/ExclusiveGatewayMergeTest.java</exclude>
-            <exclude>org/jbpm/test/cts/gateway/exclusive/ExclusiveGatewaySplitTest.java</exclude>
             <exclude>org/jbpm/test/cts/gateway/inclusive/InclusiveGatewayMergeTest.java</exclude>
-            <exclude>org/jbpm/test/cts/gateway/inclusive/InclusiveGatewaySplitTest.java</exclude>
             <exclude>org/jbpm/test/cts/gateway/parallel/ParallelGatewayMergeTest.java</exclude>
-            <exclude>org/jbpm/test/cts/gateway/parallel/ParallelGatewaySplitTest.java</exclude>
             <exclude>org/jbpm/test/cts/node/NodeInputSetTest.java</exclude>
             <exclude>org/jbpm/test/cts/node/NodeOutputSetTest.java</exclude>
-            <exclude>org/jbpm/test/pattern/control/exclusivechoice/ExclusiveChoiceTest.java</exclude>
-            <exclude>org/jbpm/test/pattern/control/multichoice/MultiChoiceTest.java</exclude>
             <exclude>org/jbpm/test/pattern/control/parallelsplit/ParallelSplitTest.java</exclude>
             <exclude>org/jbpm/test/pattern/control/simplemerge/SimpleMergeTest.java</exclude>
             <exclude>org/jbpm/test/pattern/control/synchronization/SynchronizationTest.java</exclude>

Modified: projects/spec/trunk/modules/cts/src/test/java/org/jbpm/test/cts/gateway/exclusive/ExclusiveGatewayMergeTest.java
===================================================================
--- projects/spec/trunk/modules/cts/src/test/java/org/jbpm/test/cts/gateway/exclusive/ExclusiveGatewayMergeTest.java	2008-10-01 03:42:57 UTC (rev 2456)
+++ projects/spec/trunk/modules/cts/src/test/java/org/jbpm/test/cts/gateway/exclusive/ExclusiveGatewayMergeTest.java	2008-10-01 13:18:18 UTC (rev 2457)
@@ -29,7 +29,9 @@
 import org.jbpm.api.model.Message;
 import org.jbpm.api.model.Process;
 import org.jbpm.api.model.Signal;
+import org.jbpm.api.model.Assignment.AssignTime;
 import org.jbpm.api.model.Event.EventDetailType;
+import org.jbpm.api.model.Expression.ExpressionLanguage;
 import org.jbpm.api.model.Gateway.GatewayType;
 import org.jbpm.api.model.Signal.SignalType;
 import org.jbpm.api.model.builder.EventBuilder;
@@ -168,12 +170,12 @@
     EventBuilder eventBuilder = procBuilder.addProcess(getName()).addStartEvent("StartA", EventDetailType.Signal);
     eventBuilder.addSignalRef(SignalType.SYSTEM_START_TRIGGER, "A");
     TaskBuilder taskBuilder = procBuilder.addSequenceFlow("TaskA").addTask("TaskA");
-    //taskBuilder.addAssignment(AssignTime.Start, ExpressionLanguage.MVEL, "'TaskA'", "taskValue");
+    taskBuilder.addNodeAssignment(AssignTime.Start, ExpressionLanguage.MVEL, "'TaskA'", "taskValue");
     taskBuilder.addSequenceFlow("Merge");
     eventBuilder = procBuilder.addStartEvent("StartB", EventDetailType.Signal);
     eventBuilder.addSignalRef(SignalType.SYSTEM_START_TRIGGER, "B");
     taskBuilder = procBuilder.addSequenceFlow("TaskB").addTask("TaskB");
-    //taskBuilder.addAssignment(AssignTime.Start, ExpressionLanguage.MVEL, "'TaskB'", "taskValue");
+    taskBuilder.addNodeAssignment(AssignTime.Start, ExpressionLanguage.MVEL, "'TaskB'", "taskValue");
     taskBuilder.addSequenceFlow("Merge");
     procBuilder.addGateway("Merge", GatewayType.Exclusive).addSequenceFlow("End");
     procBuilder.addEndEvent("End", EventDetailType.Message).addMessageRef("EndMessage");

Modified: projects/spec/trunk/modules/cts/src/test/java/org/jbpm/test/cts/gateway/exclusive/ExclusiveGatewaySplitTest.java
===================================================================
--- projects/spec/trunk/modules/cts/src/test/java/org/jbpm/test/cts/gateway/exclusive/ExclusiveGatewaySplitTest.java	2008-10-01 03:42:57 UTC (rev 2456)
+++ projects/spec/trunk/modules/cts/src/test/java/org/jbpm/test/cts/gateway/exclusive/ExclusiveGatewaySplitTest.java	2008-10-01 13:18:18 UTC (rev 2457)
@@ -83,7 +83,7 @@
     try
     {
       proc.waitForEnd();
-      fail("No gate defained for foo==10");
+      fail("No gate defined for foo==10");
     }
     catch (RuntimeException rte)
     {

Added: projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ComplexGatewayImpl.java
===================================================================
--- projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ComplexGatewayImpl.java	                        (rev 0)
+++ projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ComplexGatewayImpl.java	2008-10-01 13:18:18 UTC (rev 2457)
@@ -0,0 +1,68 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jbpm.ri.model;
+
+//$Id$
+
+import javax.persistence.Entity;
+
+import org.jbpm.api.NotImplementedException;
+import org.jbpm.api.model.Expression;
+
+/**
+ * A Complex Gateway handles situations that are not easily handled through the other types of Gateways. Complex
+ * Gateways can also be used to combine a set of linked simple Gateways into a single, more compact situation. Modelers
+ * can provide complex expressions that determine the merging and/or splitting behavior of the 
+ * 
+ * @author thomas.diesler at jboss.com
+ * @since 08-Jul-2008
+ */
+ at Entity(name = "ComplexGateway")
+public class ComplexGatewayImpl extends GatewayImpl
+{
+  private static final long serialVersionUID = 1L;
+
+  public ComplexGatewayImpl(String name)
+  {
+    super(name, GatewayType.Complex);
+  }
+
+  public GatewayType getGatewayType()
+  {
+    return GatewayType.Complex;
+  }
+
+  public Expression getIncommingCondition()
+  {
+    throw new NotImplementedException("JBPM-1636", "ComplexGateway incomming condition");
+  }
+
+  public Expression getOutgoingCondition()
+  {
+    throw new NotImplementedException("JBPM-1637", "ComplexGateway outgoing condition");
+  }
+  
+  public String toString()
+  {
+    return "ComplexGateway[" + getName() + "]";
+  }
+}
\ No newline at end of file


Property changes on: projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ComplexGatewayImpl.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Added: projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ExclusiveGatewayImpl.java
===================================================================
--- projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ExclusiveGatewayImpl.java	                        (rev 0)
+++ projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ExclusiveGatewayImpl.java	2008-10-01 13:18:18 UTC (rev 2457)
@@ -0,0 +1,213 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jbpm.ri.model;
+
+//$Id$
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.Entity;
+import javax.persistence.Transient;
+
+import org.jbpm.api.model.Expression;
+import org.jbpm.api.model.Node;
+import org.jbpm.api.model.SequenceFlow;
+import org.jbpm.api.model.SequenceFlow.ConditionType;
+import org.jbpm.api.runtime.ExecutionHandler;
+import org.jbpm.api.runtime.FlowHandler;
+import org.jbpm.api.runtime.Token;
+import org.jbpm.api.runtime.TokenExecutor;
+import org.jbpm.ri.runtime.ExpressionEvaluator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * A point in the workflow process where, based on a decision or workflow control data, one of several branches is
+ * chosen.
+ * 
+ * @author thomas.diesler at jboss.com
+ * @since 08-Jul-2008
+ */
+ at Entity(name = "ExclusiveGateway")
+public class ExclusiveGatewayImpl extends GatewayImpl
+{
+  private static final long serialVersionUID = 1L;
+
+  // provide logging
+  final static Logger log = LoggerFactory.getLogger(ExclusiveGatewayImpl.class);
+
+  @Transient
+  private Set<SequenceFlow> outstandingFlows;
+
+  public ExclusiveGatewayImpl(String name)
+  {
+    super(name, GatewayType.Exclusive);
+  }
+
+  @Override
+  protected ExecutionHandler getDefaultExecutionHandler()
+  {
+    final Node thisNode = this;
+    final ExecutionHandler superExecHandler = super.getDefaultExecutionHandler();
+    
+    return new ExecutionHandler()
+    {
+      private static final long serialVersionUID = 1L;
+
+      public void execute(Token token)
+      {
+        // Call the super default handler
+        superExecHandler.execute(token);
+        
+        // Multiple incomingFlows must be synchronized
+        if (outstandingFlows == null)
+          outstandingFlows = new HashSet<SequenceFlow>(inFlows);
+
+        SequenceFlow flow = token.getFlow();
+        outstandingFlows.remove(flow);
+      }
+      
+      @Override
+      public Node getNode()
+      {
+        return thisNode;
+      }
+
+      @Override
+      public void setNode(Node node)
+      {
+      }
+    };
+  }
+
+  @Override
+  protected FlowHandler getDefaultFlowHandler()
+  {
+    final Node thisNode = this;
+    return new FlowHandler()
+    {
+      private static final long serialVersionUID = 1L;
+
+      public void execute(TokenExecutor tokenExecutor, Token token)
+      {
+        Node sourceRef = token.getFlow().getSourceRef();
+        
+        // Schedule the first token that arrives
+        if (token == receivedTokens.get(0))
+        {
+          log.debug("Propagate token comming from: " + sourceRef);
+          SequenceFlow selectedGate = getSelectedGate(token);
+          tokenExecutor.move(token, selectedGate);
+        }
+        // Ignore all other tokens
+        else
+        {
+          log.debug("Ignore token comming from: " + sourceRef);
+          tokenExecutor.destroy(token);
+        }
+
+        // Reset the gateway
+        if (outstandingFlows.size() == 0)
+        {
+          reset();
+        }
+      }
+
+      @Override
+      public Node getNode()
+      {
+        return thisNode;
+      }
+
+      @Override
+      public void setNode(Node node)
+      {
+      }
+    };
+  }
+
+  @Override
+  protected void reset()
+  {
+    super.reset();
+    outstandingFlows = null;
+  }
+
+  // Get a single selected gate which' condition evaluates to TRUE
+  // Fall back to the default gate if there is one
+  // Choke if there is no selected gate
+  private SequenceFlow getSelectedGate(Token token)
+  {
+    SequenceFlow selectedGate = null;
+    for (SequenceFlow auxGate : getGates())
+    {
+      SequenceFlow seqFlow = auxGate;
+      if (seqFlow.getConditionType() == ConditionType.Expression)
+      {
+        Expression expr = seqFlow.getConditionExpression();
+        ExpressionEvaluator exprEvaluator = new ExpressionEvaluator(expr);
+        if ((Boolean)exprEvaluator.evaluateExpression(token))
+        {
+          selectedGate = auxGate;
+          break;
+        }
+      }
+    }
+
+    // Use to the default gate if there is one
+    if (selectedGate == null)
+    {
+      for (SequenceFlow auxGate : getGates())
+      {
+        SequenceFlow seqFlow = auxGate;
+        if (seqFlow.getConditionType() == ConditionType.Default)
+        {
+          selectedGate = auxGate;
+          break;
+        }
+      }
+    }
+
+    // Fallback to the single outgoing gate that is not conditional
+    if (selectedGate == null && getGates().size() == 1)
+    {
+      SequenceFlow auxGate = getGates().get(0);
+      SequenceFlow seqFlow = auxGate;
+      if (seqFlow.getConditionType() == ConditionType.None)
+      {
+        selectedGate = auxGate;
+      }
+    }
+
+    if (selectedGate == null)
+      throw new IllegalStateException("Cannot select applicable gate in: " + this);
+
+    return selectedGate;
+  }
+
+  public String toString()
+  {
+    return "ExclusiveGateway[" + getName() + "]";
+  }
+}
\ No newline at end of file


Property changes on: projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ExclusiveGatewayImpl.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Modified: projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ExpressionImpl.java
===================================================================
--- projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ExpressionImpl.java	2008-10-01 03:42:57 UTC (rev 2456)
+++ projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ExpressionImpl.java	2008-10-01 13:18:18 UTC (rev 2457)
@@ -58,6 +58,10 @@
     this.lang = lang;
   }
 
+  // Persistence ctor
+  protected ExpressionImpl()
+  {
+  }
 
   public ExpressionLanguage getExpressionLanguage()
   {

Modified: projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/GatewayImpl.java
===================================================================
--- projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/GatewayImpl.java	2008-10-01 03:42:57 UTC (rev 2456)
+++ projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/GatewayImpl.java	2008-10-01 13:18:18 UTC (rev 2457)
@@ -23,16 +23,28 @@
 
 //$Id$
 
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
 import javax.management.ObjectName;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.MappedSuperclass;
+import javax.persistence.Transient;
 
 import org.jbpm.api.Constants;
+import org.jbpm.api.client.ProcessEngine;
 import org.jbpm.api.model.Gateway;
+import org.jbpm.api.model.Node;
 import org.jbpm.api.model.SequenceFlow;
+import org.jbpm.api.model.Signal;
 import org.jbpm.api.model.SequenceFlow.ConditionType;
 import org.jbpm.api.model.builder.ObjectNameFactory;
+import org.jbpm.api.runtime.ExecutionHandler;
+import org.jbpm.api.runtime.SignalHandler;
+import org.jbpm.api.runtime.Token;
+import org.jbpm.api.service.SignalService;
 import org.jbpm.ri.model.builder.MultipleInFlowSupport;
 import org.jbpm.ri.model.builder.MultipleOutFlowSupport;
 
@@ -43,14 +55,27 @@
  * @author thomas.diesler at jboss.com
  * @since 08-Jul-2008
  */
+ at MappedSuperclass
 public abstract class GatewayImpl extends NodeImpl implements Gateway, MultipleOutFlowSupport, MultipleInFlowSupport
 {
   // provide serial version UID
   private static final long serialVersionUID = 1L;
   
-  public GatewayImpl(String name)
+  @Enumerated(EnumType.STRING)
+  protected GatewayType gatewayType;
+  
+  // The list of flows from which a token is expected
+  @Transient
+  protected List<SequenceFlow> expectedFlows;
+  
+  // The list of received tokens
+  @Transient
+  protected List<Token> receivedTokens;
+  
+  public GatewayImpl(String name, GatewayType gatewayType)
   {
     super(name);
+    this.gatewayType = gatewayType;
   }
 
   @Override
@@ -62,6 +87,24 @@
     return oname;
   }
   
+  @Override
+  public GatewayType getGatewayType()
+  {
+    return gatewayType;
+  }
+  
+  @Override
+  public void addOutFlow(SequenceFlowImpl outFlow)
+  {
+    outFlows.add(outFlow);
+  }
+
+  @Override
+  public void addInFlow(SequenceFlowImpl inFlow)
+  {
+    inFlows.add(inFlow);
+  }
+  
   public List<SequenceFlow> getGates()
   {
     return Collections.unmodifiableList(outFlows);
@@ -94,4 +137,92 @@
     }
     return gate;
   }
+  
+  protected void reset()
+  {
+    expectedFlows = null;
+    receivedTokens = null;
+  }
+
+  @Override
+  protected ExecutionHandler getDefaultExecutionHandler()
+  {
+    final Node thisNode = this;
+    return new ExecutionHandler()
+    {
+      private static final long serialVersionUID = 1L;
+
+      public void execute(Token token)
+      {
+        // Initialize the gateway
+        if (expectedFlows == null)
+        {
+          expectedFlows = new ArrayList<SequenceFlow>(inFlows);
+          receivedTokens = new ArrayList<Token>();
+        }
+        
+        // Check that token from flow is valid
+        SequenceFlow flow = token.getFlow();
+        if (expectedFlows.contains(flow) == false)
+          throw new IllegalStateException("Unexpected token from: " + flow);
+        
+        // Call custom execution handler
+        ExecutionHandler exHandler = getExecutionHandler(false);
+        if (exHandler != null)
+          exHandler.execute(token);
+
+        // Remove the flow from the expected list  
+        expectedFlows.remove(flow);
+        
+        // Store the received token for processing in the FlowHandler
+        receivedTokens.add(token);
+      }
+      
+      @Override
+      public Node getNode()
+      {
+        return thisNode;
+      }
+
+      @Override
+      public void setNode(Node node)
+      {
+      }
+    };
+  }
+
+  @Override
+  protected SignalHandler getDefaultSignalHandler()
+  {
+    final Node thisNode = this;
+    return new SignalHandler()
+    {
+      private static final long serialVersionUID = 1L;
+      
+      ProcessEngine engine = getProcess().getProcessEngine();
+      SignalService sigService = engine.getService(SignalService.class);
+      
+      public void throwEnterSignal(Token token)
+      {
+        Signal signal = new Signal(getKey(), Signal.SignalType.SYSTEM_GATEWAY_ENTER);
+        sigService.throwSignal(signal);
+      }
+
+      public void throwExitSignal(Token token)
+      {
+        Signal signal = new Signal(getKey(), Signal.SignalType.SYSTEM_GATEWAY_EXIT);
+        sigService.throwSignal(signal);
+      }
+      
+      @Override
+      public Node getNode()
+      {
+        return thisNode;
+      }
+      @Override
+      public void setNode(Node node)
+      {
+      }
+    };
+  }
 }
\ No newline at end of file

Added: projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/InclusiveGatewayImpl.java
===================================================================
--- projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/InclusiveGatewayImpl.java	                        (rev 0)
+++ projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/InclusiveGatewayImpl.java	2008-10-01 13:18:18 UTC (rev 2457)
@@ -0,0 +1,195 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jbpm.ri.model;
+
+//$Id$
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.persistence.Entity;
+
+import org.jbpm.api.model.Expression;
+import org.jbpm.api.model.Expression.ExpressionLanguage;
+import org.jbpm.api.model.Node;
+import org.jbpm.api.model.SequenceFlow;
+import org.jbpm.api.model.SequenceFlow.ConditionType;
+import org.jbpm.api.runtime.ExecutionContext;
+import org.jbpm.api.runtime.FlowHandler;
+import org.jbpm.api.runtime.Token;
+import org.jbpm.api.runtime.TokenExecutor;
+import org.jbpm.api.runtime.Attachments.Key;
+import org.mvel.MVEL;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This Decision represents a branching point where Alternatives are based on conditional expressions contained within
+ * outgoing Sequence Flow. However, in this case, the True evaluation of one condition expression does not exclude the
+ * evaluation of other condition expressions. All Sequence Flow with a True evaluation will be traversed by a Token.
+ * 
+ * @author thomas.diesler at jboss.com
+ * @since 08-Jul-2008
+ */
+ at Entity(name = "InclusiveGateway")
+public class InclusiveGatewayImpl extends GatewayImpl
+{
+  private static final long serialVersionUID = 1L;
+  
+  // provide logging
+  final static Logger log = LoggerFactory.getLogger(InclusiveGatewayImpl.class);
+
+  public InclusiveGatewayImpl(String name)
+  {
+    super(name, GatewayType.Inclusive);
+  }
+  
+  @Override
+  protected FlowHandler getDefaultFlowHandler()
+  {
+    final Node thisNode = this;
+    return new FlowHandler()
+    {
+      private static final long serialVersionUID = 1L;
+
+      public void execute(TokenExecutor tokenExecutor, Token token)
+      {
+        Node sourceRef = token.getFlow().getSourceRef();
+        log.debug("Propagate token comming from: " + sourceRef);
+
+        // Get the applicable gates
+        List<SequenceFlow> applicableGates = getApplicableGates(token);
+        log.debug("applicableGates: " + applicableGates);
+
+        if (applicableGates.size() == 1)
+        {
+          SequenceFlow outFlow = applicableGates.get(0);
+          tokenExecutor.move(token, outFlow);
+        }
+        else
+        {
+          List<Token> outTokens = new ArrayList<Token>();
+          for (SequenceFlow auxGate : applicableGates)
+          {
+            SequenceFlow outFlow = auxGate;
+            Token outToken = token.copyToken();
+            tokenExecutor.create(outToken, outFlow);
+            outTokens.add(outToken);
+          }
+          for (Token outToken : outTokens)
+          {
+            tokenExecutor.start(outToken);
+          }
+        }
+
+        // Destroy the incomming token if there are
+        // more than one applicable gates
+        if (applicableGates.size() > 1)
+          tokenExecutor.destroy(token);
+      }
+
+      @Override
+      public Node getNode()
+      {
+        return thisNode;
+      }
+
+      @Override
+      public void setNode(Node node)
+      {
+      }
+    };
+  }
+
+  // Get applicable gates which' condition evaluates to TRUE
+  // Fall back to the default gate if there is one
+  // Choke if there is no applicable gate
+  private List<SequenceFlow> getApplicableGates(Token token)
+  {
+    List<SequenceFlow> applicableGates = new ArrayList<SequenceFlow>();
+    for (SequenceFlow auxGate : getGates())
+    {
+      SequenceFlow seqFlow = auxGate;
+      if (seqFlow.getConditionType() == ConditionType.Expression)
+      {
+        Expression expr = seqFlow.getConditionExpression();
+        if (expr.getExpressionLanguage() == ExpressionLanguage.MVEL)
+        {
+          String mvel = expr.getExpressionBody();
+          ExecutionContext exContext = token.getExecutionContext();
+          Map<String, Object> vars = new HashMap<String, Object>();
+          for (Key key : exContext.getAttachmentKeys())
+          {
+            String name = key.getNamePart();
+            Object value = exContext.getAttachment(name);
+            vars.put(name, value);
+          }
+          Boolean result = (Boolean)MVEL.eval(mvel, vars);
+          if (result == true)
+          {
+            applicableGates.add(auxGate);
+          }
+        }
+        else
+        {
+          throw new IllegalStateException("Unsupported expression language: " + expr.getExpressionLanguage());
+        }
+      }
+    }
+
+    // Use to the default gate if there is one
+    if (applicableGates.size() == 0)
+    {
+      for (SequenceFlow auxGate : getGates())
+      {
+        SequenceFlow seqFlow = auxGate;
+        if (seqFlow.getConditionType() == ConditionType.Default)
+        {
+          applicableGates.add(auxGate);
+        }
+      }
+    }
+
+    // Fallback to the single outgoing gate that is not conditional
+    if (applicableGates.size() == 0 && getGates().size() == 1)
+    {
+      SequenceFlow auxGate = getGates().get(0);
+      SequenceFlow seqFlow = auxGate;
+      if (seqFlow.getConditionType() == ConditionType.None)
+      {
+        applicableGates.add(auxGate);
+      }
+    }
+
+    if (applicableGates.size() == 0)
+      throw new IllegalStateException("Cannot select applicable gate in: " + this);
+
+    return applicableGates;
+  }
+
+  public String toString()
+  {
+    return "InclusiveGateway[" + getName() + "]";
+  }
+}
\ No newline at end of file


Property changes on: projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/InclusiveGatewayImpl.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Modified: projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/NodeImpl.java
===================================================================
--- projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/NodeImpl.java	2008-10-01 03:42:57 UTC (rev 2456)
+++ projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/NodeImpl.java	2008-10-01 13:18:18 UTC (rev 2457)
@@ -392,14 +392,6 @@
       throw new InvalidProcessException("Dead end node: " + this);
   }
 
-  /**
-   * Reset the Node's state
-   */
-  public void reset()
-  {
-    // noting to do
-  }
-
   private void initFlow(Process proc, SequenceFlowImpl flow)
   {
     if (flow != null)

Added: projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ParallelGatewayImpl.java
===================================================================
--- projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ParallelGatewayImpl.java	                        (rev 0)
+++ projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ParallelGatewayImpl.java	2008-10-01 13:18:18 UTC (rev 2457)
@@ -0,0 +1,207 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jbpm.ri.model;
+
+//$Id$
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.persistence.Entity;
+import javax.persistence.Transient;
+
+import org.jbpm.api.model.Node;
+import org.jbpm.api.model.SequenceFlow;
+import org.jbpm.api.runtime.ExecutionHandler;
+import org.jbpm.api.runtime.FlowHandler;
+import org.jbpm.api.runtime.Token;
+import org.jbpm.api.runtime.TokenExecutor;
+import org.jbpm.ri.runtime.TokenImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * Parallel Gateway is required when two or more Activities need to be executed in parallel.
+ * 
+ * @author thomas.diesler at jboss.com
+ * @since 08-Jul-2008
+ */
+ at Entity(name = "ParallelGateway")
+public class ParallelGatewayImpl extends GatewayImpl
+{
+  private static final long serialVersionUID = 1L;
+
+  // provide logging
+  final static Logger log = LoggerFactory.getLogger(ParallelGatewayImpl.class);
+
+  @Transient
+  private Set<SequenceFlow> outstandingFlows;
+  
+  @Transient
+  private Set<Token> mergeTokens;
+
+  public ParallelGatewayImpl(String name)
+  {
+    super(name, GatewayType.Parallel);
+  }
+
+  @Override
+  protected ExecutionHandler getDefaultExecutionHandler()
+  {
+    final Node thisNode = this;
+    final ExecutionHandler superExecHandler = super.getDefaultExecutionHandler();
+    
+    return new ExecutionHandler()
+    {
+      private static final long serialVersionUID = 1L;
+
+      public void execute(Token token)
+      {
+        // Call the super default handler
+        superExecHandler.execute(token);
+        
+        // Multiple incomingFlows must be synchronized
+        if (outstandingFlows == null)
+        {
+          outstandingFlows = new HashSet<SequenceFlow>(inFlows);
+          mergeTokens = new HashSet<Token>();
+        }
+
+        SequenceFlow flow = token.getFlow();
+        outstandingFlows.remove(flow);
+        mergeTokens.add(token);
+      }
+      
+      @Override
+      public Node getNode()
+      {
+        return thisNode;
+      }
+
+      @Override
+      public void setNode(Node node)
+      {
+      }
+    };
+  }
+
+  @Override
+  protected FlowHandler getDefaultFlowHandler()
+  {
+    final Node thisNode = this;
+    return new FlowHandler()
+    {
+      private static final long serialVersionUID = 1L;
+
+      public void execute(TokenExecutor tokenExecutor, Token token)
+      {
+        // In any case, the incomming token is not propagated
+        tokenExecutor.suspend(token);
+        
+        // If the gateway has a single incomming flow the outgoing token is the incomming token 
+        Token outToken = (getInFlows().size() == 1 ? token : null);
+        
+        // The outgoing token is the merge of all incomming tokens
+        if (outToken == null)
+        {
+          // If there are no more outstanding flows
+          if (outstandingFlows.size() == 0)
+          {
+            // Merge the tokens together and submit the merged tokens
+            outToken = getMergedTokens();
+          }
+
+          // There are outstanding flows
+          else if (outstandingFlows.size() > 0)
+          {
+            log.debug("Waiting for " + outstandingFlows + " in gateway: " + this);
+          }
+        }
+        
+        // Schedule the outgoing token
+        if (outToken != null)
+        {
+          // Start a copy of the outgoing token for every gate
+          List<Token> outTokens = new ArrayList<Token>();
+          for(SequenceFlow auxGate : getGates())
+          {
+            SequenceFlow outFlow = auxGate;
+            outToken = outToken.copyToken();
+            tokenExecutor.create(outToken, outFlow);
+            outTokens.add(outToken);
+          }
+          for (Token auxToken : outTokens)
+          {
+            tokenExecutor.start(auxToken);
+          }
+          
+          // Destroy the received tokens
+          for (Token auxToken : receivedTokens)
+          {
+            tokenExecutor.destroy(auxToken);
+          }
+          
+          // Reset the gateway
+          reset();
+        }
+      }
+
+      @Override
+      public Node getNode()
+      {
+        return thisNode;
+      }
+
+      @Override
+      public void setNode(Node node)
+      {
+      }
+    };
+  }
+  
+  @Override
+  public void reset()
+  {
+    super.reset();
+    outstandingFlows = null;
+    mergeTokens = null;
+  }
+  
+  private Token getMergedTokens()
+  {
+    TokenImpl mergedToken = new TokenImpl(null);
+    for (Token auxToken : mergeTokens)
+    {
+      log.debug("mergeToken: " + auxToken);
+      mergedToken.mergeToken(auxToken);
+    }
+    return mergedToken;
+  }
+
+  public String toString()
+  {
+    return "ParallelGateway[" + getName() + "]";
+  }
+}
\ No newline at end of file


Property changes on: projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/ParallelGatewayImpl.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Modified: projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/builder/GatewayBuilderImpl.java
===================================================================
--- projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/builder/GatewayBuilderImpl.java	2008-10-01 03:42:57 UTC (rev 2456)
+++ projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/builder/GatewayBuilderImpl.java	2008-10-01 13:18:18 UTC (rev 2457)
@@ -23,10 +23,13 @@
 
 //$Id$
 
-import org.jbpm.api.NotImplementedException;
 import org.jbpm.api.model.Gateway;
 import org.jbpm.api.model.Expression.ExpressionLanguage;
+import org.jbpm.api.model.SequenceFlow.ConditionType;
 import org.jbpm.api.model.builder.GatewayBuilder;
+import org.jbpm.ri.model.ExpressionImpl;
+import org.jbpm.ri.model.GatewayImpl;
+import org.jbpm.ri.model.SequenceFlowImpl;
 
 /**
  * The GatewayBuilder can be used to build a {@link Gateway} dynamically.
@@ -43,16 +46,32 @@
 
   public GatewayBuilder addConditionalGate(String targetName, ExpressionLanguage exprLang, String exprBody)
   {
-    throw new NotImplementedException();
+    GatewayImpl gatewayImpl = getGateway();
+    SequenceFlowImpl outFlow = new SequenceFlowImpl(targetName, ConditionType.Expression, new ExpressionImpl(exprLang, exprBody));
+    gatewayImpl.addOutFlow(outFlow);
+    return this;
   }
 
   public GatewayBuilder addDefaultGate(String targetName)
   {
-    throw new NotImplementedException();
+    GatewayImpl gatewayImpl = getGateway();
+    SequenceFlowImpl outFlow = new SequenceFlowImpl(targetName, ConditionType.Default, null);
+    gatewayImpl.addOutFlow(outFlow);
+    return this;
   }
 
   public GatewayBuilder addGate(String targetName)
   {
-    throw new NotImplementedException();
+    GatewayImpl gatewayImpl = getGateway();
+    SequenceFlowImpl outFlow = new SequenceFlowImpl(targetName);
+    gatewayImpl.addOutFlow(outFlow);
+    return this;
   }
+
+  private GatewayImpl getGateway()
+  {
+    if (node instanceof GatewayImpl == false)
+      throw new IllegalStateException("Last added flow object is not an Gateway: " + node);
+    return (GatewayImpl)node;
+  }
 }
\ No newline at end of file

Modified: projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/builder/ProcessBuilderImpl.java
===================================================================
--- projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/builder/ProcessBuilderImpl.java	2008-10-01 03:42:57 UTC (rev 2456)
+++ projects/spec/trunk/modules/impl/src/main/java/org/jbpm/ri/model/builder/ProcessBuilderImpl.java	2008-10-01 13:18:18 UTC (rev 2457)
@@ -40,10 +40,14 @@
 import org.jbpm.api.runtime.FlowHandler;
 import org.jbpm.api.runtime.SignalHandler;
 import org.jbpm.ri.model.AssignmentImpl;
+import org.jbpm.ri.model.ComplexGatewayImpl;
 import org.jbpm.ri.model.EndEventImpl;
 import org.jbpm.ri.model.EventImpl;
+import org.jbpm.ri.model.ExclusiveGatewayImpl;
 import org.jbpm.ri.model.ExpressionImpl;
+import org.jbpm.ri.model.InclusiveGatewayImpl;
 import org.jbpm.ri.model.NodeImpl;
+import org.jbpm.ri.model.ParallelGatewayImpl;
 import org.jbpm.ri.model.ProcessImpl;
 import org.jbpm.ri.model.PropertyImpl;
 import org.jbpm.ri.model.ReceiveTaskImpl;
@@ -194,19 +198,19 @@
   {
     if (GatewayType.Exclusive == type)
     {
-      throw new NotImplementedException();
+      node = new ExclusiveGatewayImpl(name);
     }
     else if (GatewayType.Inclusive == type)
     {
-      throw new NotImplementedException();
+      node = new InclusiveGatewayImpl(name);
     }
     else if (GatewayType.Parallel == type)
     {
-      throw new NotImplementedException();
+      node = new ParallelGatewayImpl(name);
     }
     else if (GatewayType.Complex == type)
     {
-      throw new NotImplementedException();
+      node = new ComplexGatewayImpl(name);
     }
     addNode(node);
     return new GatewayBuilderImpl(this);

Modified: projects/spec/trunk/modules/impl/src/main/resources/jbpm-cfg-beans.xml
===================================================================
--- projects/spec/trunk/modules/impl/src/main/resources/jbpm-cfg-beans.xml	2008-10-01 03:42:57 UTC (rev 2456)
+++ projects/spec/trunk/modules/impl/src/main/resources/jbpm-cfg-beans.xml	2008-10-01 13:18:18 UTC (rev 2457)
@@ -24,9 +24,14 @@
       <property name="annotatedClasses">
         <set elementClass="java.lang.String">
           <value>org.jbpm.ri.model.AbstractElementImpl</value>
+          <value>org.jbpm.ri.model.ComplexGatewayImpl</value>
           <value>org.jbpm.ri.model.EndEventImpl</value>
+          <value>org.jbpm.ri.model.ExclusiveGatewayImpl</value>
+          <value>org.jbpm.ri.model.GatewayImpl</value>
+          <value>org.jbpm.ri.model.InclusiveGatewayImpl</value>
           <value>org.jbpm.ri.model.MessageImpl</value>
           <value>org.jbpm.ri.model.NodeImpl</value>
+          <value>org.jbpm.ri.model.ParallelGatewayImpl</value>
           <value>org.jbpm.ri.model.ParticipantImpl</value>
           <value>org.jbpm.ri.model.ProcessImpl</value>
           <value>org.jbpm.ri.model.PropertyImpl</value>




More information about the jbpm-commits mailing list