[Zope3-dev] Enhanced Workflow
Jeffrey P Shell
jeffrey@cuemedia.com
Fri, 14 Dec 2001 14:18:49 -0700
On Friday, December 14, 2001, at 06:13 PM, Florent Guillaume wrote:
>>> Given the current CMF model, it is rather painful to publish an
>>> single
>>> folder of documents or an entire folder tree at once -- each document
>>> is independent and has no relation to its parent folders.
>>
>> Good point!
>
> I'll have a proposal written up this week-end about this.
>
> Basically (this will be for Zope2, and adapt for Zope3) I propose to
> define two new interfaces, _isWorkflowManager and _isWorkflowAware.
>
> An object that is a WorkflowManager is consulted by the Workflow Tool
> one behalf of any of its children when taking workflow-related
> decisions
> (find available actions, do action, find available workflows).
>
> An object that is WorkflowAware is directly consulted by the Workflow
> Tool for the same decisions. In both cases the object can decide to
> fallback on the standard behaviour, but can also change its state, etc.
>
> A combination of the two can pretty easily do what's proposed at
> the top
> of this message : when a WorkflowAware ObjectManager changes state, it
> can impose the same state recursively to all its children. And if it is
> also WorkflowManager it can veto any independant state change of the
> children. Or do more complex things.
I've been debating in my head where this policy makes sense -
should it be in the Workflow Agent, or the end object? Coming back
around to a task management system - I have it in my workflow
policy that a task cannot be put in an outside state unless all of
its subtasks (a task is a container, and based on its portal type
may hold just other Tasks or other objects as well) are in an
outside state (ie - Cancelled, Denied, or Completed). I don't care
about other workflows affecting other contained objects - an Image
may be published or not (I've actually replaced the default
workflow with an auto-publisher that is different than the default
CMF flow).
Currently, when you go to change the state on a Task, it does a
catalog query to find all subtasks that are not in an outside
state. One still has to go to them each manually and change their
state, but I'm going to put the ability to affect all of them into
either the workflow agent itself, or at least into the skin. I
don't think that a Task itself should have to worry about this at
all.
I really like having all of the workflow related stuff *away* from
the Task. I don't think that so-called "content objects" should
have any workflow related code in them if they can help it (one
could argue that part of a Task's interface is its status, and that
the workflow defines that status. But I would like the idea of
using tasks in a workflow-free system where status setting followed
no real rules at all).
There's nothing stopping an object being consulted by a workflow
process for certain decisions. Granted, I haven't dealt too much
with DCWorkflow based process definitions - but in writing a Python
based one the object is passed in as an argument to almost all of
the methods specified in the interface a workflow agent has to
support, allowing the workflow to do its query. I *imagine* you
could do this with scripts in DCWorkflow. For example - if a task
is of a certain tasktype, such as 'software bug', it has an extra
'Testing' state that it can go into:
elif task_status == 'In Progress':
if content.TaskType() in self.testable_types:
append_action(('Testing', 'set_testing'))
...
elif task_status not in testable_states and \
ob.TaskType() not in self.testable_types:
raise Unauthorized, 'Not in a testing state'
So, the target object can be queried. This is, in fact, how I also
test the sub-tasks:
def notifyBefore(self, ob, action):
Catalog = getToolByName(self, 'portal_catalog')
to_outer = ('set_cancelled', 'set_denied', 'set_done')
if action in to_outer:
task_status = list(self._innerStates + self._freshStates)
path = '/'.join(ob.getPhysicalPath())
waiting = Catalog(path=path, task_status=task_status)
if waiting:
raise WorkflowException('There are subitems needing
review')
So, the current workflow architecture does support this. I could
change this 'notifyBefore' to send the current action to all of the
found subtasks if I wanted to change the policy to do that. I just
don't know how to do this in DCWorkflow since I haven't really used
it.
In summary - I believe that any policies about dealing with
associated objects should be handled by the workflow agents
themselves. Why? Because one might want to install a workflow
about publishing that is really screwed-down about publishing
associated objects ("I will not automatically publish all of these
connected things. You (the user) are expected to review them
yourself!"), or one might want to install a lax one ("Alright.
I'll publish all of these images I reference too. Fine by me!").
If that policy is put into the content objects themselves in any
way, you cut down on your ability to change policy later.
At most, I'd like 'WorkflowAware' and 'WorkflowManager' to be some
sort of decorator/adapter/whatever that wraps around the object
dynamically to set these policies.
In my opinion anyways.