Author: sb
Date: Wed Aug  8 14:14:01 2007
New Revision: 5848

Log:
- Implement issue #10985: Mapping variables between parent and sub workflows.

Added:
    trunk/Workflow/tests/data/IncrementVariable_1.xml   (with props)
    trunk/Workflow/tests/data/WorkflowWithSubWorkflowAndVariablePassing_1.xml   
(with props)
    
trunk/WorkflowEventLogTiein/tests/data/WorkflowWithSubWorkflowAndVariablePassing.log
   (with props)
Modified:
    trunk/Workflow/ChangeLog
    trunk/Workflow/src/nodes/sub_workflow.php
    trunk/Workflow/tests/case.php
    trunk/Workflow/tests/definition_xml_test.php
    trunk/Workflow/tests/execution_test.php
    trunk/WorkflowEventLogTiein/tests/listener_test.php

Modified: trunk/Workflow/ChangeLog
==============================================================================
--- trunk/Workflow/ChangeLog [iso-8859-1] (original)
+++ trunk/Workflow/ChangeLog [iso-8859-1] Wed Aug  8 14:14:01 2007
@@ -5,6 +5,7 @@
     node classes. This makes it possible to have custom node classes handled by
     the XML definition storage.
 - Implemented issue #10918: Error messages when loading invalid XML.
+- Implemented issue #10985: Mapping variables between parent and sub workflows.
 - Fixed issue #11068: Implement ezcWorkflowExecution::hasVariable().
 
 1.0.1 - Monday 30 July 2007

Modified: trunk/Workflow/src/nodes/sub_workflow.php
==============================================================================
--- trunk/Workflow/src/nodes/sub_workflow.php [iso-8859-1] (original)
+++ trunk/Workflow/src/nodes/sub_workflow.php [iso-8859-1] Wed Aug  8 14:14:01 
2007
@@ -17,10 +17,27 @@
  * Incoming nodes: 1
  * Outgoing nodes: 1
  *
+ * The example below creates a sub-workflow node that passes the parent
+ * execution's variable 'x' to the variable 'y' in the child execution when the
+ * sub-workflow is started. When it end, the child execution's 'y' variable is
+ * passed to the parent execution as 'z'.
+ *
  * <code>
+ * $subWorkflow = new ezcWorkflowNodeSubWorkflow(
+ *   array(
+ *     'workflow'  => 'IncrementVariable',
+ *     'variables' => array(
+ *       'in' => array(
+ *         'x' => 'y'
+ *       ),
+ *       'out' => array(
+ *         'y' => 'z'
+ *       )
+ *     )
+ *   )
+ * );
  * </code>
  *
- * @todo Example of build up, example of resume with parameters.
  * @package Workflow
  * @version //autogen//
  */
@@ -38,15 +55,40 @@
      * Constructs a new sub workflow with the configuration $configuration.
      *
      * Configuration format
-     * - <b>String:</b>
-     *  The name of the workflow to execute. The workflow is loaded using the
-     *  loadByName method on the execution engine.
+     * <ul>
+     * <li>
+     *   <b>String:</b>
+     *   The name of the workflow to execute. The workflow is loaded using the
+     *   loadByName method on the execution engine.
+     * </li>
+     *
+     * <li>
+     *   <b>Array:</b>
+     *   <ul>
+     *     <li><i>workflow:</i> The name of the workflow to execute. The 
workflow
+     *     is loaded using the loadByName method on the execution engine.</li>
+     *     <li><i>variables:</i> An array with the information for mapping
+     *     workflow variables between parent and child workflow execution.</li>
+     *   </ul>
+     * <li>
+     * </ul>
      *
      * @param mixed $configuration
-     * @throws ezcWorkflowDefinitionStorageException
      */
     public function __construct( $configuration )
     {
+        if ( is_string( $configuration ) )
+        {
+            $configuration = array( 'workflow' => $configuration );
+        }
+
+        if ( !isset( $configuration['variables'] ) )
+        {
+            $configuration['variables'] = array(
+              'in' => array(), 'out' => array()
+            );
+        }
+
         parent::__construct( $configuration );
     }
 
@@ -65,13 +107,18 @@
             );
         }
 
-        $workflow = $execution->definitionStorage->loadByName( 
$this->configuration );
+        $workflow = $execution->definitionStorage->loadByName( 
$this->configuration['workflow'] );
 
         // Sub Workflow is not interactive.
         if ( !$workflow->isInteractive() && !$workflow->hasSubWorkflows() )
         {
             $subExecution = $execution->getSubExecution( null, false );
             $subExecution->workflow = $workflow;
+
+            $this->passVariables(
+              $execution, $subExecution, 
$this->configuration['variables']['in']
+            );
+
             $subExecution->start();
         }
         // Sub Workflow is interactive.
@@ -82,6 +129,11 @@
             {
                 $subExecution = $execution->getSubExecution();
                 $subExecution->workflow = $workflow;
+
+                $this->passVariables(
+                  $execution, $subExecution, 
$this->configuration['variables']['in']
+                );
+
                 $subExecution->start( $this->id );
 
                 $this->state = $subExecution->getId();
@@ -98,6 +150,10 @@
         // Execution of Sub Workflow has ended.
         if ( $subExecution->hasEnded() )
         {
+            $this->passVariables(
+              $subExecution, $execution, 
$this->configuration['variables']['out']
+            );
+
             $this->activateNode( $execution, $this->outNodes[0] );
 
             $this->state = 0;
@@ -121,7 +177,28 @@
      */
     public static function configurationFromXML( DOMElement $element )
     {
-        return $element->getAttribute( 'subWorkflowName' );
+        $configuration = array(
+          'workflow'  => $element->getAttribute( 'subWorkflowName' ),
+          'variables' => array(
+            'in' => array(), 'out' => array()
+          )
+        );
+
+        $xpath = new DOMXPath( $element->ownerDocument );
+        $in    = $xpath->query( 'in/variable', $element );
+        $out   = $xpath->query( 'out/variable', $element );
+
+        foreach ( $in as $variable )
+        {
+            $configuration['variables']['in'][$variable->getAttribute( 'name' 
)] = $variable->getAttribute( 'as' );
+        }
+
+        foreach ( $out as $variable )
+        {
+            $configuration['variables']['out'][$variable->getAttribute( 'name' 
)] = $variable->getAttribute( 'as' );
+        }
+
+        return $configuration;
     }
 
     /**
@@ -131,7 +208,41 @@
      */
     public function configurationToXML( DOMElement $element )
     {
-        $element->setAttribute( 'subWorkflowName', $this->configuration );
+        $element->setAttribute( 'subWorkflowName', 
$this->configuration['workflow'] );
+
+        if ( !empty( $this->configuration['variables']['in'] ) )
+        {
+            $in = $element->appendChild(
+              $element->ownerDocument->createElement( 'in' )
+            );
+
+            foreach ( $this->configuration['variables']['in'] as $fromName => 
$toName )
+            {
+                $variable = $in->appendChild(
+                  $in->ownerDocument->createElement( 'variable' )
+                );
+
+                $variable->setAttribute( 'name', $fromName );
+                $variable->setAttribute( 'as', $toName );
+            }
+        }
+
+        if ( !empty( $this->configuration['variables']['out'] ) )
+        {
+            $out = $element->appendChild(
+              $element->ownerDocument->createElement( 'out' )
+            );
+
+            foreach ( $this->configuration['variables']['out'] as $fromName => 
$toName )
+            {
+                $variable = $out->appendChild(
+                  $out->ownerDocument->createElement( 'variable' )
+                );
+
+                $variable->setAttribute( 'name', $fromName );
+                $variable->setAttribute( 'as', $toName );
+            }
+        }
     }
 
     /**
@@ -142,7 +253,24 @@
      */
     public function __toString()
     {
-        return 'Sub Workflow: ' . $this->configuration;
+        return 'Sub Workflow: ' . $this->configuration['workflow'];
+    }
+
+    /**
+     * Passes variables from one execution context to another.
+     *
+     * @param  ezcWorkflowExecution $from The execution context the variables 
are passed from.
+     * @param  ezcWorkflowExecution $to The execution context the variables 
are passed to.
+     * @param  array                $variables The names of the variables.
+     * @throws ezcWorkflowExecutionException if a variable that is to be 
passed does not exist.
+     * @ignore
+     */
+    protected function passVariables( ezcWorkflowExecution $from, 
ezcWorkflowExecution $to, array $variables )
+    {
+        foreach ( $variables as $fromName => $toName )
+        {
+            $to->setVariable( $toName, $from->getVariable( $fromName ) );
+        }
     }
 }
 ?>

Modified: trunk/Workflow/tests/case.php
==============================================================================
--- trunk/Workflow/tests/case.php [iso-8859-1] (original)
+++ trunk/Workflow/tests/case.php [iso-8859-1] Wed Aug  8 14:14:01 2007
@@ -531,6 +531,33 @@
         $this->endNode->addInNode( $subWorkflow );
     }
 
+    protected function setUpWorkflowWithSubWorkflowAndVariablePassing()
+    {
+        $this->workflow = new ezcWorkflow( 
'WorkflowWithSubWorkflowAndVariablePassing' );
+        $this->setUpReferences();
+
+        $set = new ezcWorkflowNodeVariableSet( array( 'x' => 1 ) );
+
+        $subWorkflow = new ezcWorkflowNodeSubWorkflow(
+          array(
+            'workflow'  => 'IncrementVariable',
+            'variables' => array(
+              'in' => array(
+                'x' => 'y'
+              ),
+              'out' => array(
+                'y' => 'z'
+              )
+            )
+          )
+        );
+
+        $subWorkflow->addInNode( $set );
+
+        $this->startNode->addOutNode( $set );
+        $this->endNode->addInNode( $subWorkflow );
+    }
+
     protected function setUpNestedLoops()
     {
         $this->workflow = new ezcWorkflow( 'NestedLoops' );

Added: trunk/Workflow/tests/data/IncrementVariable_1.xml
==============================================================================
--- trunk/Workflow/tests/data/IncrementVariable_1.xml (added)
+++ trunk/Workflow/tests/data/IncrementVariable_1.xml [iso-8859-1] Wed Aug  8 
14:14:01 2007
@@ -1,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<workflow name="IncrementVariable" version="1">
+  <node id="1" type="Start">
+    <outNode id="2"/>
+  </node>
+  <node id="2" type="VariableIncrement" variable="y">
+    <outNode id="3"/>
+  </node>
+  <node id="3" type="End"/>
+</workflow>

Propchange: trunk/Workflow/tests/data/IncrementVariable_1.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: trunk/Workflow/tests/data/WorkflowWithSubWorkflowAndVariablePassing_1.xml
==============================================================================
--- trunk/Workflow/tests/data/WorkflowWithSubWorkflowAndVariablePassing_1.xml 
(added)
+++ trunk/Workflow/tests/data/WorkflowWithSubWorkflowAndVariablePassing_1.xml 
[iso-8859-1] Wed Aug  8 14:14:01 2007
@@ -1,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<workflow name="WorkflowWithSubWorkflowAndVariablePassing" version="1">
+  <node id="1" type="Start">
+    <outNode id="2"/>
+  </node>
+  <node id="2" type="VariableSet">
+    <variable name="x">
+      <integer>1</integer>
+    </variable>
+    <outNode id="3"/>
+  </node>
+  <node id="3" type="SubWorkflow" subWorkflowName="IncrementVariable">
+    <in>
+      <variable name="x" as="y"/>
+    </in>
+    <out>
+      <variable name="y" as="z"/>
+    </out>
+    <outNode id="4"/>
+  </node>
+  <node id="4" type="End"/>
+</workflow>

Propchange: 
trunk/Workflow/tests/data/WorkflowWithSubWorkflowAndVariablePassing_1.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: trunk/Workflow/tests/definition_xml_test.php
==============================================================================
--- trunk/Workflow/tests/definition_xml_test.php [iso-8859-1] (original)
+++ trunk/Workflow/tests/definition_xml_test.php [iso-8859-1] Wed Aug  8 
14:14:01 2007
@@ -196,6 +196,17 @@
         );
     }
 
+    public function testSaveWorkflowWithSubWorkflowAndVariablePassing()
+    {
+        $this->setUpWorkflowWithSubWorkflowAndVariablePassing();
+        $this->definition->save( $this->workflow );
+
+        $this->assertEquals(
+          $this->readExpected( 'WorkflowWithSubWorkflowAndVariablePassing' ),
+          $this->readActual( 'WorkflowWithSubWorkflowAndVariablePassing' )
+        );
+    }
+
     public function testSaveServiceObjectWithArguments()
     {
         $this->setUpEmptyWorkflow( 'ServiceObjectWithArguments' );
@@ -403,6 +414,17 @@
         $this->assertEquals(
           $this->readExpected( 'WorkflowWithSubWorkflow' ),
           $this->readActual( 'WorkflowWithSubWorkflow' )
+        );
+    }
+
+    public function testLoadWorkflowWithSubWorkflowAndVariablePassing()
+    {
+        $this->workflow = $this->definition->loadByName( 
'WorkflowWithSubWorkflowAndVariablePassing' );
+        $this->definition->save( $this->workflow );
+
+        $this->assertEquals(
+          $this->readExpected( 'WorkflowWithSubWorkflowAndVariablePassing' ),
+          $this->readActual( 'WorkflowWithSubWorkflowAndVariablePassing' )
         );
     }
 

Modified: trunk/Workflow/tests/execution_test.php
==============================================================================
--- trunk/Workflow/tests/execution_test.php [iso-8859-1] (original)
+++ trunk/Workflow/tests/execution_test.php [iso-8859-1] Wed Aug  8 14:14:01 
2007
@@ -593,6 +593,21 @@
         $this->assertEquals( 2, $this->execution->getVariable( 'j' ) );
     }
 
+    public function testExecuteWorkflowWithSubWorkflowAndVariablePassing()
+    {
+        $this->setUpWorkflowWithSubWorkflowAndVariablePassing();
+        $this->execution->definitionStorage = $this->definition;
+        $this->execution->workflow = $this->workflow;
+        $this->execution->start();
+
+        $this->assertTrue( $this->execution->hasEnded() );
+        $this->assertFalse( $this->execution->isResumed() );
+        $this->assertFalse( $this->execution->isSuspended() );
+
+        $this->assertEquals( 1, $this->execution->getVariable( 'x' ) );
+        $this->assertEquals( 2, $this->execution->getVariable( 'z' ) );
+    }
+
     public function testGetVariable()
     {
         $this->setUpStartEnd();

Added: 
trunk/WorkflowEventLogTiein/tests/data/WorkflowWithSubWorkflowAndVariablePassing.log
==============================================================================
--- 
trunk/WorkflowEventLogTiein/tests/data/WorkflowWithSubWorkflowAndVariablePassing.log
 (added)
+++ 
trunk/WorkflowEventLogTiein/tests/data/WorkflowWithSubWorkflowAndVariablePassing.log
 [iso-8859-1] Wed Aug  8 14:14:01 2007
@@ -1,0 +1,26 @@
+MMM DD HH:MM:SS [Info] [default] [default] Started execution #1 of workflow 
"WorkflowWithSubWorkflowAndVariablePassing" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Activated node 
#4(ezcWorkflowNodeStart) for instance #1 of workflow 
"WorkflowWithSubWorkflowAndVariablePassing" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Started thread #0 (1 sibling(s)) 
for execution #1 of workflow "WorkflowWithSubWorkflowAndVariablePassing" 
(version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Activated node 
#5(ezcWorkflowNodeVariableSet) for instance #1 of workflow 
"WorkflowWithSubWorkflowAndVariablePassing" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Executed node 
#4(ezcWorkflowNodeStart) for instance #1 of workflow 
"WorkflowWithSubWorkflowAndVariablePassing" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Set variable "x" to "1" for 
execution #1 of workflow "WorkflowWithSubWorkflowAndVariablePassing" (version 
1).
+MMM DD HH:MM:SS [Debug] [default] [default] Activated node 
#6(ezcWorkflowNodeSubWorkflow) for instance #1 of workflow 
"WorkflowWithSubWorkflowAndVariablePassing" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Executed node 
#5(ezcWorkflowNodeVariableSet) for instance #1 of workflow 
"WorkflowWithSubWorkflowAndVariablePassing" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Set variable "y" to "1" for 
execution #0 of workflow "IncrementVariable" (version 1).
+MMM DD HH:MM:SS [Info] [default] [default] Started execution #0 of workflow 
"IncrementVariable" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Activated node 
#1(ezcWorkflowNodeStart) for instance #0 of workflow "IncrementVariable" 
(version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Started thread #0 (1 sibling(s)) 
for execution #0 of workflow "IncrementVariable" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Activated node 
#2(ezcWorkflowNodeVariableIncrement) for instance #0 of workflow 
"IncrementVariable" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Executed node 
#1(ezcWorkflowNodeStart) for instance #0 of workflow "IncrementVariable" 
(version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Set variable "y" to "2" for 
execution #0 of workflow "IncrementVariable" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Activated node 
#3(ezcWorkflowNodeEnd) for instance #0 of workflow "IncrementVariable" (version 
1).
+MMM DD HH:MM:SS [Debug] [default] [default] Executed node 
#2(ezcWorkflowNodeVariableIncrement) for instance #0 of workflow 
"IncrementVariable" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Executed node 
#3(ezcWorkflowNodeEnd) for instance #0 of workflow "IncrementVariable" (version 
1).
+MMM DD HH:MM:SS [Debug] [default] [default] Ended thread #0 for execution #0 
of workflow "IncrementVariable" (version 1).
+MMM DD HH:MM:SS [Info] [default] [default] Ended execution #0 of workflow 
"IncrementVariable" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Set variable "z" to "2" for 
execution #1 of workflow "WorkflowWithSubWorkflowAndVariablePassing" (version 
1).
+MMM DD HH:MM:SS [Debug] [default] [default] Activated node 
#7(ezcWorkflowNodeEnd) for instance #1 of workflow 
"WorkflowWithSubWorkflowAndVariablePassing" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Executed node 
#6(ezcWorkflowNodeSubWorkflow) for instance #1 of workflow 
"WorkflowWithSubWorkflowAndVariablePassing" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Executed node 
#7(ezcWorkflowNodeEnd) for instance #1 of workflow 
"WorkflowWithSubWorkflowAndVariablePassing" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Ended thread #0 for execution #1 
of workflow "WorkflowWithSubWorkflowAndVariablePassing" (version 1).
+MMM DD HH:MM:SS [Info] [default] [default] Ended execution #1 of workflow 
"WorkflowWithSubWorkflowAndVariablePassing" (version 1).

Propchange: 
trunk/WorkflowEventLogTiein/tests/data/WorkflowWithSubWorkflowAndVariablePassing.log
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: trunk/WorkflowEventLogTiein/tests/listener_test.php
==============================================================================
--- trunk/WorkflowEventLogTiein/tests/listener_test.php [iso-8859-1] (original)
+++ trunk/WorkflowEventLogTiein/tests/listener_test.php [iso-8859-1] Wed Aug  8 
14:14:01 2007
@@ -297,6 +297,26 @@
         );
     }
 
+    public function testLoadWorkflowWithSubWorkflowAndVariablePassing()
+    {
+        $definition = new ezcWorkflowDefinitionStorageXml(
+          dirname( dirname( dirname( __FILE__ ) ) ) . '/Workflow/tests/data/'
+        );
+
+        $workflow = $definition->loadByName( 'IncrementVariable' );
+        $this->definition->save( $workflow );
+
+        $this->setUpWorkflowWithSubWorkflowAndVariablePassing();
+        $this->definition->save( $this->workflow );
+        $this->execution->workflow = $this->workflow;
+        $this->execution->start();
+
+        $this->assertEquals(
+          $this->readExpected( 'WorkflowWithSubWorkflowAndVariablePassing' ),
+          $this->readActual()
+        );
+    }
+
     public function testLogNestedLoops()
     {
         $this->setUpNestedLoops();


-- 
svn-components mailing list
[email protected]
http://lists.ez.no/mailman/listinfo/svn-components

Reply via email to