Author: sb
Date: Mon Jan 21 17:04:16 2008
New Revision: 7215
Log:
- Implement the Cancel Case workflow pattern.
Added:
trunk/Workflow/src/interfaces/rollbackable_service_object.php
- copied, changed from r7197,
trunk/Workflow/src/interfaces/service_object.php
trunk/Workflow/src/nodes/cancel.php
- copied, changed from r7197, trunk/Workflow/src/nodes/end.php
trunk/Workflow/tests/data/ParallelSplitActionActionCancelCaseSynchronization.dot
(with props)
trunk/Workflow/tests/data/ParallelSplitActionActionCancelCaseSynchronization_1.xml
(with props)
trunk/Workflow/tests/data/ParallelSplitCancelCaseActionActionSynchronization.dot
(with props)
trunk/Workflow/tests/data/ParallelSplitCancelCaseActionActionSynchronization_1.xml
(with props)
trunk/WorkflowEventLogTiein/tests/data/ParallelSplitActionActionCancelCaseSynchronization.log
(with props)
trunk/WorkflowEventLogTiein/tests/data/ParallelSplitCancelCaseActionActionSynchronization.log
(with props)
trunk/WorkflowEventLogTiein/tests/data/ParallelSplitSynchronizationCancelCase.log
(with props)
Modified:
trunk/Workflow/ChangeLog
trunk/Workflow/src/interfaces/execution.php
trunk/Workflow/src/nodes/action.php
trunk/Workflow/src/workflow_autoload.php
trunk/Workflow/tests/case.php
trunk/Workflow/tests/definition_xml_test.php
trunk/Workflow/tests/execution_test.php
trunk/Workflow/tests/visitor_visualization_test.php
trunk/WorkflowDatabaseTiein/ChangeLog
trunk/WorkflowDatabaseTiein/src/execution.php
trunk/WorkflowEventLogTiein/tests/listener_test.php
Modified: trunk/Workflow/ChangeLog
==============================================================================
--- trunk/Workflow/ChangeLog [iso-8859-1] (original)
+++ trunk/Workflow/ChangeLog [iso-8859-1] Mon Jan 21 17:04:16 2008
@@ -1,3 +1,5 @@
+- Implemented issue #10941: Support for the Cancel Case workflow pattern.
+
- Implemented issue #12404: Separate file i/o from XML processing in
ezcWorkflowDefinitionStorageXml.
Modified: trunk/Workflow/src/interfaces/execution.php
==============================================================================
--- trunk/Workflow/src/interfaces/execution.php [iso-8859-1] (original)
+++ trunk/Workflow/src/interfaces/execution.php [iso-8859-1] Mon Jan 21
17:04:16 2008
@@ -69,6 +69,14 @@
protected $numActivatedEndNodes = 0;
/**
+ * Rollbackable service objects that have been executed
+ * in the current execution loop.
+ *
+ * @var array
+ */
+ protected $rollbackableServiceObjects = array();
+
+ /**
* Nodes of the workflow that started a new thread of execution.
*
* @var array
@@ -81,6 +89,11 @@
* @var integer
*/
protected $nextThreadId = 0;
+
+ /**
+ * @var bool
+ */
+ protected $cancelled;
/**
* @var bool
@@ -221,6 +234,7 @@
);
}
+ $this->cancelled = false;
$this->ended = false;
$this->resumed = false;
$this->suspended = false;
@@ -266,6 +280,7 @@
*/
public function suspend()
{
+ $this->cancelled = false;
$this->ended = false;
$this->resumed = false;
$this->suspended = true;
@@ -318,6 +333,7 @@
);
}
+ $this->cancelled = false;
$this->ended = false;
$this->resumed = true;
$this->suspended = false;
@@ -370,6 +386,41 @@
}
/**
+ * Cancels workflow execution with the node $endNode.
+ *
+ * @param ezcWorkflowNodeEnd $endNode
+ * @ignore
+ */
+ public function cancel( ezcWorkflowNodeEnd $endNode )
+ {
+ $this->activatedNodes = array();
+ $this->cancelled = true;
+ $this->numActivatedNodes = 0;
+
+ foreach ( $this->rollbackableServiceObjects as $object )
+ {
+ $result = $object['object']->rollback( $this );
+
+ $this->notifyListeners(
+ sprintf(
+ '%s back service object "%s" of node #%d for instance #%d ' .
+ 'of workflow "%s" (version %d).',
+
+ $result ? 'Rolled' : 'Could not roll',
+ get_class( $object['object'] ),
+ $object['node']->getId(),
+ $this->id,
+ $this->workflow->name,
+ $this->workflow->version
+ ),
+ ezcWorkflowExecutionListener::DEBUG
+ );
+ }
+
+ $this->end( $endNode );
+ }
+
+ /**
* Ends workflow execution with the node $endNode.
*
* End nodes must call this method to end the execution.
@@ -400,12 +451,16 @@
ezcWorkflowExecutionListener::DEBUG
);
- $this->endThread( $endNode->getThreadId() );
+ if ( !$this->cancelled )
+ {
+ $this->endThread( $endNode->getThreadId() );
+ }
$this->notifyListeners(
sprintf(
- 'Ended execution #%d of workflow "%s" (version %d).',
-
+ '%s execution #%d of workflow "%s" (version %d).',
+
+ $this->cancelled ? 'Cancelled' : 'Ended',
$this->id,
$this->workflow->name,
$this->workflow->version
@@ -421,8 +476,7 @@
*/
protected function execute()
{
- // Try to execute nodes until while there are executable nodes on the
- // stack of activated nodes.
+ // Try to execute nodes while there are executable nodes on the stack.
do
{
// Flag that indicates whether a node has been executed during the
@@ -438,7 +492,8 @@
{
// The current node is an end node but there are still
// activated nodes on the stack.
- if ( $node instanceof ezcWorkflowNodeEnd &&
+ if ( $node instanceof ezcWorkflowNodeEnd &&
+ !$node instanceof ezcWorkflowNodeCancel &&
$this->numActivatedNodes !=
$this->numActivatedEndNodes )
{
continue;
@@ -543,6 +598,20 @@
/**
* Adds a variable that an (input) node is waiting for.
*
+ * @param ezcWorkflowNodeAction $node
+ * @param ezcWorkflowRollbackableServiceObject $object
+ * @ignore
+ */
+ public function addRollbackableServiceObject( ezcWorkflowNodeAction $node,
ezcWorkflowRollbackableServiceObject $object )
+ {
+ $this->rollbackableServiceObjects[] = array(
+ 'node' => $node, 'object' => $object
+ );
+ }
+
+ /**
+ * Adds a variable that an (input) node is waiting for.
+ *
* @param ezcWorkflowNode $node
* @param string $variableName
* @param ezcWorkflowCondition $condition
@@ -888,6 +957,16 @@
}
/**
+ * Returns true when the workflow execution has been cancelled.
+ *
+ * @return bool
+ */
+ public function isCancelled()
+ {
+ return $this->cancelled;
+ }
+
+ /**
* Returns true when the workflow execution has ended.
*
* @return bool
Copied: trunk/Workflow/src/interfaces/rollbackable_service_object.php (from
r7197, trunk/Workflow/src/interfaces/service_object.php)
==============================================================================
--- trunk/Workflow/src/interfaces/service_object.php [iso-8859-1] (original)
+++ trunk/Workflow/src/interfaces/rollbackable_service_object.php [iso-8859-1]
Mon Jan 21 17:04:16 2008
@@ -1,6 +1,6 @@
<?php
/**
- * File containing the ezcWorkflowServiceObject interface.
+ * File containing the ezcWorkflowRollbackableServiceObject interface.
*
* @package Workflow
* @version //autogen//
@@ -9,34 +9,23 @@
*/
/**
- * Interface for service objects that can be attached to
- * ezcWorkflowNodeAction nodes.
+ * Interface for service objects for which the action can be rolled back
+ * in case the workflow execution is cancelled.
*
* @package Workflow
* @version //autogen//
*/
-interface ezcWorkflowServiceObject
+interface ezcWorkflowRollbackableServiceObject extends ezcWorkflowServiceObject
{
/**
- * Executes the business logic of this service object.
+ * Rolls back the business logic of this service object.
*
- * Implementations can return true if the execution of the
- * service object was successful to resume the workflow and activate
- * the next node.
- *
- * Returning false will cause the workflow to be suspended and the service
- * object to be executed again on a later invokation.
+ * Implementors should return true when the rollback was successful
+ * and false when it was not.
*
* @param ezcWorkflowExecution $execution
* @return boolean
*/
- public function execute( ezcWorkflowExecution $execution );
-
- /**
- * Returns a textual representation of this service object.
- *
- * @return string
- */
- public function __toString();
+ public function rollback( ezcWorkflowExecution $execution );
}
?>
Modified: trunk/Workflow/src/nodes/action.php
==============================================================================
--- trunk/Workflow/src/nodes/action.php [iso-8859-1] (original)
+++ trunk/Workflow/src/nodes/action.php [iso-8859-1] Mon Jan 21 17:04:16 2008
@@ -107,7 +107,13 @@
*/
public function execute( ezcWorkflowExecution $execution )
{
- $object = $this->createObject();
+ $object = $this->createObject();
+
+ if ( $object instanceof ezcWorkflowRollbackableServiceObject )
+ {
+ $execution->addRollbackableServiceObject( $this, $object );
+ }
+
$finished = $object->execute( $execution );
// Execution of the Service Object has finished.
Copied: trunk/Workflow/src/nodes/cancel.php (from r7197,
trunk/Workflow/src/nodes/end.php)
==============================================================================
--- trunk/Workflow/src/nodes/end.php [iso-8859-1] (original)
+++ trunk/Workflow/src/nodes/cancel.php [iso-8859-1] Mon Jan 21 17:04:16 2008
@@ -1,6 +1,6 @@
<?php
/**
- * File containing the ezcWorkflowNodeEnd class.
+ * File containing the ezcWorkflowNodeCancel class.
*
* @package Workflow
* @version //autogen//
@@ -9,57 +9,45 @@
*/
/**
- * An object of the ezcWorkflowNodeEnd class represents an end node of a
workflow.
+ * This node implements the Cancel Case workflow pattern.
*
- * A workflow must have at least one end node. The execution of the workflow
ends
- * when an end node is reached.
- * Creating an object of the ezcWorkflow class automatically creates a default
end node for the new
- * workflow. It can be accessed through the getEndNode() method.
+ * A complete process instance is removed. This includes currently executing
+ * tasks, those which may execute at some future time and all sub-processes.
+ * The process instance is recorded as having completed unsuccessfully.
*
* Incoming nodes: 1
- * Outgoing nodes: 0
- *
- * Example:
- * <code>
- * $workflow = new ezcWorkflow( 'Test' );
- * // build up your workflow here... result in $node
- * $node = ....
- * $workflow->startNode->addOutNode( ....some other node here .. );
- * $node->addOutNode( $workflow->endNode );
- * </code>
+ * Outgoing nodes: 0..1
*
* @package Workflow
* @version //autogen//
*/
-class ezcWorkflowNodeEnd extends ezcWorkflowNode
+class ezcWorkflowNodeCancel extends ezcWorkflowNodeEnd
{
/**
* Constraint: The minimum number of outgoing nodes this node has to have
- * to be valid.
+ * to be valid. Set to false to disable this constraint.
*
* @var integer
*/
- protected $minOutNodes = 0;
+ protected $minOutNodes = false;
/**
* Constraint: The maximum number of outgoing nodes this node has to have
- * to be valid.
+ * to be valid. Set to false to disable this constraint.
*
* @var integer
*/
- protected $maxOutNodes = 0;
+ protected $maxOutNodes = false;
/**
- * Ends the execution of this workflow.
+ * Cancels the execution of this workflow.
*
* @param ezcWorkflowExecution $execution
* @ignore
*/
public function execute( ezcWorkflowExecution $execution )
{
- $execution->end( $this );
-
- return parent::execute( $execution );
+ $execution->cancel( $this );
}
}
?>
Modified: trunk/Workflow/src/workflow_autoload.php
==============================================================================
--- trunk/Workflow/src/workflow_autoload.php [iso-8859-1] (original)
+++ trunk/Workflow/src/workflow_autoload.php [iso-8859-1] Mon Jan 21 17:04:16
2008
@@ -57,6 +57,7 @@
'ezcWorkflowNodeAction' => 'Workflow/nodes/action.php',
'ezcWorkflowNodeDiscriminator' =>
'Workflow/nodes/control_flow/discriminator.php',
'ezcWorkflowNodeEnd' => 'Workflow/nodes/end.php',
+ 'ezcWorkflowNodeCancel' => 'Workflow/nodes/cancel.php',
'ezcWorkflowNodeExclusiveChoice' =>
'Workflow/nodes/control_flow/exclusive_choice.php',
'ezcWorkflowNodeInput' =>
'Workflow/nodes/variables/input.php',
'ezcWorkflowNodeLoop' =>
'Workflow/nodes/control_flow/loop.php',
@@ -75,6 +76,7 @@
'ezcWorkflowNodeVariableSub' =>
'Workflow/nodes/variables/sub.php',
'ezcWorkflowNodeVariableUnset' =>
'Workflow/nodes/variables/unset.php',
'ezcWorkflowServiceObject' =>
'Workflow/interfaces/service_object.php',
+ 'ezcWorkflowRollbackableServiceObject' =>
'Workflow/interfaces/rollbackable_service_object.php',
'ezcWorkflowUtil' => 'Workflow/util.php',
'ezcWorkflowVariableHandler' =>
'Workflow/interfaces/variable_handler.php',
'ezcWorkflowVisitorNodeCollector' =>
'Workflow/visitors/node_collector.php',
Modified: trunk/Workflow/tests/case.php
==============================================================================
--- trunk/Workflow/tests/case.php [iso-8859-1] (original)
+++ trunk/Workflow/tests/case.php [iso-8859-1] Mon Jan 21 17:04:16 2008
@@ -33,7 +33,7 @@
if ( !class_exists( 'ServiceObject', false ) )
{
- $this->getMock( 'ezcWorkflowServiceObject', array(), array(),
'ServiceObject' );
+ $this->getMock( 'ezcWorkflowRollbackableServiceObject', array(),
array(), 'ServiceObject' );
}
}
@@ -690,6 +690,51 @@
->addConditionalOutNode( $outerBreak, $this->endNode );
}
+ protected function setUpCancelCase( $order )
+ {
+ if ( $order == 'first' )
+ {
+ $workflowName =
'ParallelSplitCancelCaseActionActionSynchronization';
+ }
+ else
+ {
+ $workflowName =
'ParallelSplitActionActionCancelCaseSynchronization';
+ }
+
+ $this->workflow = new ezcWorkflow( $workflowName );
+ $this->setUpReferences();
+
+ $this->branchNode = new ezcWorkflowNodeParallelSplit;
+ $cancelNode = new ezcWorkflowNodeCancel;
+ $actionNodeA = new ezcWorkflowNodeAction( 'ServiceObject' );
+ $actionNodeB = new ezcWorkflowNodeAction( 'ServiceObject' );
+ $synchronization = new ezcWorkflowNodeSynchronization;
+
+ if ( $order == 'first' )
+ {
+ $this->branchNode->addOutNode( $cancelNode );
+ $this->branchNode->addOutNode( $actionNodeA );
+ $this->branchNode->addOutNode( $actionNodeB );
+
+ $synchronization->addInNode( $cancelNode );
+ $synchronization->addInNode( $actionNodeA );
+ $synchronization->addInNode( $actionNodeB );
+ }
+ else
+ {
+ $this->branchNode->addOutNode( $actionNodeA );
+ $this->branchNode->addOutNode( $actionNodeB );
+ $this->branchNode->addOutNode( $cancelNode );
+
+ $synchronization->addInNode( $actionNodeA );
+ $synchronization->addInNode( $actionNodeB );
+ $synchronization->addInNode( $cancelNode );
+ }
+
+ $this->startNode->addOutNode( $this->branchNode );
+ $this->endNode->addInNode( $synchronization );
+ }
+
protected function setUpReferences()
{
$this->startNode = $this->workflow->startNode;
Added:
trunk/Workflow/tests/data/ParallelSplitActionActionCancelCaseSynchronization.dot
==============================================================================
---
trunk/Workflow/tests/data/ParallelSplitActionActionCancelCaseSynchronization.dot
(added)
+++
trunk/Workflow/tests/data/ParallelSplitActionActionCancelCaseSynchronization.dot
[iso-8859-1] Mon Jan 21 17:04:16 2008
@@ -1,0 +1,18 @@
+digraph ParallelSplitActionActionCancelCaseSynchronization {
+node1 [label="Start"]
+node2 [label="Parallel Split"]
+node3 [label=""]
+node4 [label="Synchronization"]
+node5 [label="End"]
+node6 [label=""]
+node7 [label="Cancel"]
+
+node1 -> node2
+node2 -> node3
+node2 -> node6
+node2 -> node7
+node3 -> node4
+node4 -> node5
+node6 -> node4
+node7 -> node4
+}
Propchange:
trunk/Workflow/tests/data/ParallelSplitActionActionCancelCaseSynchronization.dot
------------------------------------------------------------------------------
svn:eol-style = native
Added:
trunk/Workflow/tests/data/ParallelSplitActionActionCancelCaseSynchronization_1.xml
==============================================================================
---
trunk/Workflow/tests/data/ParallelSplitActionActionCancelCaseSynchronization_1.xml
(added)
+++
trunk/Workflow/tests/data/ParallelSplitActionActionCancelCaseSynchronization_1.xml
[iso-8859-1] Mon Jan 21 17:04:16 2008
@@ -1,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<workflow name="ParallelSplitActionActionCancelCaseSynchronization"
version="1">
+ <node id="1" type="Start">
+ <outNode id="2"/>
+ </node>
+ <node id="2" type="ParallelSplit">
+ <outNode id="3"/>
+ <outNode id="6"/>
+ <outNode id="7"/>
+ </node>
+ <node id="3" type="Action" serviceObjectClass="ServiceObject">
+ <outNode id="4"/>
+ </node>
+ <node id="4" type="Synchronization">
+ <outNode id="5"/>
+ </node>
+ <node id="5" type="End"/>
+ <node id="6" type="Action" serviceObjectClass="ServiceObject">
+ <outNode id="4"/>
+ </node>
+ <node id="7" type="Cancel">
+ <outNode id="4"/>
+ </node>
+</workflow>
Propchange:
trunk/Workflow/tests/data/ParallelSplitActionActionCancelCaseSynchronization_1.xml
------------------------------------------------------------------------------
svn:eol-style = native
Added:
trunk/Workflow/tests/data/ParallelSplitCancelCaseActionActionSynchronization.dot
==============================================================================
---
trunk/Workflow/tests/data/ParallelSplitCancelCaseActionActionSynchronization.dot
(added)
+++
trunk/Workflow/tests/data/ParallelSplitCancelCaseActionActionSynchronization.dot
[iso-8859-1] Mon Jan 21 17:04:16 2008
@@ -1,0 +1,18 @@
+digraph ParallelSplitCancelCaseActionActionSynchronization {
+node1 [label="Start"]
+node2 [label="Parallel Split"]
+node3 [label="Cancel"]
+node4 [label="Synchronization"]
+node5 [label="End"]
+node6 [label=""]
+node7 [label=""]
+
+node1 -> node2
+node2 -> node3
+node2 -> node6
+node2 -> node7
+node3 -> node4
+node4 -> node5
+node6 -> node4
+node7 -> node4
+}
Propchange:
trunk/Workflow/tests/data/ParallelSplitCancelCaseActionActionSynchronization.dot
------------------------------------------------------------------------------
svn:eol-style = native
Added:
trunk/Workflow/tests/data/ParallelSplitCancelCaseActionActionSynchronization_1.xml
==============================================================================
---
trunk/Workflow/tests/data/ParallelSplitCancelCaseActionActionSynchronization_1.xml
(added)
+++
trunk/Workflow/tests/data/ParallelSplitCancelCaseActionActionSynchronization_1.xml
[iso-8859-1] Mon Jan 21 17:04:16 2008
@@ -1,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<workflow name="ParallelSplitCancelCaseActionActionSynchronization"
version="1">
+ <node id="1" type="Start">
+ <outNode id="2"/>
+ </node>
+ <node id="2" type="ParallelSplit">
+ <outNode id="3"/>
+ <outNode id="6"/>
+ <outNode id="7"/>
+ </node>
+ <node id="3" type="Cancel">
+ <outNode id="4"/>
+ </node>
+ <node id="4" type="Synchronization">
+ <outNode id="5"/>
+ </node>
+ <node id="5" type="End"/>
+ <node id="6" type="Action" serviceObjectClass="ServiceObject">
+ <outNode id="4"/>
+ </node>
+ <node id="7" type="Action" serviceObjectClass="ServiceObject">
+ <outNode id="4"/>
+ </node>
+</workflow>
Propchange:
trunk/Workflow/tests/data/ParallelSplitCancelCaseActionActionSynchronization_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] Mon Jan 21
17:04:16 2008
@@ -274,6 +274,28 @@
);
}
+ public function
testSaveParallelSplitCancelCaseActionActionSynchronization()
+ {
+ $this->setUpCancelCase( 'first' );
+ $this->definition->save( $this->workflow );
+
+ $this->assertEquals(
+ $this->readExpected(
'ParallelSplitCancelCaseActionActionSynchronization' ),
+ $this->readActual(
'ParallelSplitCancelCaseActionActionSynchronization' )
+ );
+ }
+
+ public function
testSaveParallelSplitActionActionCancelCaseSynchronization()
+ {
+ $this->setUpCancelCase( 'last' );
+ $this->definition->save( $this->workflow );
+
+ $this->assertEquals(
+ $this->readExpected(
'ParallelSplitActionActionCancelCaseSynchronization' ),
+ $this->readActual(
'ParallelSplitActionActionCancelCaseSynchronization' )
+ );
+ }
+
public function testLoadStartEnd()
{
$this->workflow = $this->definition->loadByName( 'StartEnd' );
@@ -512,6 +534,28 @@
$this->assertEquals(
$this->readExpected( 'NestedLoops' ),
$this->readActual( 'NestedLoops' )
+ );
+ }
+
+ public function
testLoadParallelSplitCancelCaseActionActionSynchronization()
+ {
+ $this->workflow = $this->definition->loadByName(
'ParallelSplitCancelCaseActionActionSynchronization' );
+ $this->definition->save( $this->workflow );
+
+ $this->assertEquals(
+ $this->readExpected(
'ParallelSplitCancelCaseActionActionSynchronization' ),
+ $this->readActual(
'ParallelSplitCancelCaseActionActionSynchronization' )
+ );
+ }
+
+ public function
testLoadParallelSplitActionActionCancelCaseSynchronization()
+ {
+ $this->workflow = $this->definition->loadByName(
'ParallelSplitActionActionCancelCaseSynchronization' );
+ $this->definition->save( $this->workflow );
+
+ $this->assertEquals(
+ $this->readExpected(
'ParallelSplitActionActionCancelCaseSynchronization' ),
+ $this->readActual(
'ParallelSplitActionActionCancelCaseSynchronization' )
);
}
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] Mon Jan 21 17:04:16
2008
@@ -35,6 +35,7 @@
$this->execution->workflow = $this->workflow;
$this->execution->start();
+ $this->assertFalse( $this->execution->isCancelled() );
$this->assertTrue( $this->execution->hasEnded() );
$this->assertFalse( $this->execution->isResumed() );
$this->assertFalse( $this->execution->isSuspended() );
@@ -46,6 +47,7 @@
$this->execution->workflow = $this->workflow;
$this->execution->start();
+ $this->assertFalse( $this->execution->isCancelled() );
$this->assertTrue( $this->execution->hasEnded() );
$this->assertFalse( $this->execution->isResumed() );
$this->assertFalse( $this->execution->isSuspended() );
@@ -59,6 +61,7 @@
$this->execution->setInputVariable( 'variable', 'value' );
$this->execution->start();
+ $this->assertFalse( $this->execution->isCancelled() );
$this->assertTrue( $this->execution->hasEnded() );
$this->assertFalse( $this->execution->isResumed() );
$this->assertFalse( $this->execution->isSuspended() );
@@ -81,6 +84,7 @@
$this->assertArrayHasKey( 'variable', $e->errors );
$this->assertContains( 'is string', $e->errors );
+ $this->assertFalse( $this->execution->isCancelled() );
$this->assertFalse( $this->execution->hasEnded() );
$this->assertTrue( $this->execution->isResumed() );
$this->assertFalse( $this->execution->isSuspended() );
@@ -178,6 +182,7 @@
$this->execution->workflow = $this->workflow;
$this->execution->start();
+ $this->assertFalse( $this->execution->isCancelled() );
$this->assertTrue( $this->execution->hasEnded() );
$this->assertFalse( $this->execution->isResumed() );
$this->assertFalse( $this->execution->isSuspended() );
@@ -189,6 +194,7 @@
$this->execution->workflow = $this->workflow;
$this->execution->start();
+ $this->assertFalse( $this->execution->isCancelled() );
$this->assertTrue( $this->execution->hasEnded() );
$this->assertFalse( $this->execution->isResumed() );
$this->assertFalse( $this->execution->isSuspended() );
@@ -200,6 +206,7 @@
$this->execution->workflow = $this->workflow;
$this->execution->start();
+ $this->assertFalse( $this->execution->isCancelled() );
$this->assertTrue( $this->execution->hasEnded() );
$this->assertFalse( $this->execution->isResumed() );
$this->assertFalse( $this->execution->isSuspended() );
@@ -211,6 +218,7 @@
$this->execution->workflow = $this->workflow;
$this->execution->start();
+ $this->assertFalse( $this->execution->isCancelled() );
$this->assertTrue( $this->execution->hasEnded() );
$this->assertFalse( $this->execution->isResumed() );
$this->assertFalse( $this->execution->isSuspended() );
@@ -223,6 +231,7 @@
$this->execution->workflow = $this->workflow;
$this->execution->start();
+ $this->assertFalse( $this->execution->isCancelled() );
$this->assertTrue( $this->execution->hasEnded() );
$this->assertFalse( $this->execution->isResumed() );
$this->assertFalse( $this->execution->isSuspended() );
@@ -269,6 +278,7 @@
$this->execution->workflow = $this->workflow;
$this->execution->start();
+ $this->assertFalse( $this->execution->isCancelled() );
$this->assertTrue( $this->execution->hasEnded() );
$this->assertFalse( $this->execution->isResumed() );
$this->assertFalse( $this->execution->isSuspended() );
@@ -281,6 +291,7 @@
$this->execution->workflow = $this->workflow;
$this->execution->start();
+ $this->assertFalse( $this->execution->isCancelled() );
$this->assertTrue( $this->execution->hasEnded() );
$this->assertFalse( $this->execution->isResumed() );
$this->assertFalse( $this->execution->isSuspended() );
@@ -293,6 +304,7 @@
$this->execution->setVariables( array( 'foo' => 'bar', 'bar' => 'foo'
) );
$this->execution->start();
+ $this->assertFalse( $this->execution->isCancelled() );
$this->assertTrue( $this->execution->hasEnded() );
$this->assertFalse( $this->execution->isResumed() );
$this->assertFalse( $this->execution->isSuspended() );
@@ -327,6 +339,7 @@
$this->execution->setVariables( array( 'condition' => true ) );
$this->execution->start();
+ $this->assertFalse( $this->execution->isCancelled() );
$this->assertTrue( $this->execution->hasEnded() );
$this->assertFalse( $this->execution->isResumed() );
$this->assertFalse( $this->execution->isSuspended() );
@@ -339,6 +352,7 @@
$this->execution->setVariables( array( 'condition' => false ) );
$this->execution->start();
+ $this->assertFalse( $this->execution->isCancelled() );
$this->assertTrue( $this->execution->hasEnded() );
$this->assertFalse( $this->execution->isResumed() );
$this->assertFalse( $this->execution->isSuspended() );
@@ -397,6 +411,7 @@
$this->execution->setVariables( array( 'condition' => true ) );
$this->execution->start();
+ $this->assertFalse( $this->execution->isCancelled() );
$this->assertTrue( $this->execution->hasEnded() );
$this->assertFalse( $this->execution->isResumed() );
$this->assertFalse( $this->execution->isSuspended() );
@@ -410,6 +425,7 @@
$this->execution->setVariables( array( 'condition' => false ) );
$this->execution->start();
+ $this->assertFalse( $this->execution->isCancelled() );
$this->assertTrue( $this->execution->hasEnded() );
$this->assertFalse( $this->execution->isResumed() );
$this->assertFalse( $this->execution->isSuspended() );
@@ -423,6 +439,7 @@
$this->execution->setVariables( array( 'condition' => false ) );
$this->execution->start();
+ $this->assertFalse( $this->execution->isCancelled() );
$this->assertTrue( $this->execution->hasEnded() );
$this->assertFalse( $this->execution->isResumed() );
$this->assertFalse( $this->execution->isSuspended() );
@@ -438,6 +455,7 @@
$this->execution->setVariables( array( 'condition' => true ) );
$this->execution->start();
+ $this->assertFalse( $this->execution->isCancelled() );
$this->assertTrue( $this->execution->hasEnded() );
$this->assertFalse( $this->execution->isResumed() );
$this->assertFalse( $this->execution->isSuspended() );
@@ -452,6 +470,7 @@
$this->execution->workflow = $this->workflow;
$this->execution->start();
+ $this->assertFalse( $this->execution->isCancelled() );
$this->assertTrue( $this->execution->hasEnded() );
$this->assertFalse( $this->execution->isResumed() );
$this->assertFalse( $this->execution->isSuspended() );
@@ -467,6 +486,7 @@
$this->execution->workflow = $this->workflow;
$this->execution->start();
+ $this->assertFalse( $this->execution->isCancelled() );
$this->assertTrue( $this->execution->hasEnded() );
$this->assertFalse( $this->execution->isResumed() );
$this->assertFalse( $this->execution->isSuspended() );
@@ -482,6 +502,7 @@
$this->execution->workflow = $this->workflow;
$this->execution->start();
+ $this->assertFalse( $this->execution->isCancelled() );
$this->assertTrue( $this->execution->hasEnded() );
$this->assertFalse( $this->execution->isResumed() );
$this->assertFalse( $this->execution->isSuspended() );
@@ -496,6 +517,7 @@
$this->execution->workflow = $this->workflow;
$this->execution->start();
+ $this->assertFalse( $this->execution->isCancelled() );
$this->assertTrue( $this->execution->hasEnded() );
$this->assertFalse( $this->execution->isResumed() );
$this->assertFalse( $this->execution->isSuspended() );
@@ -507,6 +529,7 @@
$this->execution->workflow = $this->workflow;
$this->execution->start();
+ $this->assertFalse( $this->execution->isCancelled() );
$this->assertTrue( $this->execution->hasEnded() );
$this->assertFalse( $this->execution->isResumed() );
$this->assertFalse( $this->execution->isSuspended() );
@@ -519,6 +542,7 @@
$this->execution->workflow = $this->workflow;
$this->execution->start();
+ $this->assertFalse( $this->execution->isCancelled() );
$this->assertTrue( $this->execution->hasEnded() );
$this->assertFalse( $this->execution->isResumed() );
$this->assertFalse( $this->execution->isSuspended() );
@@ -554,6 +578,7 @@
$this->execution->setInputVariableForSubWorkflow( 'variable', 'value'
);
$this->execution->start();
+ $this->assertFalse( $this->execution->isCancelled() );
$this->assertTrue( $this->execution->hasEnded() );
$this->assertFalse( $this->execution->isResumed() );
$this->assertFalse( $this->execution->isSuspended() );
@@ -565,6 +590,7 @@
$this->execution->workflow = $this->workflow;
$this->execution->start();
+ $this->assertFalse( $this->execution->isCancelled() );
$this->assertTrue( $this->execution->hasEnded() );
$this->assertFalse( $this->execution->isResumed() );
$this->assertFalse( $this->execution->isSuspended() );
@@ -598,6 +624,7 @@
$this->execution->workflow = $this->workflow;
$this->execution->start();
+ $this->assertFalse( $this->execution->isCancelled() );
$this->assertTrue( $this->execution->hasEnded() );
$this->assertFalse( $this->execution->isResumed() );
$this->assertFalse( $this->execution->isSuspended() );
@@ -613,12 +640,37 @@
$this->execution->workflow = $this->workflow;
$this->execution->start();
+ $this->assertFalse( $this->execution->isCancelled() );
$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
testExecuteParallelSplitCancelCaseActionActionSynchronization()
+ {
+ $this->setUpCancelCase( 'first' );
+ $this->execution->workflow = $this->workflow;
+ $this->execution->start();
+
+ $this->assertTrue( $this->execution->isCancelled() );
+ $this->assertTrue( $this->execution->hasEnded() );
+ $this->assertFalse( $this->execution->isResumed() );
+ $this->assertFalse( $this->execution->isSuspended() );
+ }
+
+ public function
testExecuteParallelSplitActionActionCancelCaseSynchronization()
+ {
+ $this->setUpCancelCase( 'last' );
+ $this->execution->workflow = $this->workflow;
+ $this->execution->start();
+
+ $this->assertTrue( $this->execution->isCancelled() );
+ $this->assertTrue( $this->execution->hasEnded() );
+ $this->assertFalse( $this->execution->isResumed() );
+ $this->assertFalse( $this->execution->isSuspended() );
}
public function testListener()
Modified: trunk/Workflow/tests/visitor_visualization_test.php
==============================================================================
--- trunk/Workflow/tests/visitor_visualization_test.php [iso-8859-1] (original)
+++ trunk/Workflow/tests/visitor_visualization_test.php [iso-8859-1] Mon Jan 21
17:04:16 2008
@@ -227,6 +227,28 @@
);
}
+ public function
testVisitParallelSplitCancelCaseActionActionSynchronization()
+ {
+ $this->setUpCancelCase( 'first' );
+ $this->workflow->accept( $this->visitor );
+
+ $this->assertEquals(
+ $this->readExpected(
'ParallelSplitCancelCaseActionActionSynchronization' ),
+ $this->visitor->__toString()
+ );
+ }
+
+ public function
testVisitParallelSplitActionActionCancelCaseSynchronization()
+ {
+ $this->setUpCancelCase( 'last' );
+ $this->workflow->accept( $this->visitor );
+
+ $this->assertEquals(
+ $this->readExpected(
'ParallelSplitActionActionCancelCaseSynchronization' ),
+ $this->visitor->__toString()
+ );
+ }
+
protected function readExpected( $name )
{
return file_get_contents(
Modified: trunk/WorkflowDatabaseTiein/ChangeLog
==============================================================================
--- trunk/WorkflowDatabaseTiein/ChangeLog [iso-8859-1] (original)
+++ trunk/WorkflowDatabaseTiein/ChangeLog [iso-8859-1] Mon Jan 21 17:04:16 2008
@@ -1,3 +1,5 @@
+- Implemented issue #10941: Support for the Cancel Case workflow pattern.
+
- Fixed issue #12403: Multiple construction of
ezcWorkflowDatabaseDefinitionStorage.
Modified: trunk/WorkflowDatabaseTiein/src/execution.php
==============================================================================
--- trunk/WorkflowDatabaseTiein/src/execution.php [iso-8859-1] (original)
+++ trunk/WorkflowDatabaseTiein/src/execution.php [iso-8859-1] Mon Jan 21
17:04:16 2008
@@ -136,7 +136,10 @@
$this->cleanupTable( 'execution' );
$this->cleanupTable( 'execution_state' );
- $this->db->commit();
+ if ( !$this->isCancelled() )
+ {
+ $this->db->commit();
+ }
}
/**
Added:
trunk/WorkflowEventLogTiein/tests/data/ParallelSplitActionActionCancelCaseSynchronization.log
==============================================================================
---
trunk/WorkflowEventLogTiein/tests/data/ParallelSplitActionActionCancelCaseSynchronization.log
(added)
+++
trunk/WorkflowEventLogTiein/tests/data/ParallelSplitActionActionCancelCaseSynchronization.log
[iso-8859-1] Mon Jan 21 17:04:16 2008
@@ -1,0 +1,19 @@
+MMM DD HH:MM:SS [Info] [default] [default] Started execution #1 of workflow
"ParallelSplitActionActionCancelCaseSynchronization" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Activated node
#1(ezcWorkflowNodeStart) for instance #1 of workflow
"ParallelSplitActionActionCancelCaseSynchronization" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Started thread #0 (1 sibling(s))
for execution #1 of workflow
"ParallelSplitActionActionCancelCaseSynchronization" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Activated node
#2(ezcWorkflowNodeParallelSplit) for instance #1 of workflow
"ParallelSplitActionActionCancelCaseSynchronization" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Executed node
#1(ezcWorkflowNodeStart) for instance #1 of workflow
"ParallelSplitActionActionCancelCaseSynchronization" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Started thread #1 (3 sibling(s))
for execution #1 of workflow
"ParallelSplitActionActionCancelCaseSynchronization" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Activated node
#3(ezcWorkflowNodeAction) for instance #1 of workflow
"ParallelSplitActionActionCancelCaseSynchronization" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Started thread #2 (3 sibling(s))
for execution #1 of workflow
"ParallelSplitActionActionCancelCaseSynchronization" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Activated node
#6(ezcWorkflowNodeAction) for instance #1 of workflow
"ParallelSplitActionActionCancelCaseSynchronization" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Started thread #3 (3 sibling(s))
for execution #1 of workflow
"ParallelSplitActionActionCancelCaseSynchronization" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Activated node
#7(ezcWorkflowNodeCancel) for instance #1 of workflow
"ParallelSplitActionActionCancelCaseSynchronization" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Executed node
#2(ezcWorkflowNodeParallelSplit) for instance #1 of workflow
"ParallelSplitActionActionCancelCaseSynchronization" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Activated node
#4(ezcWorkflowNodeSynchronization) for instance #1 of workflow
"ParallelSplitActionActionCancelCaseSynchronization" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Executed node
#3(ezcWorkflowNodeAction) for instance #1 of workflow
"ParallelSplitActionActionCancelCaseSynchronization" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Executed node
#6(ezcWorkflowNodeAction) for instance #1 of workflow
"ParallelSplitActionActionCancelCaseSynchronization" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Could not roll back service object
"ServiceObject" of node #3 for instance #1 of workflow
"ParallelSplitActionActionCancelCaseSynchronization" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Could not roll back service object
"ServiceObject" of node #6 for instance #1 of workflow
"ParallelSplitActionActionCancelCaseSynchronization" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Executed node
#7(ezcWorkflowNodeCancel) for instance #1 of workflow
"ParallelSplitActionActionCancelCaseSynchronization" (version 1).
+MMM DD HH:MM:SS [Info] [default] [default] Cancelled execution #1 of workflow
"ParallelSplitActionActionCancelCaseSynchronization" (version 1).
Propchange:
trunk/WorkflowEventLogTiein/tests/data/ParallelSplitActionActionCancelCaseSynchronization.log
------------------------------------------------------------------------------
svn:eol-style = native
Added:
trunk/WorkflowEventLogTiein/tests/data/ParallelSplitCancelCaseActionActionSynchronization.log
==============================================================================
---
trunk/WorkflowEventLogTiein/tests/data/ParallelSplitCancelCaseActionActionSynchronization.log
(added)
+++
trunk/WorkflowEventLogTiein/tests/data/ParallelSplitCancelCaseActionActionSynchronization.log
[iso-8859-1] Mon Jan 21 17:04:16 2008
@@ -1,0 +1,14 @@
+MMM DD HH:MM:SS [Info] [default] [default] Started execution #1 of workflow
"ParallelSplitCancelCaseActionActionSynchronization" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Activated node
#1(ezcWorkflowNodeStart) for instance #1 of workflow
"ParallelSplitCancelCaseActionActionSynchronization" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Started thread #0 (1 sibling(s))
for execution #1 of workflow
"ParallelSplitCancelCaseActionActionSynchronization" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Activated node
#2(ezcWorkflowNodeParallelSplit) for instance #1 of workflow
"ParallelSplitCancelCaseActionActionSynchronization" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Executed node
#1(ezcWorkflowNodeStart) for instance #1 of workflow
"ParallelSplitCancelCaseActionActionSynchronization" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Started thread #1 (3 sibling(s))
for execution #1 of workflow
"ParallelSplitCancelCaseActionActionSynchronization" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Activated node
#3(ezcWorkflowNodeCancel) for instance #1 of workflow
"ParallelSplitCancelCaseActionActionSynchronization" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Started thread #2 (3 sibling(s))
for execution #1 of workflow
"ParallelSplitCancelCaseActionActionSynchronization" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Activated node
#6(ezcWorkflowNodeAction) for instance #1 of workflow
"ParallelSplitCancelCaseActionActionSynchronization" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Started thread #3 (3 sibling(s))
for execution #1 of workflow
"ParallelSplitCancelCaseActionActionSynchronization" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Activated node
#7(ezcWorkflowNodeAction) for instance #1 of workflow
"ParallelSplitCancelCaseActionActionSynchronization" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Executed node
#2(ezcWorkflowNodeParallelSplit) for instance #1 of workflow
"ParallelSplitCancelCaseActionActionSynchronization" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Executed node
#3(ezcWorkflowNodeCancel) for instance #1 of workflow
"ParallelSplitCancelCaseActionActionSynchronization" (version 1).
+MMM DD HH:MM:SS [Info] [default] [default] Cancelled execution #1 of workflow
"ParallelSplitCancelCaseActionActionSynchronization" (version 1).
Propchange:
trunk/WorkflowEventLogTiein/tests/data/ParallelSplitCancelCaseActionActionSynchronization.log
------------------------------------------------------------------------------
svn:eol-style = native
Added:
trunk/WorkflowEventLogTiein/tests/data/ParallelSplitSynchronizationCancelCase.log
==============================================================================
---
trunk/WorkflowEventLogTiein/tests/data/ParallelSplitSynchronizationCancelCase.log
(added)
+++
trunk/WorkflowEventLogTiein/tests/data/ParallelSplitSynchronizationCancelCase.log
[iso-8859-1] Mon Jan 21 17:04:16 2008
@@ -1,0 +1,14 @@
+MMM DD HH:MM:SS [Info] [default] [default] Started execution #1 of workflow
"ParallelSplitSynchronizationCancelCase" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Activated node
#1(ezcWorkflowNodeStart) for instance #1 of workflow
"ParallelSplitSynchronizationCancelCase" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Started thread #0 (1 sibling(s))
for execution #1 of workflow "ParallelSplitSynchronizationCancelCase" (version
1).
+MMM DD HH:MM:SS [Debug] [default] [default] Activated node
#2(ezcWorkflowNodeParallelSplit) for instance #1 of workflow
"ParallelSplitSynchronizationCancelCase" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Executed node
#1(ezcWorkflowNodeStart) for instance #1 of workflow
"ParallelSplitSynchronizationCancelCase" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Started thread #1 (3 sibling(s))
for execution #1 of workflow "ParallelSplitSynchronizationCancelCase" (version
1).
+MMM DD HH:MM:SS [Debug] [default] [default] Activated node
#3(ezcWorkflowNodeCancel) for instance #1 of workflow
"ParallelSplitSynchronizationCancelCase" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Started thread #2 (3 sibling(s))
for execution #1 of workflow "ParallelSplitSynchronizationCancelCase" (version
1).
+MMM DD HH:MM:SS [Debug] [default] [default] Activated node
#6(ezcWorkflowNodeAction) for instance #1 of workflow
"ParallelSplitSynchronizationCancelCase" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Started thread #3 (3 sibling(s))
for execution #1 of workflow "ParallelSplitSynchronizationCancelCase" (version
1).
+MMM DD HH:MM:SS [Debug] [default] [default] Activated node
#7(ezcWorkflowNodeAction) for instance #1 of workflow
"ParallelSplitSynchronizationCancelCase" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Executed node
#2(ezcWorkflowNodeParallelSplit) for instance #1 of workflow
"ParallelSplitSynchronizationCancelCase" (version 1).
+MMM DD HH:MM:SS [Debug] [default] [default] Executed node
#3(ezcWorkflowNodeCancel) for instance #1 of workflow
"ParallelSplitSynchronizationCancelCase" (version 1).
+MMM DD HH:MM:SS [Info] [default] [default] Cancelled execution #1 of workflow
"ParallelSplitSynchronizationCancelCase" (version 1).
Propchange:
trunk/WorkflowEventLogTiein/tests/data/ParallelSplitSynchronizationCancelCase.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] Mon Jan 21
17:04:16 2008
@@ -344,5 +344,31 @@
$this->readActual()
);
}
+
+ public function testLogParallelSplitCancelCaseActionActionSynchronization()
+ {
+ $this->setUpCancelCase( 'first' );
+ $this->definition->save( $this->workflow );
+ $this->execution->workflow = $this->workflow;
+ $this->execution->start();
+
+ $this->assertEquals(
+ $this->readExpected(
'ParallelSplitCancelCaseActionActionSynchronization' ),
+ $this->readActual()
+ );
+ }
+
+ public function testLogParallelSplitActionActionCancelCaseSynchronization()
+ {
+ $this->setUpCancelCase( 'last' );
+ $this->definition->save( $this->workflow );
+ $this->execution->workflow = $this->workflow;
+ $this->execution->start();
+
+ $this->assertEquals(
+ $this->readExpected(
'ParallelSplitActionActionCancelCaseSynchronization' ),
+ $this->readActual()
+ );
+ }
}
?>
--
svn-components mailing list
[email protected]
http://lists.ez.no/mailman/listinfo/svn-components