Personal tools
You are here: Home Products Plone Roadmap #221: Use adaption for workflow history and status
Document Actions

#221: Use adaption for workflow history and status

Contents
  1. Definitions
  2. Motivation
  3. Assumptions
  4. Proposal
  5. Implementation
  6. Deliverables
  7. Risks
  8. Progress log
  9. Participants
by Laurence Rowe last modified December 17, 2007 - 00:26
The other major area that the workflow tool makes difficult to customize is the storage of workflow history and status. This proposal attempts to address the issue by using adaption to determine how workflow history and status should be stored
Proposed by
Laurence Rowe
Proposal type
Architecture
State
being-discussed

Definitions

 

Motivation

Currently it is very difficult to use alternate mechanisms for storing workflow history. For example collective.tin needs a content mixin class defining a workflow_history property in order to store workflow history in a database.

This proposal is inspired by Kapil's work in cmfblackbird and my experience building collective.tin.

Assumptions

 

Proposal

Providing workflow history storage via adaptation is a pretty trivial task which can be made fully backward compatible. We simply need to replace the content of the WorkflowTool.getHistoryOf , setStatusOf  methods with a lookup via adaptation:

    def getHistoryOf(self, wf_id, ob):
""" Get the history of an object for a given workflow.
"""
return queryMultiAdapter((ob, wf_id), IWorkflowHistory, default=())

def setStatusOf(self, wf_id, ob, status):
""" Append a record to the workflow history of a given workflow.
"""
wfs = getMultiAdapter((ob, wf_id), IWorkflowStatus)
wfs.set(status)

def getStatusOf(self, wf_id, ob):
""" Get the last element of a workflow history for a given workflow.
"""
wfs = queryMultiAdapter((ob, wf_id), IWorkflowStatus, default=None)
if wfs:
return wfs.get()
return None

Multi-adapters on the content object and workflow id are used. This allows for content type developers and integrators to customise the storage of workflow status and optionally history for either all workflows or individual workflows (by registering a multiadapter for (IContentish, 'workflow_id'). The default adapters are simply:

class DefaultWorkflowStatus(object):
implements(IWorkflowStatus)
adapts(IContentish, basestring)

def __init__(self, context, wf_id):
self.context = aq_base(context)
self.wf_id = wf_id

def get(self):
history = getattr(self.context, 'workflow_history', {})
return history.get(self.wf_id, None)
def set(self, status):
history = getattr(self.context, 'workflow_history', None)
if history is None:
history = self.context.workflow_history = PersistentMapping()
wfh = list(history.get(self.wf_id, ()))
wfh.append(status)
history[self.wf_id] = tuple(wfh)


@implementer(IWorkflowHistory)
@adapter(IContentish, basestring)
def default_workflow_history(context, wf_id):
history = getattr(aq_base(context), 'workflow_history', {})
return history.get(self.wf_id, ())

Interfaces are:

class IWorkflowStatus(Interface):

    def get():
        """Return the workflow status"""

    def set(status):
        """Update the workflow status to `status`"""

class IWorkflowHistory(Interface):
    """A sequence of workflow status dictionaries"""

Ideally this would be done in CMFCore. However, it's certainly feasible to do it inside of the CMFPlone workflow tool if no major release of CMF is imminent. The changes could easily be merged back into the core as needed.

Implementation

 

Deliverables

  • The interfaces for IWorkflowHistory and IWorkflowStatus would need to be created.
  • The getWorkflowHistory, setStatusOf and getStatusOf methods would need to be rewritten/overridden, and a test would need to be written to demonstrate the adaptation based mechanism.
  • The default adapters would need to be created
  • Some documentation on how to provide a custom workflow history and status storage should be provided.

Risks

There should be no risk as the WorkflowTool interface and default history storage remain consistent. The only risk is that our workflow tool will deviate further from the CMF version, hopefully we can get this code applied in CMFCore sooner rather than later.

Progress log

 

Participants

 

Framework team vote

Posted by Raphael Ritz at December 17, 2007 - 12:45
+1 (I don't mind the delay in this case as I consider it an enhancement of Alec's PLIP #217 which I'm also in favor of rather then something new)

Framework vote

Posted by Martijn Pieters at December 21, 2007 - 22:51
-1 as I prefer this going straight into CMF; there is no pressing need to do this now.

Framework team vote

Posted by Andreas Zeidler at December 22, 2007 - 10:00
±0 (see http://lists.plone.org/pipermail/framework-team/2007-December/001625.html)

Framework team vote

Posted by Tom Lazar at December 22, 2007 - 15:10
abstained. i *think* this should probably go into CMFWorkflow but i'm not really knowledgeable enough on the matter to reach an informed decision.

Framework team vote

Posted by Danny Bloemendaal at December 22, 2007 - 16:10
+/-

another implementation.. also backwards compatible

Posted by Kapil Thangavelu at January 3, 2008 - 17:36

+1

that blackbird link is pretty old.. i separated out the functionality and put in into an egg.. here's the guts
http://svn.objectrealms.net/view/public/browser/ore.adaptedworkflow/trunk/src/ore/adaptedworkflow

i agree it should probably go in the cmf

Putting it into CMF

Posted by Laurence Rowe at January 3, 2008 - 17:41
I'm discussing this on zope-cmf at the moment, any input there appreciated.

For any issues with the web site functionality, please file a ticket.

Please consult the policy on plone.org content if you want your content published on this site.

Servers and hosting by