[jbpm-commits] JBoss JBPM SVN: r1749 - in jbossbpm/spec/trunk/modules: api/src/main/java/org/jboss/bpm/client and 8 other directories.

do-not-reply at jboss.org do-not-reply at jboss.org
Tue Jul 29 10:55:19 EDT 2008


Author: thomas.diesler at jboss.com
Date: 2008-07-29 10:55:18 -0400 (Tue, 29 Jul 2008)
New Revision: 1749

Added:
   jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/runtime/
   jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/runtime/internal/
   jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/runtime/internal/TokenImpl.java
   jbossbpm/spec/trunk/modules/testsuite/src/test/java/org/jboss/bpm/samples/airticket/AvailabilityHandler.java
Modified:
   jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/BPMException.java
   jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/EngineShutdownException.java
   jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/InvalidProcessException.java
   jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/NameNotUniqueException.java
   jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/NotImplementedException.java
   jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/ProcessTimeoutException.java
   jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/client/MessageManager.java
   jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/model/TaskBuilder.java
   jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/runtime/FlowScheduler.java
   jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/runtime/MutableFlowScheduler.java
   jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/runtime/Token.java
   jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/client/internal/ExecutionManagerImpl.java
   jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/client/internal/ProcessManagerImpl.java
   jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/ActivityImpl.java
   jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/BPMNElementImpl.java
   jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/EndEventImpl.java
   jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/ExclusiveGatewayImpl.java
   jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/FlowObjectImpl.java
   jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/FlowSchedulerImpl.java
   jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/GatewayImpl.java
   jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/GraphicalElementImpl.java
   jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/InclusiveGatewayImpl.java
   jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/IntermediateEventImpl.java
   jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/ParallelGatewayImpl.java
   jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/ReceiveTaskImpl.java
   jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/SendTaskImpl.java
   jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/StartEventImpl.java
   jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/SubProcessImpl.java
   jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/TaskBuilderImpl.java
   jbossbpm/spec/trunk/modules/testsuite/src/test/java/org/jboss/bpm/samples/airticket/AirticketTest.java
Log:
Implement synchronizing merge

Modified: jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/BPMException.java
===================================================================
--- jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/BPMException.java	2008-07-29 13:25:51 UTC (rev 1748)
+++ jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/BPMException.java	2008-07-29 14:55:18 UTC (rev 1749)
@@ -29,10 +29,9 @@
  * @author thomas.diesler at jboss.com
  * @since 18-Jun-2008
  */
+ at SuppressWarnings("serial")
 public class BPMException extends RuntimeException
 {
-  private static final long serialVersionUID = 1L;
-
   public BPMException()
   {
     super();

Modified: jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/EngineShutdownException.java
===================================================================
--- jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/EngineShutdownException.java	2008-07-29 13:25:51 UTC (rev 1748)
+++ jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/EngineShutdownException.java	2008-07-29 14:55:18 UTC (rev 1749)
@@ -24,24 +24,22 @@
 // $Id$
 
 /**
- * A JBPMException that is thrown when an invalid operation is invoked on 
- * engine shutdown.
+ * A JBPMException that is thrown when an invalid operation is invoked on engine shutdown.
  * 
  * @author thomas.diesler at jboss.com
  * @since 18-Jun-2008
  */
-public class EngineShutdownException extends BPMException {
+ at SuppressWarnings("serial")
+public class EngineShutdownException extends BPMException
+{
 
-  /**
-   * 
-   */
-  private static final long serialVersionUID = 1L;
-
-  public EngineShutdownException() {
+  public EngineShutdownException()
+  {
     super();
   }
 
-  public EngineShutdownException(String message) {
+  public EngineShutdownException(String message)
+  {
     super(message);
   }
 }

Modified: jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/InvalidProcessException.java
===================================================================
--- jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/InvalidProcessException.java	2008-07-29 13:25:51 UTC (rev 1748)
+++ jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/InvalidProcessException.java	2008-07-29 14:55:18 UTC (rev 1749)
@@ -30,13 +30,9 @@
  * @author thomas.diesler at jboss.com
  * @since 18-Jun-2008
  */
+ at SuppressWarnings("serial")
 public class InvalidProcessException extends BPMException
 {
-  /**
-   * 
-   */
-  private static final long serialVersionUID = 1L;
-
   public InvalidProcessException()
   {
     super();

Modified: jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/NameNotUniqueException.java
===================================================================
--- jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/NameNotUniqueException.java	2008-07-29 13:25:51 UTC (rev 1748)
+++ jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/NameNotUniqueException.java	2008-07-29 14:55:18 UTC (rev 1749)
@@ -29,10 +29,9 @@
  * @author thomas.diesler at jboss.com
  * @since 18-Jun-2008
  */
+ at SuppressWarnings("serial")
 public class NameNotUniqueException extends InvalidProcessException
 {
-  private static final long serialVersionUID = 1L;
-
   public NameNotUniqueException()
   {
     super();

Modified: jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/NotImplementedException.java
===================================================================
--- jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/NotImplementedException.java	2008-07-29 13:25:51 UTC (rev 1748)
+++ jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/NotImplementedException.java	2008-07-29 14:55:18 UTC (rev 1749)
@@ -29,18 +29,16 @@
  * @author thomas.diesler at jboss.com
  * @since 18-Jun-2008
  */
-public class NotImplementedException extends RuntimeException {
-
-  /**
-   * 
-   */
-  private static final long serialVersionUID = 1L;
-
-  public NotImplementedException() {
+ at SuppressWarnings("serial")
+public class NotImplementedException extends RuntimeException
+{
+  public NotImplementedException()
+  {
     super();
   }
 
-  public NotImplementedException(String message) {
+  public NotImplementedException(String message)
+  {
     super(message);
   }
 }

Modified: jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/ProcessTimeoutException.java
===================================================================
--- jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/ProcessTimeoutException.java	2008-07-29 13:25:51 UTC (rev 1748)
+++ jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/ProcessTimeoutException.java	2008-07-29 14:55:18 UTC (rev 1749)
@@ -29,10 +29,9 @@
  * @author thomas.diesler at jboss.com
  * @since 24-Jul-2008
  */
+ at SuppressWarnings("serial")
 public class ProcessTimeoutException extends BPMException
 {
-  private static final long serialVersionUID = 1L;
-
   public ProcessTimeoutException()
   {
     super();

Modified: jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/client/MessageManager.java
===================================================================
--- jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/client/MessageManager.java	2008-07-29 13:25:51 UTC (rev 1748)
+++ jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/client/MessageManager.java	2008-07-29 14:55:18 UTC (rev 1749)
@@ -118,13 +118,9 @@
         break;
       }
     }
-    if (msgListener != null)
-    {
-      msgListener.catchMessage(msg);
-    }
-    else
-    {
-      log.warn("No message listener registered: " + targetID);
-    }
+    if (msgListener == null)
+      throw new IllegalStateException("No message listener registered for: " + targetID);
+
+    msgListener.catchMessage(msg);
   }
 }
\ No newline at end of file

Modified: jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/model/TaskBuilder.java
===================================================================
--- jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/model/TaskBuilder.java	2008-07-29 13:25:51 UTC (rev 1748)
+++ jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/model/TaskBuilder.java	2008-07-29 14:55:18 UTC (rev 1749)
@@ -23,7 +23,9 @@
 
 import javax.management.ObjectName;
 
+import org.jboss.bpm.runtime.ExecutionHandler;
 
+
 //$Id$
 
 /**
@@ -37,4 +39,9 @@
   TaskBuilder addMessageRef(String messageName, ObjectName targetID);
 
   TaskBuilder addMessageProperty(String propName, String propValue, boolean isCorrelation);
+  
+  /**
+   * Add an {@link ExecutionHandler} with a given Class
+   */
+  TaskBuilder addExecutionHandler(Class<?> clazz);
 }
\ No newline at end of file

Modified: jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/runtime/FlowScheduler.java
===================================================================
--- jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/runtime/FlowScheduler.java	2008-07-29 13:25:51 UTC (rev 1748)
+++ jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/runtime/FlowScheduler.java	2008-07-29 14:55:18 UTC (rev 1749)
@@ -36,37 +36,7 @@
 {
   /**
    * Schedule the given {@link Flow} and {@link Token}
+   * @param flow TODO
    */
-  void scheduleTuple(Tuple tuple);
-  
-  /**
-   * A tuple of Flow and Token
-   */
-  class Tuple
-  {
-    private Flow flow;
-    private Token token;
-    /**
-     * Construct the Tuple with a given flow and Token
-     */
-    public Tuple(Flow flow, Token token)
-    {
-      this.flow = flow;
-      this.token = token;
-    }
-    /**
-     * Get the Flow
-     */
-    public Flow getFlow()
-    {
-      return flow;
-    }
-    /**
-     * Get the Token
-     */
-    public Token getToken()
-    {
-      return token;
-    }
-  }
+  void scheduleTuple(Flow flow, Token token);
 }

Modified: jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/runtime/MutableFlowScheduler.java
===================================================================
--- jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/runtime/MutableFlowScheduler.java	2008-07-29 13:25:51 UTC (rev 1748)
+++ jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/runtime/MutableFlowScheduler.java	2008-07-29 14:55:18 UTC (rev 1749)
@@ -33,12 +33,12 @@
 public interface MutableFlowScheduler extends FlowScheduler
 {
   /**
-   * Peek the head {@link Tuple}
+   * Peek the head {@link Token}
    */
-  Tuple peekHeadTuple();
+  Token peekHeadTuple();
   
   /**
-   * Remove the head {@link Tuple}
+   * Remove the head {@link Token}
    */
-  Tuple removeHeadTuple();
+  Token removeHeadTuple();
 }

Modified: jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/runtime/Token.java
===================================================================
--- jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/runtime/Token.java	2008-07-29 13:25:51 UTC (rev 1748)
+++ jbossbpm/spec/trunk/modules/api/src/main/java/org/jboss/bpm/runtime/Token.java	2008-07-29 14:55:18 UTC (rev 1749)
@@ -23,6 +23,7 @@
 
 //$Id$
 
+import org.jboss.bpm.model.Flow;
 import org.jboss.bpm.model.Process;
 
 /**
@@ -37,57 +38,37 @@
  * @author Thomas.Diesler at jboss.com
  * @since 20-Apr-2007
  */
-public class Token
+public interface Token
 {
-  private Process proc;
-  private ExecutionContext context;
-
   /**
-   * Construct a Token with a given {@link Process} and {@link Attachments}
+   * Get the unique token identity
    */
-  public Token(Process proc, Attachments att)
-  {
-    this.proc = proc;
-    this.context = new InitialContext(att);
-  }
+  String getTokenID();
 
   /**
    * Get the associated {@link Process}
    */
-  public Process getProcess()
-  {
-    return proc;
-  }
-  
+  Process getProcess();
+
   /**
    * Get the associated {@link ExecutionContext}
    */
-  public ExecutionContext getExecutionContext()
-  {
-    return context;
-  }
+  ExecutionContext getExecutionContext();
+
+  /**
+   * Get the current @{link SequenceFlow} 
+   */
+  Flow getFlow();
   
   /**
    * Create a schallow copy of this Token.
    * <p/>
-   * The content in the {@link ExecutionContext} will be 
-   * copied by reference. 
+   * The content in the {@link ExecutionContext} will be copied by reference. 
    */
-  public Token createCopy()
-  {
-    return new Token(proc, context);
-  }
-  
-  public String toString()
-  {
-    return "[proc=" + proc.getID() + ",ctx=" + context + "]";
-  }
-  
-  static class InitialContext extends BasicAttachments implements ExecutionContext
-  {
-    InitialContext(Attachments att)
-    {
-      super(att);
-    }
-  }
+  Token copyToken();
+
+  /**
+   * Merge this Token with another token.
+   */
+  void mergeToken(Token token);
 }
\ No newline at end of file

Modified: jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/client/internal/ExecutionManagerImpl.java
===================================================================
--- jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/client/internal/ExecutionManagerImpl.java	2008-07-29 13:25:51 UTC (rev 1748)
+++ jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/client/internal/ExecutionManagerImpl.java	2008-07-29 14:55:18 UTC (rev 1749)
@@ -26,8 +26,6 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.jboss.bpm.client.ExecutionManager;
-import org.jboss.bpm.client.ProcessEngine;
-import org.jboss.bpm.client.ProcessEngineLocator;
 import org.jboss.bpm.client.SignalManager;
 import org.jboss.bpm.model.Flow;
 import org.jboss.bpm.model.FlowObject;
@@ -45,7 +43,7 @@
 import org.jboss.bpm.runtime.RuntimeProcess;
 import org.jboss.bpm.runtime.SignalHandler;
 import org.jboss.bpm.runtime.Token;
-import org.jboss.bpm.runtime.FlowScheduler.Tuple;
+import org.jboss.bpm.runtime.internal.TokenImpl;
 
 /**
  * The process manager is the entry point to create, find and otherwise manage processes.
@@ -79,17 +77,15 @@
     MutableFlowScheduler flowScheduler = rtProc.getFlowScheduler();
     try
     {
-      Token initalToken = new Token(proc, att);
+      Token initalToken = new TokenImpl(proc, att);
       StartEvent start = proc.getStartEvent();
-      Tuple tuple = new Tuple(new InitialFlow(start), initalToken);
-      flowScheduler.scheduleTuple(tuple);
+      flowScheduler.scheduleTuple(new InitialFlow(start), initalToken);
 
       while (flowScheduler.peekHeadTuple() != null)
       {
         // Peek the head flow
-        tuple = flowScheduler.peekHeadTuple();
-        Flow flow = tuple.getFlow();
-        Token token = tuple.getToken();
+        Token token = flowScheduler.peekHeadTuple();
+        Flow flow = token.getFlow();
 
         // Get the target and its handlers
         FlowObject target = (FlowObject)flow.getTargetRef();

Modified: jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/client/internal/ProcessManagerImpl.java
===================================================================
--- jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/client/internal/ProcessManagerImpl.java	2008-07-29 13:25:51 UTC (rev 1748)
+++ jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/client/internal/ProcessManagerImpl.java	2008-07-29 14:55:18 UTC (rev 1749)
@@ -26,12 +26,9 @@
 import java.util.Map;
 import java.util.Set;
 
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
 import org.jboss.bpm.client.DialectHandler;
 import org.jboss.bpm.client.DialectRegistry;
 import org.jboss.bpm.client.ExecutionManager;
-import org.jboss.bpm.client.ProcessEngine;
 import org.jboss.bpm.client.ProcessManager;
 import org.jboss.bpm.model.Process;
 import org.jboss.bpm.model.Process.Status;
@@ -46,9 +43,6 @@
  */
 public class ProcessManagerImpl extends ProcessManager
 {
-  // provide logging
-  private static final Log log = LogFactory.getLog(ProcessManagerImpl.class);
-
   public void setDialectHandlers(Map<String, DialectHandler> dialectHandlers)
   {
     this.dialectHandlers = dialectHandlers;

Modified: jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/ActivityImpl.java
===================================================================
--- jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/ActivityImpl.java	2008-07-29 13:25:51 UTC (rev 1748)
+++ jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/ActivityImpl.java	2008-07-29 14:55:18 UTC (rev 1749)
@@ -48,7 +48,6 @@
 import org.jboss.bpm.runtime.FlowScheduler;
 import org.jboss.bpm.runtime.MutablePropertySupport;
 import org.jboss.bpm.runtime.Token;
-import org.jboss.bpm.runtime.FlowScheduler.Tuple;
 import org.mvel.MVEL;
 
 /**
@@ -59,8 +58,8 @@
  * @author thomas.diesler at jboss.com
  * @since 08-Jul-2008
  */
-public abstract class ActivityImpl extends FlowObjectImpl implements Activity, MutablePropertySupport,
-    SingleInFlowSetterSupport, SingleOutFlowSetterSupport
+ at SuppressWarnings("serial")
+public abstract class ActivityImpl extends FlowObjectImpl implements Activity, MutablePropertySupport, SingleInFlowSetterSupport, SingleOutFlowSetterSupport
 {
   // provide logging
   private static final Log log = LogFactory.getLog(ActivityImpl.class);
@@ -223,14 +222,14 @@
           for (Property prop : auxSet.getProperties())
           {
             String name = prop.getName();
-            Expression expr = exContext.getAttachment(name);
-            inputSet.addProperty(new PropertyImpl(name, expr));
+            String value = exContext.getAttachment(name);
+            inputSet.addProperty(new PropertyImpl(name, new ExpressionImpl(value)));
           }
           break;
         }
       }
       if (inputSet == null)
-        throw new IllegalStateException("Cannot find inputSet that matches token: " + token);
+        throw new IllegalStateException("Cannot find matching inputSet for " + exContext + " in Activity: " + getName());
     }
 
     // Create an empty input set
@@ -245,9 +244,8 @@
    */
   protected void executeHandler(Token token, InputSet inputSet, OutputSet outputSet)
   {
-    ExecutionHandler handler = getExecutionHandler();
-    
     // Call the execution handler with the InputSet
+    ExecutionHandler handler = getExecutionHandler();
     if (handler != null)
     {
       handler.execute(token, inputSet, outputSet);
@@ -304,7 +302,8 @@
       {
         Property outProp = outputSet.getProperty(prop.getName());
         if (outProp == null)
-          throw new IllegalStateException("Cannot find required outputSet property: " + prop.getName());
+          throw new IllegalStateException("Cannot find required outputSet property '" + prop.getName()
+              + "' in Activity: " + getName());
 
         exContext.addAttachment(outProp.getName(), outProp.getValue().getExpressionBody());
       }
@@ -319,7 +318,7 @@
     ExecutionContext exContext = token.getExecutionContext();
     for (Property prop : inputSet.getProperties())
     {
-      // TODO: define proper scope for token data 
+      // TODO: define proper scope for token data
       // exContext.removeAttachment(prop.getName());
     }
   }
@@ -333,8 +332,7 @@
       {
         public void execute(FlowScheduler scheduler, Token token)
         {
-          Tuple tuple = new Tuple(outFlow, token);
-          scheduler.scheduleTuple(tuple);
+          scheduler.scheduleTuple(outFlow, token);
         }
       };
     }

Modified: jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/BPMNElementImpl.java
===================================================================
--- jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/BPMNElementImpl.java	2008-07-29 13:25:51 UTC (rev 1748)
+++ jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/BPMNElementImpl.java	2008-07-29 14:55:18 UTC (rev 1749)
@@ -40,10 +40,9 @@
  * @author thomas.diesler at jboss.com
  * @since 08-Jul-2008
  */
+ at SuppressWarnings("serial")
 public class BPMNElementImpl implements BPMNElement
 {
-  private static final long serialVersionUID = 1L;
-
   private ObjectName id;
   private Process process;
 

Modified: jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/EndEventImpl.java
===================================================================
--- jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/EndEventImpl.java	2008-07-29 13:25:51 UTC (rev 1748)
+++ jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/EndEventImpl.java	2008-07-29 14:55:18 UTC (rev 1749)
@@ -44,6 +44,7 @@
  * @author thomas.diesler at jboss.com
  * @since 08-Jul-2008
  */
+ at SuppressWarnings("serial")
 public class EndEventImpl extends EventImpl implements EndEvent, SingleInFlowSetterSupport
 {
   // provide logging

Modified: jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/ExclusiveGatewayImpl.java
===================================================================
--- jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/ExclusiveGatewayImpl.java	2008-07-29 13:25:51 UTC (rev 1748)
+++ jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/ExclusiveGatewayImpl.java	2008-07-29 14:55:18 UTC (rev 1749)
@@ -26,10 +26,13 @@
 import java.util.HashMap;
 import java.util.Map;
 
+import org.jboss.bpm.NotImplementedException;
 import org.jboss.bpm.model.ExclusiveGateway;
 import org.jboss.bpm.model.Expression;
+import org.jboss.bpm.model.Flow;
 import org.jboss.bpm.model.Gate;
 import org.jboss.bpm.model.SequenceFlow;
+import org.jboss.bpm.model.ExclusiveGateway.ExclusiveType;
 import org.jboss.bpm.model.Expression.ExpressionLanguage;
 import org.jboss.bpm.model.SequenceFlow.ConditionType;
 import org.jboss.bpm.runtime.ExecutionContext;
@@ -37,7 +40,6 @@
 import org.jboss.bpm.runtime.FlowScheduler;
 import org.jboss.bpm.runtime.Token;
 import org.jboss.bpm.runtime.Attachments.Key;
-import org.jboss.bpm.runtime.FlowScheduler.Tuple;
 import org.mvel.MVEL;
 
 /**
@@ -60,6 +62,15 @@
   }
 
   @Override
+  public void addInFlow(Flow inFlow)
+  {
+    if (getInFlows().size() > 0)
+      throw new NotImplementedException("ExclusiveGateway with multiple inFlows");
+    
+    super.addInFlow(inFlow);
+  }
+
+  @Override
   public FlowHandler getFlowHandler()
   {
     FlowHandler handler = super.getFlowHandler();
@@ -118,8 +129,8 @@
           if (selectedGate == null)
             throw new IllegalStateException("Cannot select applicable gate for: " + token);
 
-          Tuple tuple = new Tuple(selectedGate.getOutgoingSequenceFlow(), token);
-          scheduler.scheduleTuple(tuple);
+          SequenceFlow outFlow = selectedGate.getOutgoingSequenceFlow();
+          scheduler.scheduleTuple(outFlow, token);
         }
       };
     }

Modified: jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/FlowObjectImpl.java
===================================================================
--- jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/FlowObjectImpl.java	2008-07-29 13:25:51 UTC (rev 1748)
+++ jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/FlowObjectImpl.java	2008-07-29 14:55:18 UTC (rev 1749)
@@ -47,13 +47,12 @@
  * @author thomas.diesler at jboss.com
  * @since 08-Jul-2008
  */
+ at SuppressWarnings("serial")
 public abstract class FlowObjectImpl extends GraphicalElementImpl implements FlowObject, HandlerSetterSupport, Executable
 {
-  private static final long serialVersionUID = 1L;
-  
-  private ExecutionHandler executionHandler;
   private FlowHandler flowHandler;
   private SignalHandler signalHandler;
+  private ExecutionHandler executionHandler;
   
   public ExecutionHandler getExecutionHandler()
   {

Modified: jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/FlowSchedulerImpl.java
===================================================================
--- jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/FlowSchedulerImpl.java	2008-07-29 13:25:51 UTC (rev 1748)
+++ jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/FlowSchedulerImpl.java	2008-07-29 14:55:18 UTC (rev 1749)
@@ -30,6 +30,7 @@
 import org.jboss.bpm.runtime.FlowHandler;
 import org.jboss.bpm.runtime.MutableFlowScheduler;
 import org.jboss.bpm.runtime.Token;
+import org.jboss.bpm.runtime.internal.TokenImpl;
 
 /**
  * The {@link FlowHandler} invokes the FlowScheduler to schedule 
@@ -40,19 +41,21 @@
  */
 public class FlowSchedulerImpl implements MutableFlowScheduler
 {
-  private Queue<Tuple> flowQueue = new ConcurrentLinkedQueue<Tuple>();
+  private Queue<Token> flowQueue = new ConcurrentLinkedQueue<Token>();
 
-  public void scheduleTuple(Tuple tuple)
+  public void scheduleTuple(Flow flow, Token token)
   {
-    flowQueue.add(tuple); 
+    TokenImpl tokenImpl = (TokenImpl)token;
+    tokenImpl.setFlow(flow);
+    flowQueue.add(tokenImpl); 
   }
   
-  public Tuple peekHeadTuple()
+  public Token peekHeadTuple()
   {
    return flowQueue.peek();
   }
   
-  public Tuple removeHeadTuple()
+  public Token removeHeadTuple()
   {
    return flowQueue.remove();
   }

Modified: jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/GatewayImpl.java
===================================================================
--- jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/GatewayImpl.java	2008-07-29 13:25:51 UTC (rev 1748)
+++ jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/GatewayImpl.java	2008-07-29 14:55:18 UTC (rev 1749)
@@ -25,7 +25,9 @@
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -33,15 +35,18 @@
 import org.jboss.bpm.model.FlowObject;
 import org.jboss.bpm.model.Gate;
 import org.jboss.bpm.model.Gateway;
+import org.jboss.bpm.model.GraphicalElement;
 import org.jboss.bpm.model.InputSet;
+import org.jboss.bpm.model.NameSupport;
 import org.jboss.bpm.model.OutputSet;
+import org.jboss.bpm.model.SequenceFlow;
 import org.jboss.bpm.model.Signal;
 import org.jboss.bpm.runtime.ExecutionHandler;
 import org.jboss.bpm.runtime.FlowHandler;
 import org.jboss.bpm.runtime.FlowScheduler;
 import org.jboss.bpm.runtime.SignalHandler;
 import org.jboss.bpm.runtime.Token;
-import org.jboss.bpm.runtime.FlowScheduler.Tuple;
+import org.jboss.bpm.runtime.internal.TokenImpl;
 
 /**
  * Gateways are modelling elements that are used to control how Sequence Flow interact as they converge and diverge within a Process. If the flow does not need to be
@@ -50,6 +55,7 @@
  * @author thomas.diesler at jboss.com
  * @since 08-Jul-2008
  */
+ at SuppressWarnings("serial")
 public abstract class GatewayImpl extends FlowObjectImpl implements Gateway, MultipleInFlowSetterSupport
 {
   // provide logging
@@ -58,6 +64,8 @@
   private String name;
   protected List<Flow> inFlows = new ArrayList<Flow>();
   private List<Gate> gates = new ArrayList<Gate>();
+  private Set<Flow> outstandingFlows;
+  private Set<Token> mergeTokens;
 
   public GatewayImpl(String name)
   {
@@ -89,6 +97,33 @@
     this.inFlows.add(inFlow);
   }
 
+  @Override
+  public void execute(Token token)
+  {
+    // Multiple incomingFlows must be synchronized 
+    if (getInFlows().size() > 1)
+    {
+      if (outstandingFlows == null)
+      {
+        outstandingFlows = new HashSet<Flow>(inFlows);
+        mergeTokens = new HashSet<Token>();
+      }
+      
+      Flow flow = token.getFlow();
+      outstandingFlows.remove(flow);
+      
+      if (outstandingFlows.size() > 0)
+        mergeTokens.add(token);
+    }
+    
+    // Call the execution handler with the InputSet
+    ExecutionHandler handler = getExecutionHandler();
+    if (handler != null)
+    {
+      handler.execute(token, null, null);
+    }
+  }
+  
   public ExecutionHandler getExecutionHandler()
   {
     ExecutionHandler handler = super.getExecutionHandler();
@@ -110,18 +145,54 @@
     FlowHandler handler = super.getFlowHandler();
     if (handler == null && gates.size() == 1)
     {
+      final SequenceFlow outFlow = gates.get(0).getOutgoingSequenceFlow();
       handler = new FlowHandler()
       {
         public void execute(FlowScheduler scheduler, Token token)
         {
-          Tuple tuple = new Tuple(gates.get(0).getOutgoingSequenceFlow(), token);
-          scheduler.scheduleTuple(tuple);
+          if (getInFlows().size() > 1)
+          {
+            if (outstandingFlows.size() == 0)
+            {
+              Token mergedToken = mergeTokens(token);
+              scheduler.scheduleTuple(outFlow, mergedToken);
+              outstandingFlows = null;
+              mergeTokens = null;
+            }
+            else
+            {
+              // Log the list of outstanding flows
+              Set<String> sourceNames = new HashSet<String>();
+              for(Flow flow : outstandingFlows)
+              {
+                GraphicalElement sourceRef = flow.getSourceRef();
+                if (sourceRef instanceof NameSupport)
+                  sourceNames.add(((NameSupport)sourceRef).getName());
+                else
+                  sourceNames.add(sourceRef.getID().getCanonicalName());
+              }
+              log.debug("Waiting for " + outstandingFlows + " in gateway: " + sourceNames);
+            }
+          }
+          else
+          {
+            scheduler.scheduleTuple(outFlow, token);
+          }
         }
       };
     }
     return handler;
   }
 
+  private Token mergeTokens(Token token)
+  {
+    TokenImpl mergedToken = new TokenImpl(token.getProcess(), null);
+    for (Token auxToken : mergeTokens)
+      mergedToken.mergeToken(auxToken);
+    
+    return mergedToken;
+  }
+  
   public SignalHandler getSignalHandler()
   {
     SignalHandler handler = super.getSignalHandler();

Modified: jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/GraphicalElementImpl.java
===================================================================
--- jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/GraphicalElementImpl.java	2008-07-29 13:25:51 UTC (rev 1748)
+++ jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/GraphicalElementImpl.java	2008-07-29 14:55:18 UTC (rev 1749)
@@ -30,7 +30,7 @@
  * @author thomas.diesler at jboss.com
  * @since 08-Jul-2008
  */
+ at SuppressWarnings("serial")
 public abstract class GraphicalElementImpl extends BPMNElementImpl implements GraphicalElement
 {
-  private static final long serialVersionUID = 1L;
 }
\ No newline at end of file

Modified: jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/InclusiveGatewayImpl.java
===================================================================
--- jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/InclusiveGatewayImpl.java	2008-07-29 13:25:51 UTC (rev 1748)
+++ jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/InclusiveGatewayImpl.java	2008-07-29 14:55:18 UTC (rev 1749)
@@ -23,12 +23,9 @@
 
 //$Id$
 
-import java.util.List;
-
 import org.jboss.bpm.NotImplementedException;
 import org.jboss.bpm.model.Gate;
 import org.jboss.bpm.model.InclusiveGateway;
-import org.jboss.bpm.model.Gateway.GatewayType;
 
 
 
@@ -40,6 +37,7 @@
  * @author thomas.diesler at jboss.com
  * @since 08-Jul-2008
  */
+ at SuppressWarnings("serial")
 public class InclusiveGatewayImpl extends GatewayImpl implements InclusiveGateway
 {
   public InclusiveGatewayImpl(String name)

Modified: jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/IntermediateEventImpl.java
===================================================================
--- jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/IntermediateEventImpl.java	2008-07-29 13:25:51 UTC (rev 1748)
+++ jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/IntermediateEventImpl.java	2008-07-29 14:55:18 UTC (rev 1749)
@@ -36,7 +36,6 @@
 import org.jboss.bpm.runtime.FlowScheduler;
 import org.jboss.bpm.runtime.SignalHandler;
 import org.jboss.bpm.runtime.Token;
-import org.jboss.bpm.runtime.FlowScheduler.Tuple;
 
 /**
  * An Intermediate Event is an Event that occurs after a Process has been started. It will affect the Flow of the Process, but will not start or (directly) terminate
@@ -110,8 +109,7 @@
       {
         public void execute(FlowScheduler scheduler, Token token)
         {
-          Tuple tuple = new Tuple(getOutFlow(), token);
-          scheduler.scheduleTuple(tuple);
+          scheduler.scheduleTuple(getOutFlow(), token);
         }
       };
     }

Modified: jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/ParallelGatewayImpl.java
===================================================================
--- jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/ParallelGatewayImpl.java	2008-07-29 13:25:51 UTC (rev 1748)
+++ jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/ParallelGatewayImpl.java	2008-07-29 14:55:18 UTC (rev 1749)
@@ -23,16 +23,12 @@
 
 //$Id$
 
-import java.util.List;
-
-import org.jboss.bpm.NotImplementedException;
-import org.jboss.bpm.model.Flow;
 import org.jboss.bpm.model.Gate;
 import org.jboss.bpm.model.ParallelGateway;
+import org.jboss.bpm.model.SequenceFlow;
 import org.jboss.bpm.runtime.FlowHandler;
 import org.jboss.bpm.runtime.FlowScheduler;
 import org.jboss.bpm.runtime.Token;
-import org.jboss.bpm.runtime.FlowScheduler.Tuple;
 
 
 /**
@@ -41,6 +37,7 @@
  * @author thomas.diesler at jboss.com
  * @since 08-Jul-2008
  */
+ at SuppressWarnings("serial")
 public class ParallelGatewayImpl extends GatewayImpl implements ParallelGateway
 {
   public ParallelGatewayImpl(String name)
@@ -67,8 +64,8 @@
         {
           for(Gate gate : getGates())
           {
-            Tuple tuple = new Tuple(gate.getOutgoingSequenceFlow(), token.createCopy());
-            scheduler.scheduleTuple(tuple);
+            SequenceFlow outFlow = gate.getOutgoingSequenceFlow();
+            scheduler.scheduleTuple(outFlow, token.copyToken());
           }
         }
       };

Modified: jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/ReceiveTaskImpl.java
===================================================================
--- jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/ReceiveTaskImpl.java	2008-07-29 13:25:51 UTC (rev 1748)
+++ jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/ReceiveTaskImpl.java	2008-07-29 14:55:18 UTC (rev 1749)
@@ -146,7 +146,7 @@
     {
       String key = prop.getName();
       Expression value = msg.getProperty(key).getValue();
-      exContext.addAttachment(key, value);
+      exContext.addAttachment(key, value.getExpressionBody());
     }
     
     // Call default execute

Modified: jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/SendTaskImpl.java
===================================================================
--- jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/SendTaskImpl.java	2008-07-29 13:25:51 UTC (rev 1748)
+++ jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/SendTaskImpl.java	2008-07-29 14:55:18 UTC (rev 1749)
@@ -21,18 +21,12 @@
  */
 package org.jboss.bpm.model.internal;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import javax.management.ObjectName;
 
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
 import org.jboss.bpm.InvalidProcessException;
 import org.jboss.bpm.client.MessageManager;
 import org.jboss.bpm.client.ObjectNameFactory;
 import org.jboss.bpm.model.Entity;
-import org.jboss.bpm.model.Expression;
 import org.jboss.bpm.model.InputSet;
 import org.jboss.bpm.model.Message;
 import org.jboss.bpm.model.MessageBuilder;
@@ -41,13 +35,10 @@
 import org.jboss.bpm.model.Participant;
 import org.jboss.bpm.model.Process;
 import org.jboss.bpm.model.Property;
-import org.jboss.bpm.model.PropertyBuilder;
 import org.jboss.bpm.model.SendTask;
-import org.jboss.bpm.model.Expression.ExpressionLanguage;
 import org.jboss.bpm.runtime.ExecutionContext;
 import org.jboss.bpm.runtime.ExecutionHandler;
 import org.jboss.bpm.runtime.Token;
-import org.mvel.MVEL;
 
 //$Id$
 
@@ -57,11 +48,9 @@
  * @author thomas.diesler at jboss.com
  * @since 08-Jul-2008
  */
+ at SuppressWarnings("serial")
 public class SendTaskImpl extends TaskImpl implements SendTask
 {
-  // provide logging
-  private static final Log log = LogFactory.getLog(SendTaskImpl.class);
-
   // A Web service is the default technology
   private Implementation implementation = Implementation.WebService;
   private Message messageRef;
@@ -123,11 +112,11 @@
       for (Property auxProp : messageRef.getProperties())
       {
         String key = auxProp.getName();
-        Expression expr = exContext.getAttachment(key);
-        if (expr == null)
+        String value = exContext.getAttachment(key);
+        if (value == null)
           throw new IllegalStateException("Cannot obtain property: " + key);
 
-        msgBuilder.addProperty(key, expr.getExpressionBody());
+        msgBuilder.addProperty(key, value);
       }
       Message msg = msgBuilder.getMessage();
       

Modified: jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/StartEventImpl.java
===================================================================
--- jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/StartEventImpl.java	2008-07-29 13:25:51 UTC (rev 1748)
+++ jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/StartEventImpl.java	2008-07-29 14:55:18 UTC (rev 1749)
@@ -39,7 +39,6 @@
 import org.jboss.bpm.runtime.FlowScheduler;
 import org.jboss.bpm.runtime.SignalHandler;
 import org.jboss.bpm.runtime.Token;
-import org.jboss.bpm.runtime.FlowScheduler.Tuple;
 
 /**
  * A Start Event indicates where a particular Process will start. In terms of Sequence Flow, the Start Event starts the Flow of the Process, and thus, will not have any
@@ -95,8 +94,7 @@
       {
         public void execute(FlowScheduler scheduler, Token token)
         {
-          Tuple tuple = new Tuple(outFlow, token);
-          scheduler.scheduleTuple(tuple);
+          scheduler.scheduleTuple(outFlow, token);
         }
       };
     }

Modified: jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/SubProcessImpl.java
===================================================================
--- jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/SubProcessImpl.java	2008-07-29 13:25:51 UTC (rev 1748)
+++ jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/SubProcessImpl.java	2008-07-29 14:55:18 UTC (rev 1749)
@@ -34,10 +34,9 @@
  * @author thomas.diesler at jboss.com
  * @since 08-Jul-2008
  */
+ at SuppressWarnings("serial")
 public class SubProcessImpl extends ActivityImpl implements SubProcess, SingleInFlowSetterSupport, SingleOutFlowSetterSupport
 {
-  private static final long serialVersionUID = 1L;
-
   public SubProcessImpl(String name)
   {
     super(name);

Modified: jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/TaskBuilderImpl.java
===================================================================
--- jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/TaskBuilderImpl.java	2008-07-29 13:25:51 UTC (rev 1748)
+++ jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/model/internal/TaskBuilderImpl.java	2008-07-29 14:55:18 UTC (rev 1749)
@@ -76,6 +76,12 @@
     message.addProperty(prop);
     return this;
   }
+
+  public TaskBuilder addExecutionHandler(Class<?> clazz)
+  {
+    super.addExecutionHandler(clazz);
+    return this;
+  }
   
   private Task getTask()
   {

Added: jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/runtime/internal/TokenImpl.java
===================================================================
--- jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/runtime/internal/TokenImpl.java	                        (rev 0)
+++ jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/runtime/internal/TokenImpl.java	2008-07-29 14:55:18 UTC (rev 1749)
@@ -0,0 +1,128 @@
+/*
+ * 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.jboss.bpm.runtime.internal;
+
+//$Id$
+
+import org.jboss.bpm.model.Flow;
+import org.jboss.bpm.model.Process;
+import org.jboss.bpm.runtime.Attachments;
+import org.jboss.bpm.runtime.BasicAttachments;
+import org.jboss.bpm.runtime.ExecutionContext;
+import org.jboss.bpm.runtime.Token;
+import org.jboss.bpm.runtime.Attachments.Key;
+import org.jboss.util.id.UID;
+
+/**
+ * A Token is a descriptive construct used to describe how the flow of a Process will proceed at runtime.
+ * 
+ * By tracking how the Token traverses the Flow Objects, gets diverted through alternative paths, and gets split into parallel paths, the normal Sequence Flow should be
+ * completely definable.
+ * 
+ * A Token will have a unique identity that can be used to separate multiple Tokens that may exist because of concurrent process instances or the splitting of the Token
+ * for parallel processing within a single process instance.
+ * 
+ * @author Thomas.Diesler at jboss.com
+ * @since 20-Apr-2007
+ */
+public class TokenImpl implements Token
+{
+  private String id;
+  private Process proc;
+  private Flow flow;
+  private ExecutionContext context;
+
+  /**
+   * Construct a Token with a given {@link Process} and {@link Attachments}
+   */
+  public TokenImpl(Process proc, Attachments att)
+  {
+    this.proc = proc;
+    this.context = new InitialContext(att);
+    this.id = new UID().toString();
+  }
+
+  public String getTokenID()
+  {
+    return id;
+  }
+
+  public Process getProcess()
+  {
+    return proc;
+  }
+  
+  public ExecutionContext getExecutionContext()
+  {
+    return context;
+  }
+  
+  public Flow getFlow()
+  {
+    return flow;
+  }
+
+  public void setFlow(Flow flow)
+  {
+    this.flow = flow;
+  }
+
+  /**
+   * Create a schallow copy of this Token.
+   * <p/>
+   * The content in the {@link ExecutionContext} will be copied by reference. 
+   */
+  public Token copyToken()
+  {
+    return new TokenImpl(proc, context);
+  }
+  
+  /**
+   * Merge this Token with another token.
+   */
+  public void mergeToken(Token token)
+  {
+    ExecutionContext mergeContext = token.getExecutionContext();
+    for(Key key : mergeContext.getAttachmentKeys())
+    {
+      Object mergeValue = mergeContext.getAttachment(key.getClassPart(), key.getNamePart());
+      Object existValue = context.getAttachment(key.getClassPart(), key.getNamePart());
+      if (existValue != null && existValue.equals(mergeValue) == false)
+        throw new IllegalStateException("Cannot merge the same key with different values: " + key);
+      
+      context.addAttachment(key.getClassPart(), key.getNamePart(), mergeValue);
+    }
+  }
+  
+  public String toString()
+  {
+    return "[proc=" + proc.getID() + ",ctx=" + context + "]";
+  }
+  
+  static class InitialContext extends BasicAttachments implements ExecutionContext
+  {
+    InitialContext(Attachments att)
+    {
+      super(att);
+    }
+  }
+}
\ No newline at end of file


Property changes on: jbossbpm/spec/trunk/modules/ri/src/main/java/org/jboss/bpm/runtime/internal/TokenImpl.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Modified: jbossbpm/spec/trunk/modules/testsuite/src/test/java/org/jboss/bpm/samples/airticket/AirticketTest.java
===================================================================
--- jbossbpm/spec/trunk/modules/testsuite/src/test/java/org/jboss/bpm/samples/airticket/AirticketTest.java	2008-07-29 13:25:51 UTC (rev 1748)
+++ jbossbpm/spec/trunk/modules/testsuite/src/test/java/org/jboss/bpm/samples/airticket/AirticketTest.java	2008-07-29 14:55:18 UTC (rev 1749)
@@ -29,11 +29,9 @@
 
 import org.jboss.bpm.client.MessageListener;
 import org.jboss.bpm.client.MessageManager;
-import org.jboss.bpm.client.ObjectNameFactory;
 import org.jboss.bpm.client.ProcessManager;
 import org.jboss.bpm.client.SignalListener;
 import org.jboss.bpm.client.SignalManager;
-import org.jboss.bpm.model.BPMNElement;
 import org.jboss.bpm.model.GatewayBuilder;
 import org.jboss.bpm.model.Message;
 import org.jboss.bpm.model.MessageBuilder;
@@ -56,6 +54,40 @@
  */
 public class AirticketTest extends DefaultEngineTestCase
 {
+  private final class AirticketMessageListener implements MessageListener
+  {
+    private Process proc;
+    private ObjectName targetID;
+    private Message confirmMessage;
+
+    private AirticketMessageListener(Process proc, ObjectName listenerID)
+    {
+      this.proc = proc;
+      this.targetID = listenerID;
+    }
+
+    public Message getConfirmMessage()
+    {
+      return confirmMessage;
+    }
+
+    public void catchMessage(Message message)
+    {
+      MessageManager mm = MessageManager.locateMessageManager();
+      if (message.getName().equals("InvalidDataMsg"))
+        mm.sendMessage(proc.getID(), "ReceiveReqTask", getValidRequestMessage());
+      else if (message.getName().equals("OfferMsg"))
+        mm.sendMessage(proc.getID(), "ReceiveOrderTask", getAcceptOfferMessage());
+      else if (message.getName().equals("ConfirmMsg"))
+        confirmMessage = message;
+    }
+
+    public ObjectName getMessageListenerID()
+    {
+      return targetID;
+    }
+  }
+
   @Override
   protected void setUp() throws Exception
   {
@@ -66,7 +98,7 @@
     {
       public void catchSignal(Signal signal)
       {
-        System.out.println(signal);
+        //System.out.println(signal);
       }
     };
     SignalManager engine = SignalManager.locateSignalManager();
@@ -88,13 +120,21 @@
 
   public void testValidRequest() throws Exception
   {
-    Process proc = buildDynamicProcess();
+    final Process proc = buildDynamicProcess();
     proc.startProcess();
 
+    ObjectName listenerID = getMessageListenerID();
     MessageManager mm = MessageManager.locateMessageManager();
+    AirticketMessageListener msgListener = new AirticketMessageListener(proc, listenerID);
+    mm.addMessageListener(msgListener);
+    
     mm.sendMessage(proc.getID(), "ReceiveReqTask", getValidRequestMessage());
+    proc.waitForEnd();
 
-    proc.waitForEnd();
+    Message confirmMessage = msgListener.getConfirmMessage();
+    assertNotNull("Expected confirm message", confirmMessage);
+    String price = confirmMessage.getProperty("Price").getValue().getExpressionBody();
+    assertEquals("222", price);
   }
 
   public void testInvalidRequest() throws Exception
@@ -102,25 +142,18 @@
     final Process proc = buildDynamicProcess();
     proc.startProcess();
 
-    final MessageManager mm = MessageManager.locateMessageManager();
-    final ObjectName listenerID = ObjectNameFactory.create(BPMNElement.ID_DOMAIN, "test", getName());
-    MessageListener msgListener = new MessageListener()
-    {
-      public void catchMessage(Message message)
-      {
-        mm.sendMessage(proc.getID(), "ReceiveReqTask", getValidRequestMessage());
-      }
-
-      public ObjectName getMessageListenerID()
-      {
-        return listenerID;
-      }
-    };
+    ObjectName listenerID = getMessageListenerID();
+    MessageManager mm = MessageManager.locateMessageManager();
+    AirticketMessageListener msgListener = new AirticketMessageListener(proc, listenerID);
     mm.addMessageListener(msgListener);
     
-    mm.sendMessage(proc.getID(), "ReceiveReqTask", getInvalidRequestMessage(listenerID));
-
+    mm.sendMessage(proc.getID(), "ReceiveReqTask", getInvalidRequestMessage());
     proc.waitForEnd();
+    
+    Message confirmMessage = msgListener.getConfirmMessage();
+    assertNotNull("Expected confirm message", confirmMessage);
+    String price = confirmMessage.getProperty("Price").getValue().getExpressionBody();
+    assertEquals("222", price);
   }
 
   private Process buildDynamicProcess()
@@ -130,7 +163,7 @@
     ProcessBuilder procBuilder = procFactory.newProcessBuilder();
     procBuilder.addProcess("Airticket").addStartEvent().addSequenceFlow("ReceiveReqTask");
 
-    // Build the ReceiveReq Task
+    // Build the ReceiveReqTask
     TaskBuilder taskBuilder = procBuilder.addTask("ReceiveReqTask", TaskType.Receive);
     taskBuilder.addMessageRef("ReqDataMsg", null).
     addMessageProperty("Name", null, true).
@@ -140,7 +173,7 @@
     addMessageProperty("Seats", null, true).
     addSequenceFlow("ValidateTask");
 
-    // Build the Validate Task
+    // Build the ValidateTask
     taskBuilder = procBuilder.addTask("ValidateTask", TaskType.None);
     taskBuilder.addInputSet().
     addPropertyInput("Name", null).
@@ -153,16 +186,25 @@
     addIORule("Name != null && From != null && To != null && Date != null && Seats > 0", ExpressionLanguage.MVEL).
     addSequenceFlow("ValidateGateway");
 
-    // Build the Validate Gateway
+    // Build the ValidateGateway
     GatewayBuilder gatewayBuilder = procBuilder.addGateway("ValidateGateway", GatewayType.Exclusive);
     gatewayBuilder.addConditionalGate("CheckAvailabilityTask", ExpressionLanguage.MVEL, "isReqDataValid == true").
     addDefaultGate("SendInvalidTask");
 
-    // Build the CheckAvailability Task
+    // Build the CheckAvailabilityTask
     taskBuilder = procBuilder.addTask("CheckAvailabilityTask", TaskType.None);
-    taskBuilder.addSequenceFlow("End");
+    taskBuilder.addExecutionHandler(AvailabilityHandler.class).
+    addInputSet().
+    addPropertyInput("From", null).
+    addPropertyInput("To", null).
+    addPropertyInput("Date", null).
+    addPropertyInput("Seats", null).
+    addOutputSet().
+    addPropertyOutput("isAvailable", null).
+    addPropertyOutput("Price", null).
+    addSequenceFlow("AvailabilityGateway");
 
-    // Build the SendInvalid Task
+    // Build the SendInvalidTask
     taskBuilder = procBuilder.addTask("SendInvalidTask", TaskType.Send);
     taskBuilder.addMessageRef("InvalidDataMsg", getMessageListenerID()).
     addMessageProperty("Name", null, true).
@@ -172,7 +214,84 @@
     addMessageProperty("Seats", null, true).
     addSequenceFlow("ReceiveReqTask");
 
-    // Add the EndEvent get the Process
+    // Build the AvailabilityGateway
+    gatewayBuilder = procBuilder.addGateway("AvailabilityGateway", GatewayType.Exclusive);
+    gatewayBuilder.addConditionalGate("SendOfferTask", ExpressionLanguage.MVEL, "isAvailable == true").
+    addDefaultGate("SendNotAvailableTask");
+    
+    // Build the SendOfferTask
+    taskBuilder = procBuilder.addTask("SendOfferTask", TaskType.Send);
+    taskBuilder.addMessageRef("OfferMsg", getMessageListenerID()).
+    addMessageProperty("Name", null, true).
+    addMessageProperty("From", null, true).
+    addMessageProperty("To", null, true).
+    addMessageProperty("Date", null, true).
+    addMessageProperty("Seats", null, true).
+    addMessageProperty("Price", null, true).
+    addSequenceFlow("ReceiveOrderTask");
+
+    // Build the SendNotAvailableTask
+    taskBuilder = procBuilder.addTask("SendNotAvailableTask", TaskType.Send);
+    taskBuilder.addMessageRef("NotAvailableMsg", getMessageListenerID()).
+    addMessageProperty("Name", null, true).
+    addMessageProperty("From", null, true).
+    addMessageProperty("To", null, true).
+    addMessageProperty("Date", null, true).
+    addMessageProperty("Seats", null, true).
+    addSequenceFlow("ReceiveReqTask");
+
+    // Build the ReceiveReqTask
+    taskBuilder = procBuilder.addTask("ReceiveOrderTask", TaskType.Receive);
+    taskBuilder.addMessageRef("AcceptOfferMsg", null).
+    addMessageProperty("CreditCard", null, true).
+    addMessageProperty("Expire", null, true).
+    addMessageProperty("isOfferAccepted", null, true).
+    addSequenceFlow("AcceptOfferGateway");
+    
+    // Build the AcceptOfferGateway
+    gatewayBuilder = procBuilder.addGateway("AcceptOfferGateway", GatewayType.Exclusive);
+    gatewayBuilder.addConditionalGate("ParallelSplitGateway", ExpressionLanguage.MVEL, "isOfferAccepted == true").
+    addDefaultGate("ReceiveReqTask");
+    
+    // Build the AcceptOfferGateway
+    gatewayBuilder = procBuilder.addGateway("ParallelSplitGateway", GatewayType.Parallel);
+    gatewayBuilder.addGate("CreditCardTask").
+    addGate("BookingTask");
+    
+    // Build the CreditCardTask
+    taskBuilder = procBuilder.addTask("CreditCardTask", TaskType.None);
+    taskBuilder.addInputSet().
+    addPropertyInput("CreditCard", null).
+    addPropertyInput("Expire", null).
+    addPropertyInput("Price", null).
+    addSequenceFlow("SynchronizedJoinGateway");
+    
+    // Build the BookingTask
+    taskBuilder = procBuilder.addTask("BookingTask", TaskType.None);
+    taskBuilder.addInputSet().
+    addPropertyInput("Name", null).
+    addPropertyInput("From", null).
+    addPropertyInput("To", null).
+    addPropertyInput("Date", null).
+    addPropertyInput("Seats", null).
+    addSequenceFlow("SynchronizedJoinGateway");
+    
+    // Build the SynchronizedJoinGateway
+    gatewayBuilder = procBuilder.addGateway("SynchronizedJoinGateway", GatewayType.Parallel);
+    gatewayBuilder.addGate("SendConfirmTask");
+    
+    // Build the SendConfirmTask
+    taskBuilder = procBuilder.addTask("SendConfirmTask", TaskType.Send);
+    taskBuilder.addMessageRef("ConfirmMsg", getMessageListenerID()).
+    addMessageProperty("Name", null, true).
+    addMessageProperty("From", null, true).
+    addMessageProperty("To", null, true).
+    addMessageProperty("Date", null, true).
+    addMessageProperty("Seats", null, true).
+    addMessageProperty("Price", null, true).
+    addSequenceFlow("End");
+    
+    // Add the EndEvent
     Process proc = procBuilder.addEndEvent("End").getProcess();
     ProcessManager pm = ProcessManager.locateProcessManager();
     pm.registerProcess(proc);
@@ -188,16 +307,16 @@
     addProperty("From", "MUC").
     addProperty("To", "NYC").
     addProperty("Date", "25-Jul-2008").
-    addProperty("Seats", "1").
+    addProperty("Seats", "2").
     getMessage();
     return msg;
   }
 
-  private Message getInvalidRequestMessage(ObjectName targetID)
+  private Message getInvalidRequestMessage()
   {
     MessageBuilderFactory msgFactory = MessageBuilderFactory.newInstance();
     MessageBuilder msgBuilder = msgFactory.newMessageBuilder();
-    Message msg = msgBuilder.newMessage("ReqDataMsg", targetID).
+    Message msg = msgBuilder.newMessage("ReqDataMsg", getMessageListenerID()).
     addProperty("Name", "Kermit").
     addProperty("From", "MUC").
     addProperty("To", "NYC").
@@ -206,4 +325,26 @@
     getMessage();
     return msg;
   }
+
+  private Message getAcceptOfferMessage()
+  {
+    MessageBuilderFactory msgFactory = MessageBuilderFactory.newInstance();
+    MessageBuilder msgBuilder = msgFactory.newMessageBuilder();
+    Message msg = msgBuilder.newMessage("AcceptOfferMsg", null).
+    addProperty("CreditCard", "1234-1234-1234-1234").
+    addProperty("Expire", "25-Jul-2012").
+    addProperty("isOfferAccepted", "true").
+    getMessage();
+    return msg;
+  }
+
+  private Message getDenyOfferMessage()
+  {
+    MessageBuilderFactory msgFactory = MessageBuilderFactory.newInstance();
+    MessageBuilder msgBuilder = msgFactory.newMessageBuilder();
+    Message msg = msgBuilder.newMessage("AcceptOfferMsg", null).
+    addProperty("isOfferAccepted", "false").
+    getMessage();
+    return msg;
+  }
 }
\ No newline at end of file

Added: jbossbpm/spec/trunk/modules/testsuite/src/test/java/org/jboss/bpm/samples/airticket/AvailabilityHandler.java
===================================================================
--- jbossbpm/spec/trunk/modules/testsuite/src/test/java/org/jboss/bpm/samples/airticket/AvailabilityHandler.java	                        (rev 0)
+++ jbossbpm/spec/trunk/modules/testsuite/src/test/java/org/jboss/bpm/samples/airticket/AvailabilityHandler.java	2008-07-29 14:55:18 UTC (rev 1749)
@@ -0,0 +1,48 @@
+/*
+ * 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.jboss.bpm.samples.airticket;
+
+// $Id$
+
+import org.jboss.bpm.model.InputSet;
+import org.jboss.bpm.model.OutputSet;
+import org.jboss.bpm.model.PropertyBuilder;
+import org.jboss.bpm.model.PropertyBuilderFactory;
+import org.jboss.bpm.runtime.ExecutionHandler;
+import org.jboss.bpm.runtime.Token;
+
+/**
+ * An ExecutionHandler that adds the required outputSet properties
+ * 
+ * @author Thomas.Diesler at jboss.com
+ * @since 04-Jul-2008
+ */
+public class AvailabilityHandler implements ExecutionHandler
+{
+  public void execute(Token token, InputSet inputSet, OutputSet outputSet)
+  {
+    PropertyBuilder builder = PropertyBuilderFactory.newInstance().newPropertyBuilder();
+    Integer seats = Integer.valueOf(inputSet.getProperty("Seats").getValue().getExpressionBody());
+    outputSet.addProperty(builder.newProperty("isAvailable", new Boolean(seats < 10).toString()));
+    outputSet.addProperty(builder.newProperty("Price", new Integer(seats * 111).toString()));
+  }
+}


Property changes on: jbossbpm/spec/trunk/modules/testsuite/src/test/java/org/jboss/bpm/samples/airticket/AvailabilityHandler.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF




More information about the jbpm-commits mailing list