[Zope-CVS] CVS: Packages3/workflow/stateful - __init__.py:1.1 configure.zcml:1.1 contentworkflow.py:1.1 definition.py:1.1 instance.py:1.1
Ulrich Eck
ueck@net-labs.de
Tue, 4 Feb 2003 16:42:21 -0500
Update of /cvs-repository/Packages3/workflow/stateful
In directory cvs.zope.org:/tmp/cvs-serv29212
Added Files:
__init__.py configure.zcml contentworkflow.py definition.py
instance.py
Log Message:
migration of stateful workflow implementation from rotterdam.
tests pass, not yet much functionality
=== Added File Packages3/workflow/stateful/__init__.py ===
=== Added File Packages3/workflow/stateful/configure.zcml ===
<zopeConfigure
xmlns="http://namespaces.zope.org/zope">
<content class="zope.app.workflow.stateful.contentworkflow.ContentWorkflowsUtility">
<require
permission="zope.ManageServices"
interface="zope.app.interfaces.workflow.stateful.IContentWorkflowsUtility"
/>
<factory
id="zope.app.workflow.stateful.contentworkflow.ContentWorkflowsUtility"
permission="zope.ManageServices"
/>
</content>
</zopeConfigure>
=== Added File Packages3/workflow/stateful/contentworkflow.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Content Workflows Utility
Associates content objects with some workflow process definitions.
$Id: contentworkflow.py,v 1.1 2003/02/04 21:42:18 jack-e Exp $
"""
__metaclass__ = type
from zope.interface import Interface
from persistence import Persistent
from zope.component import getService, queryAdapter
from zope.component.exceptions import ComponentLookupError
from zope.proxy.context import ContextMethod
from zope.app.interfaces.event import ISubscriber
from zope.app.interfaces.services.hub import IRegistrationHubEvent
from zope.app.interfaces.services.hub import IObjectRegisteredHubEvent
from zope.app.interfaces.services.hub import IObjectUnregisteredHubEvent
from zope.app.interfaces.workflow import IProcessInstanceContainer
from zope.app.interfaces.workflow import IContentWorkflowsUtility
class ContentWorkflowsUtility(Persistent):
__implements__ = IContentWorkflowsUtility, ISubscriber
def __init__(self):
super(ContentWorkflowsUtility, self).__init__()
self._names = () # _names should be a TypeRegistry
# ISubscriber
def notify(self, event):
"""An event occured. Perhaps register this object with the hub."""
pi_container = queryAdapter(event.object, IProcessInstanceContainer)
# probably need to adapt to IZopeContainer to use pi_container with
# context.
if pi_container is None:
# Object can't have associated PIs.
return
if IObjectRegisteredHubEvent.isImplementedBy(event):
wfs = getService(self, "Workflows")
# here we will lookup the configured processdefinitions
# for the newly created compoent. For every pd_name
# returned we will create a processinstance.
for pd_name in self._names:
try:
pi = wfs.createProcessInstance(pd_name)
except KeyError:
# No registered PD with that name..
continue
# XXX What happens if there's already a pi with that name?
container[pd_name] = pi
elif IObjectUnregisteredHubEvent.isImplementedBy(event):
for pd_name in self._names:
if pd_name in container:
# give the pi a chanche to know that it's going
# to be deleted ??
del container[pd_name]
notify = ContextMethod(notify)
# IContentWorkflowsUtility
# control
currentlySubscribed = False # Default subscription state
def subscribe(self):
if self.currentlySubscribed:
raise ValueError, "already subscribed; please unsubscribe first"
channel = self._getChannel(None)
channel.subscribe(self, IRegistrationHubEvent)
self.currentlySubscribed = True
subscribe = ContextMethod(subscribe)
def unsubscribe(self):
if not self.currentlySubscribed:
raise ValueError, "not subscribed; please subscribe first"
channel = self._getChannel(None)
channel.unsubscribe(self, IRegistrationHubEvent)
self.currentlySubscribed = False
unsubscribe = ContextMethod(unsubscribe)
def isSubscribed(self):
return self.currentlySubscribed
def _getChannel(self, channel):
if channel is None:
channel = getService(self, "ObjectHub")
return channel
_getChannel = ContextMethod(_getChannel)
# config
def getProcessDefinitionNames(self):
"""Get the process definition names."""
return self._names
def setProcessDefinitionNames(self, names):
"""Set the process definition names."""
self._names = tuple(names)
=== Added File Packages3/workflow/stateful/definition.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Stateful workflow process definition.
$Id: definition.py,v 1.1 2003/02/04 21:42:18 jack-e Exp $
"""
__metaclass__ = type
from persistence import Persistent
from persistence.dict import PersistentDict
from zope.proxy.context import ContextMethod, ContextWrapper
from zope.proxy.context import getWrapperData
from zope.app.interfaces.workflow import IProcessDefinition
from zope.app.interfaces.workflow.stateful \
import IStatefulProcessDefinition, IState, ITransition
from zope.app.workflow.definition import ProcessDefinition
from zope.app.workflow.stateful.instance import StatefulProcessInstance
class State:
"""State."""
__implements__ = IState
class Transition:
"""Transition."""
__implements__ = ITransition
def __init__(self, source, destination, condition):
super(Transition, self).__init__()
self._source = source
self._destination = destination
self._condition = condition
sourceState = property(lambda self: self._source)
destinationState = property(lambda self: self._destination)
condition = property(lambda self: self._condition)
class StatefulProcessDefinition(ProcessDefinition):
"""Stateful workflow process definition."""
__implements__ = IStatefulProcessDefinition
def __init__(self):
super(StatefulProcessDefinition, self).__init__()
self.__states = PersistentDict()
initial = State()
self.__states[self.getInitialStateName()] = initial
self.__transitions = PersistentDict()
############################################################
# Implementation methods for interface
# zope.app.interfaces.workflow.stateful.IStatefulProcessDefinition
def addState(self, name, state):
if name in self.__states:
raise KeyError, name
self.__states[name] = state
def getState(self, name):
return ContextWrapper(self.__states[name], self)
getState = ContextMethod(getState)
def removeState(self, name):
del self.__states[name]
def getStateNames(self):
return self.__states.keys()
def getInitialStateName(self):
return 'INITIAL'
def addTransition(self, name, transition):
if name in self.__transitions:
raise KeyError, name
self.__transitions[name] = transition
def getTransition(self, name):
return ContextWrapper(self.__transitions[name], self)
getTransition = ContextMethod(getTransition)
def removeTransition(self, name):
del self.__transitions[name]
def getTransitionNames(self):
return self.__transitions.keys()
# IProcessDefinition
def createProcessInstance(self):
pd_name = getWrapperData(self)['name']
initial_state = self.getInitialState()
pi_obj = StatefulProcessInstance(pd_name, initial_state)
return pi_obj
createProcessInstance = ContextMethod(createProcessInstance)
#
############################################################
=== Added File Packages3/workflow/stateful/instance.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Content Workflows Utility
Associates content objects with some workflow process definitions.
$Id: instance.py,v 1.1 2003/02/04 21:42:18 jack-e Exp $
"""
__metaclass__ = type
from persistence import Persistent
from zope.component import getService
from zope.app.interfaces.workflow.stateful import IStatefulProcessInstance
from zope.app.workflow.instance import ProcessInstance
class StatefulProcessInstance(ProcessInstance, Persistent):
"""Stateful Workflow ProcessInstance.
"""
__implements__ = IStatefulProcessInstance
def __init__(self, pd_name, initial_state):
super(StatefulProcessInstance, self).__init__(pd_name, initial_state)
############################################################
# Implementation methods for interface
# zope.app.interfaces.workflow.IStatefulProcessInstance
def getOutgoingTransitions(self):
pass
def fireTransition(self, id):
pass
#
############################################################
def _getProcessDefinition(self):
"""Get the ProcessDefinition object from WorkflowService.
only call from within a ContextWrapped Method.
"""
svc = getService(self, "Workflows")
return svc.getProcessDefinition(self.processDefinition)