[Zope3-checkins] CVS: Zope3/src/zope/app/workflow/stateful - configure.zcml:1.3 contentworkflow.py:1.7

Stephan Richter srichter@cosmos.phy.tufts.edu
Tue, 29 Jul 2003 20:01:00 -0400


Update of /cvs-repository/Zope3/src/zope/app/workflow/stateful
In directory cvs.zope.org:/tmp/cvs-serv20793/src/zope/app/workflow/stateful

Modified Files:
	configure.zcml contentworkflow.py 
Log Message:
Workflow enhancements to make them more useful. (More to come)

- ContentWorkflowsUtility has been renamed to ContentWorkflowsManager

- Specific Process Definitions can now be mapped to interfaces (later 
  content types), so that a content type only receives the workflows that
  were inteneded for it.

- Supplied a management screen for the above.

- Wrote a bunch of tests for ContentWorkflowsManager.

- Added a default screen to the Workflow Service, which lists all registered
  process definitions.


=== Zope3/src/zope/app/workflow/stateful/configure.zcml 1.2 => 1.3 ===
--- Zope3/src/zope/app/workflow/stateful/configure.zcml:1.2	Sat Jun 21 17:22:16 2003
+++ Zope3/src/zope/app/workflow/stateful/configure.zcml	Tue Jul 29 20:00:25 2003
@@ -4,7 +4,8 @@
 
 <!-- Stateful ProcessDefintion -->
 
-<content class="zope.app.workflow.stateful.definition.StatefulProcessDefinition">
+<content 
+    class="zope.app.workflow.stateful.definition.StatefulProcessDefinition">
   <factory
       id="StatefulProcessDefinition"
       permission="zope.workflow.ManageProcessDefinitions"
@@ -39,7 +40,7 @@
       />
   <require
       permission="zope.workflow.ManageProcessDefinitions"
-      interface="zope.app.interfaces.workflow.stateful.IStatefulStatesContainer" 
+      interface="zope.app.interfaces.workflow.stateful.IStatefulStatesContainer"
       />
   <implements 
       interface="zope.app.interfaces.annotation.IAttributeAnnotatable" 
@@ -96,16 +97,18 @@
       />
 </content>
 
-<!-- ContentWorkflowsUtility -->
+<!-- ContentWorkflowsManager -->
 
-<content class="zope.app.workflow.stateful.contentworkflow.ContentWorkflowsUtility">
-  <require
-    permission="zope.ManageServices"
-    interface="zope.app.interfaces.workflow.stateful.IContentWorkflowsUtility"
-    />
+<content 
+    class="zope.app.workflow.stateful.contentworkflow.ContentWorkflowsManager">
   <factory
-    id="ContentWorkflowsUtility"
+    id="ContentWorkflowsManager"
+    permission="zope.ManageServices"
+  />
+  <require
     permission="zope.ManageServices"
+    interface="zope.app.interfaces.workflow.stateful.IContentWorkflowsManager"
+    attributes="cpRegistry"
     />
 </content>
 


=== Zope3/src/zope/app/workflow/stateful/contentworkflow.py 1.6 => 1.7 ===
--- Zope3/src/zope/app/workflow/stateful/contentworkflow.py:1.6	Tue Jul 15 10:16:31 2003
+++ Zope3/src/zope/app/workflow/stateful/contentworkflow.py	Tue Jul 29 20:00:25 2003
@@ -11,7 +11,7 @@
 # FOR A PARTICULAR PURPOSE.
 #
 ##############################################################################
-"""Content Workflows Utility
+"""Content Workflows Manager
 
 Associates content objects with some workflow process definitions.
 
@@ -20,6 +20,7 @@
 __metaclass__ = type
 
 from persistence import Persistent
+from persistence.dict import PersistentDict
 from zope.component import getService, queryAdapter
 from zope.context import ContextMethod
 
@@ -29,31 +30,26 @@
 
 from zope.app.interfaces.workflow import IProcessInstanceContainer
 from zope.app.interfaces.workflow import IProcessInstanceContainerAdaptable
-from zope.app.interfaces.workflow.stateful import IContentWorkflowsUtility
-from zope.interface import implements
+from zope.app.interfaces.workflow.stateful import IContentWorkflowsManager
+from zope.interface import implements, providedBy
 
 
-class ContentWorkflowsUtility(Persistent):
+class ContentWorkflowsManager(Persistent):
 
-    implements(IContentWorkflowsUtility, ISubscriber)
+    implements(IContentWorkflowsManager, ISubscriber)
 
-    def __init__(self):
-        super(ContentWorkflowsUtility, self).__init__()
-        # XXX: This should not be declared here and should be generated by
-        #      looking for all 'Active' Stateful Process Definition names. It
-        #      took me a while to figure this out, since the workflow will not
-        #      work otherwise. (SR)
-        self._names = ('default',) # _names should be a TypeRegistry
+    currentlySubscribed = False # Default subscription state
 
-    # ISubscriber
+    def __init__(self):
+        super(ContentWorkflowsManager, self).__init__()
+        self._registry = PersistentDict()
 
     def notify(self, event):
-        """An event occured. Perhaps register this object with the hub."""
+        """See zope.app.interfaces.event.ISubscriber"""
         obj = event.object
 
-        # XXX Do i need to removeAllProxies somewhere in here ???
-
         # check if it implements IProcessInstanceContainerAdaptable
+        # This interface ensures that the object can store process instances. 
         if not IProcessInstanceContainerAdaptable.isImplementedBy(obj):
             return
 
@@ -70,13 +66,12 @@
             # 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:
+            for pd_name in self.getProcessDefinitionNamesForObject(obj):
 
                 if pd_name in pi_container.keys():
                     continue
                 try:
                     pi = wfs.createProcessInstance(pd_name)
-                    print "CREATED PROCESSINSTANCE:", str(pi)
                 except KeyError:
                     # No registered PD with that name..
                     continue
@@ -84,13 +79,9 @@
 
     notify = ContextMethod(notify)
 
-    # IContentWorkflowsUtility
-
-    # control
-
-    currentlySubscribed = False # Default subscription state
 
     def subscribe(self):
+        """See interfaces.workflows.stateful.IContentWorkflowsManager"""
         if self.currentlySubscribed:
             raise ValueError, "already subscribed; please unsubscribe first"
         channel = self._getChannel(None)
@@ -99,6 +90,7 @@
     subscribe = ContextMethod(subscribe)
 
     def unsubscribe(self):
+        """See interfaces.workflows.stateful.IContentWorkflowsManager"""
         if not self.currentlySubscribed:
             raise ValueError, "not subscribed; please subscribe first"
         channel = self._getChannel(None)
@@ -107,6 +99,7 @@
     unsubscribe = ContextMethod(unsubscribe)
 
     def isSubscribed(self):
+        """See interfaces.workflows.stateful.IContentWorkflowsManager"""
         return self.currentlySubscribed
 
     def _getChannel(self, channel):
@@ -115,13 +108,35 @@
         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)
-
+    def getProcessDefinitionNamesForObject(self, object):
+        """See interfaces.workflows.stateful.IContentWorkflowsManager"""
+        names = ()
+        for iface in providedBy(object):
+            names += self.getProcessNamesForInterface(iface)
+        return names
+
+    def register(self, iface, name):
+        """See zope.app.interfaces.workflows.stateful.IContentProcessRegistry"""
+        if iface not in self._registry.keys():
+            self._registry[iface] = ()
+        self._registry[iface] += (name,)
+        
+    def unregister(self, iface, name):
+        """See zope.app.interfaces.workflows.stateful.IContentProcessRegistry"""
+        names = list(self._registry[iface])
+        names = filter(lambda n: n != name, names)
+        if not names:
+            del self._registry[iface]
+        else:
+            self._registry[iface] = tuple(names)
+
+    def getProcessNamesForInterface(self, iface):
+        """See zope.app.interfaces.workflows.stateful.IContentProcessRegistry"""
+        return self._registry.get(iface, ())
+
+    def getInterfacesForProcessName(self, name):
+        ifaces = []
+        for iface, names in self._registry.items():
+            if name in names:
+                ifaces.append(iface)
+        return tuple(ifaces)