[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)