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