[Zope3-checkins] SVN: Zope3/branches/jack-e_interfacebased_workflow/ very basic implementation of jim's idea of implementing state-based workflow with interfaces.

Ulrich Eck ueck at net-labs.de
Sat Sep 18 17:54:14 EDT 2004


Log message for revision 27636:
  very basic implementation of jim's idea of implementing state-based workflow with interfaces.
  everyone interested in workflow is invited to join this effort and try/discuss this way of
  implementing state machines.
  
  
  


Changed:
  A   Zope3/branches/jack-e_interfacebased_workflow/package-includes/wfproto-configure.zcml
  A   Zope3/branches/jack-e_interfacebased_workflow/src/wfproto/
  A   Zope3/branches/jack-e_interfacebased_workflow/src/wfproto/__init__.py
  A   Zope3/branches/jack-e_interfacebased_workflow/src/wfproto/configure.zcml
  A   Zope3/branches/jack-e_interfacebased_workflow/src/wfproto/interfaces.py
  A   Zope3/branches/jack-e_interfacebased_workflow/src/wfproto/myprocess.py
  A   Zope3/branches/jack-e_interfacebased_workflow/src/wfproto/statea.pt
  A   Zope3/branches/jack-e_interfacebased_workflow/src/wfproto/stateb.pt
  A   Zope3/branches/jack-e_interfacebased_workflow/src/wfproto/statec.pt
  A   Zope3/branches/jack-e_interfacebased_workflow/src/wfproto/userevent.py
  A   Zope3/branches/jack-e_interfacebased_workflow/src/wfproto/wfproto.pt
  U   Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/browser/definition.py
  U   Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/configure.zcml
  U   Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/definition.py
  U   Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/instance.py
  U   Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/interfaces/__init__.py
  U   Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/stateful/browser/configure.zcml
  U   Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/stateful/browser/definition.py
  U   Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/stateful/browser/filteradapter.py
  U   Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/stateful/browser/instance.py
  U   Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/stateful/configure.zcml
  U   Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/stateful/contentworkflow.py
  U   Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/stateful/definition.py
  U   Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/stateful/instance.py
  U   Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/stateful/interfaces.py


-=-
Added: Zope3/branches/jack-e_interfacebased_workflow/package-includes/wfproto-configure.zcml
===================================================================
--- Zope3/branches/jack-e_interfacebased_workflow/package-includes/wfproto-configure.zcml	2004-09-18 21:49:13 UTC (rev 27635)
+++ Zope3/branches/jack-e_interfacebased_workflow/package-includes/wfproto-configure.zcml	2004-09-18 21:54:13 UTC (rev 27636)
@@ -0,0 +1 @@
+<include package="wfproto"/>

Added: Zope3/branches/jack-e_interfacebased_workflow/src/wfproto/__init__.py
===================================================================

Added: Zope3/branches/jack-e_interfacebased_workflow/src/wfproto/configure.zcml
===================================================================
--- Zope3/branches/jack-e_interfacebased_workflow/src/wfproto/configure.zcml	2004-09-18 21:49:13 UTC (rev 27635)
+++ Zope3/branches/jack-e_interfacebased_workflow/src/wfproto/configure.zcml	2004-09-18 21:54:13 UTC (rev 27636)
@@ -0,0 +1,82 @@
+<configure
+   xmlns="http://namespaces.zope.org/zope"
+   xmlns:browser="http://namespaces.zope.org/browser"
+   i18n_domain="zope"
+   >
+
+<interface
+   interface="buddydemo.interfaces.IBuddy"
+   type="zope.app.content.interfaces.IContentType"
+   />
+
+<adapter
+   factory="zope.app.workflow.stateful.instance.StatefulPIAdapter"
+   provides="zope.app.workflow.stateful.interfaces.IStatefulPIAdapter"
+   for=".interfaces.IMyProcess"
+   />
+
+<interface
+   interface=".interfaces.IMyStateINITIAL" />
+
+<interface
+   interface=".interfaces.IMyStateA" />
+
+<interface
+   interface=".interfaces.IMyStateB" />
+
+<interface
+   interface=".interfaces.IMyStateC" />
+
+
+
+
+<subscriber
+  factory=".userevent.UserEventSubscriber"
+  for=".interfaces.IUserEvent"
+  />
+
+
+<browser:page
+  name="state.html"
+  for=".interfaces.IMyStateA"
+  template="statea.pt"
+  menu="zmi_views" title="State"
+  permission="zope.Public"
+  />
+
+<browser:page
+  name="state.html"
+  for=".interfaces.IMyStateB"
+  template="stateb.pt"
+  menu="zmi_views" title="State"
+  permission="zope.Public"
+  />
+
+<browser:page
+  name="state.html"
+  for=".interfaces.IMyStateC"
+  template="statec.pt"
+  menu="zmi_views" title="State"
+  permission="zope.Public"
+  />
+
+
+
+
+<browser:page
+  name="wfproto.html"
+  for=".interfaces.IMyProcess"
+  template="wfproto.pt"
+  menu="zmi_views" title="Process"
+  permission="zope.Public"
+  />
+
+<browser:page
+  name="submit.html"
+  for=".interfaces.IMyProcess"
+  class=".myprocess.FormSubmitView"
+  attribute="submit"
+  permission="zope.Public"
+  />
+
+</configure>

Added: Zope3/branches/jack-e_interfacebased_workflow/src/wfproto/interfaces.py
===================================================================
--- Zope3/branches/jack-e_interfacebased_workflow/src/wfproto/interfaces.py	2004-09-18 21:49:13 UTC (rev 27635)
+++ Zope3/branches/jack-e_interfacebased_workflow/src/wfproto/interfaces.py	2004-09-18 21:54:13 UTC (rev 27636)
@@ -0,0 +1,35 @@
+from zope import interface
+from zope.app.event.interfaces import IObjectEvent
+
+
+class IMyProcess(interface.Interface):
+    """ just my process. """
+
+    __processdefinition_name__ = interface.Attribute('temporary helper to find pd')
+
+
+class IMyStateINITIAL(IMyProcess):
+    """ the INITIAL state. """
+
+class IMyStateA(IMyProcess): 
+    """ the A state. """
+
+class IMyStateB(IMyProcess):
+    """ the B state. """
+
+class IMyStateC(IMyProcess):
+    """ the C state. """
+
+
+
+
+
+
+class IUserEvent(IObjectEvent):
+    """ an informal UserEvent Interface. """
+
+
+    formData = interface.Attribute('form data')
+    method   = interface.Attribute('submit method')
+
+    

Added: Zope3/branches/jack-e_interfacebased_workflow/src/wfproto/myprocess.py
===================================================================
--- Zope3/branches/jack-e_interfacebased_workflow/src/wfproto/myprocess.py	2004-09-18 21:49:13 UTC (rev 27635)
+++ Zope3/branches/jack-e_interfacebased_workflow/src/wfproto/myprocess.py	2004-09-18 21:54:13 UTC (rev 27636)
@@ -0,0 +1,18 @@
+from zope.event import notify
+
+from userevent import UserEvent
+
+
+
+class FormSubmitView:
+
+    def __init__(self, context, request):
+        self.context=context
+        self.request=request
+
+    # XXX easy way .. not final !!!
+    def submit(self, transition):
+        notify(UserEvent(self.context, transition, self.request.form))
+        
+        # XXX how do we control this ??
+        self.request.response.redirect(self.request.get('REFERER', '') or 'wfproto.html')

Added: Zope3/branches/jack-e_interfacebased_workflow/src/wfproto/statea.pt
===================================================================
--- Zope3/branches/jack-e_interfacebased_workflow/src/wfproto/statea.pt	2004-09-18 21:49:13 UTC (rev 27635)
+++ Zope3/branches/jack-e_interfacebased_workflow/src/wfproto/statea.pt	2004-09-18 21:54:13 UTC (rev 27636)
@@ -0,0 +1,10 @@
+<html metal:use-macro='context/@@standard_macros/view'
+      i18n:domain='wfproto'>
+<body>
+<div metal:fill-slot='body'>
+<h1>I'm State A Template</h1>
+<br/>
+i'm the 1st page.
+</div>
+</body>
+</html>

Added: Zope3/branches/jack-e_interfacebased_workflow/src/wfproto/stateb.pt
===================================================================
--- Zope3/branches/jack-e_interfacebased_workflow/src/wfproto/stateb.pt	2004-09-18 21:49:13 UTC (rev 27635)
+++ Zope3/branches/jack-e_interfacebased_workflow/src/wfproto/stateb.pt	2004-09-18 21:54:13 UTC (rev 27636)
@@ -0,0 +1,11 @@
+<html metal:use-macro='context/@@standard_macros/view'
+      i18n:domain='wfproto'>
+<body>
+<div metal:fill-slot='body'>
+<h1>I'm State B Template</h1>
+
+<br/>
+i'm the 2nd page.
+</div>
+</body>
+</html>
\ No newline at end of file

Added: Zope3/branches/jack-e_interfacebased_workflow/src/wfproto/statec.pt
===================================================================
--- Zope3/branches/jack-e_interfacebased_workflow/src/wfproto/statec.pt	2004-09-18 21:49:13 UTC (rev 27635)
+++ Zope3/branches/jack-e_interfacebased_workflow/src/wfproto/statec.pt	2004-09-18 21:54:13 UTC (rev 27636)
@@ -0,0 +1,10 @@
+<html metal:use-macro='context/@@standard_macros/view'
+      i18n:domain='wfproto'>
+<body>
+<div metal:fill-slot='body'>
+<h1>I'm State __C__ Template</h1>
+<br/>
+I'm the 3rd page.
+</div>
+</body>
+</html>
\ No newline at end of file

Added: Zope3/branches/jack-e_interfacebased_workflow/src/wfproto/userevent.py
===================================================================
--- Zope3/branches/jack-e_interfacebased_workflow/src/wfproto/userevent.py	2004-09-18 21:49:13 UTC (rev 27635)
+++ Zope3/branches/jack-e_interfacebased_workflow/src/wfproto/userevent.py	2004-09-18 21:54:13 UTC (rev 27636)
@@ -0,0 +1,31 @@
+from zope.interface import implements
+from zope.app import zapi
+from zope.app.event.objectevent import ObjectEvent
+
+from interfaces import IUserEvent
+from zope.app.workflow.interfaces import IProcessDefinition
+from zope.app.workflow.stateful.interfaces import IStatefulPIAdapter
+
+
+class UserEvent(ObjectEvent):
+
+    implements(IUserEvent)
+
+    def __init__(self, object, method, formData):
+        super(UserEvent, self).__init__(object)
+        self.method   = method
+        self.formData = formData
+
+
+
+
+def UserEventSubscriber(event):
+    # XXX for now we use __processdefiniton_name__
+    pd_name = getattr(event.object, '__processdefinition_name__', '')
+    pia = zapi.queryAdapter(event.object, IStatefulPIAdapter, pd_name)
+    if pia is not None:
+        #try:
+        pia.fireTransition(event.method, event)
+        #except Exception, e:
+        #    print 'invalid Transition', event.method, str(e)
+            

Added: Zope3/branches/jack-e_interfacebased_workflow/src/wfproto/wfproto.pt
===================================================================
--- Zope3/branches/jack-e_interfacebased_workflow/src/wfproto/wfproto.pt	2004-09-18 21:49:13 UTC (rev 27635)
+++ Zope3/branches/jack-e_interfacebased_workflow/src/wfproto/wfproto.pt	2004-09-18 21:54:13 UTC (rev 27636)
@@ -0,0 +1,23 @@
+<html metal:use-macro='context/@@standard_macros/view'
+      i18n:domain='wfproto'>
+<body>
+<div metal:fill-slot='body'>
+<form action='submit.html' method='POST'>
+<table>
+ <caption i18n:translate=''>Workflow Prototype Testpage</caption>
+ <tr>
+  <td i18n:translate=''>Text:</td>
+  <td><input type='text' name='text'/></td>
+ </tr>
+ <tr>
+  <td i18n:translate=''>Transition:</td>
+  <td><input type='text' name='transition'/></td>
+ </tr>
+ <tr>
+  <td colspan='2'><input type='submit' value='Submit'/></td>
+ </tr>
+</table>
+</form>
+</div>
+</body>
+</html>

Modified: Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/browser/definition.py
===================================================================
--- Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/browser/definition.py	2004-09-18 21:49:13 UTC (rev 27635)
+++ Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/browser/definition.py	2004-09-18 21:54:13 UTC (rev 27636)
@@ -37,4 +37,5 @@
         self.request.response.redirect('@@importexport.html?success=1')
 
     def exportDefinition(self):
+        return ''
         return IProcessDefinitionExportHandler(self.context).doExport()

Modified: Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/configure.zcml
===================================================================
--- Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/configure.zcml	2004-09-18 21:49:13 UTC (rev 27635)
+++ Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/configure.zcml	2004-09-18 21:54:13 UTC (rev 27636)
@@ -82,14 +82,6 @@
         />
   </content>
 
-  <adapter
-      factory="zope.app.workflow.instance.ProcessInstanceContainerAdapter"
-      provides="zope.app.workflow.interfaces.IProcessInstanceContainer"
-      for="zope.app.annotation.interfaces.IAnnotatable"
-      permission="zope.workflow.UseProcessInstances"
-      trusted="true"
-      />
-
   <include package=".stateful" />
 
   <include package=".browser" />

Modified: Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/definition.py
===================================================================
--- Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/definition.py	2004-09-18 21:49:13 UTC (rev 27635)
+++ Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/definition.py	2004-09-18 21:54:13 UTC (rev 27636)
@@ -29,6 +29,7 @@
 from zope.app.workflow.interfaces import IProcessDefinitionElementContainer
 from zope.app.workflow.interfaces import IProcessDefinition
 
+
 class ProcessDefinition(Persistent, Contained):
     """Abstract Process Definition class.
 
@@ -38,9 +39,6 @@
 
     name = None
 
-    def createProcessInstance(self, definition_name):
-        """See zope.app.workflow.interfaces.IProcessDefinition"""
-        return None
 
 
 class ProcessDefinitionElementContainer(Persistent, Contained):

Modified: Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/instance.py
===================================================================
--- Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/instance.py	2004-09-18 21:49:13 UTC (rev 27635)
+++ Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/instance.py	2004-09-18 21:54:13 UTC (rev 27636)
@@ -19,114 +19,39 @@
 from persistent.dict import PersistentDict
 from zope.proxy import removeAllProxies
 
+from zope.interface import providedBy
+
 from zope.app import zapi
 from zope.app.annotation.interfaces import IAnnotatable, IAnnotations
 from zope.app.container.interfaces import IContained
-from zope.app.servicenames import Utilities
-from zope.app.workflow.interfaces import IProcessInstance, IProcessDefinition
-from zope.app.workflow.interfaces import IProcessInstanceContainer
+from zope.app.servicenames import Utilities, Adapters
+from zope.app.workflow.interfaces import IPIAdapter, IProcessDefinition
 
 from zope.interface import implements
 
-from zope.app.container.contained import Contained, setitem, uncontained
 
-class ProcessInstance(Contained):
-    """Process Instance implementation.
 
-    Process instances are always added to a process instance container. This
-    container lives in an annotation of the object and is commonly stored in
-    the ZODB. Therefore a process instance should be persistent.
+class PIAdapter(object):
+    """Adapter to interpret ProcessDefinitions with ContentObjects as Context.
+
     """
-    implements(IProcessInstance)
+    implements(IPIAdapter)
 
-    def __init__(self, pd_name):
-        self._pd_name = pd_name
-        self._status = None
-
-    processDefinitionName = property(lambda self: self._pd_name)
-
-    status = property(lambda self: self._status)
-
-    ## should probably have a method "getProcessDefinition"
-
-
-def createProcessInstance(context, name):
-    """Helper function to create a process instance from a process definition
-    name."""
-    utils = zapi.getService(Utilities, context)
-    pd = utils.getUtility(IProcessDefinition, name)
-    return pd.createProcessInstance(name)
-
-
-_marker = object()
-
-WFKey = "zope.app.worfklow.ProcessInstanceContainer"
-
-class ProcessInstanceContainerAdapter(object):
-
-    implements(IProcessInstanceContainer)
-
-    __used_for__ = IAnnotatable
-
     def __init__(self, context):
         self.context = context
-        annotations = IAnnotations(context)
-        wfdata = annotations.get(WFKey)
-        if not wfdata:
-            wfdata = PersistentDict()
-            annotations[WFKey] = wfdata
-        self.wfdata = wfdata
 
-    def __getitem__(self, key):
-        "See IProcessInstanceContainer"
-        value = self.wfdata[key]
-        return value
+    def _getProcessDefinition(self):
+        # we have an Interface (ISomeState) that represents the actual
+        # state of the object and extends our IMyProcessInstance Interface.
+        # we should register the ProcessDefinition as an Adapter for IMyProcessInstance
+        #return zapi.getService(Adapters).lookup([...how to define this?...],
+        #                                        IProcessDefinition, '', None)
+        
+        # XXX but for now we just use the __processdefinition_name__ attribute on components.
+        pd_name = getattr(removeAllProxies(self.context), '__processdefinition_name__', '')
+        return zapi.getUtility(IProcessDefinition, pd_name)
+    
+    processDefinition = property(_getProcessDefinition)
 
-    def get(self, key, default=None):
-        "See IProcessInstanceContainer"
-        value = self.wfdata.get(key, _marker)
-        if value is not _marker:
-            return value
-        else:
-            return default
 
-    def __contains__(self, key):
-        "See IProcessInstanceContainer"
-        return key in self.wfdata
 
-    def values(self):
-        "See IProcessInstanceContainer"
-        return self.wfdata.values()
-
-    def keys(self):
-        "See IProcessInstanceContainer"
-        return self.wfdata.keys()
-
-    def __len__(self):
-        "See IProcessInstanceContainer"
-        return len(self.wfdata)
-
-    def items(self):
-        "See IProcessInstanceContainer"
-        return self.wfdata.items()
-
-    def __setitem__(self, key, object):
-        "See IProcessInstanceContainer"
-        # We cannot make the message the parent right away, since it is not
-        # added to any message board yet;
-        setitem(self, self.wfdata.__setitem__, key, object)
-        # Set the final parent to be the message.
-        if IContained.providedBy(object):
-            object.__parent__ = self.context
-
-    def __delitem__(self, key):
-        "See IZopeWriteContainer"
-        container = self.wfdata
-        # publish event ?
-        uncontained(container[key], self, key)
-        del container[key]
-
-    def __iter__(self):
-        '''See interface IReadContainer'''
-        return iter(self.wfdata)
-

Modified: Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/interfaces/__init__.py
===================================================================
--- Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/interfaces/__init__.py	2004-09-18 21:49:13 UTC (rev 27635)
+++ Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/interfaces/__init__.py	2004-09-18 21:54:13 UTC (rev 27636)
@@ -43,43 +43,26 @@
         """Return the ProcessDefinition Object."""
 
 
-class IProcessInstance(Interface):
-    """Workflow process instance.
 
-    Represents the instance of a process defined by a ProcessDefinition."""
+class IPIAdapter(Interface):
+    """PI Adapter that does the hard work."""
 
-    status = Attribute("The status in which the workitem is.")
+    status            = Attribute('the current status of the PI')
+    processDefinition = Attribute('the ProcessDefinition')
 
-    processDefinitionName = Attribute("The process definition Name.")
+    # specify the methods that are used !!!
 
 
 
-class IProcessInstanceContainer(IContainer):
-    """Workflow process instance container."""
 
+class IProcessInstance(Interface):
+    """Workflow process instance.
 
-class IProcessInstanceContainerAdaptable(Interface):
-    """Marker interface for components that can be adapted to a process
-    instance container."""
+    Represents the instance of a process defined by a ProcessDefinition."""
 
 
-class IProcessInstanceControl(Interface):
-    """Interface to interact with a process instance."""
 
-    def start():
-        """Start a process instance."""
 
-    def finish():
-        """Finish a process instance."""
-
-
-class IWorklistHandler(Interface):
-    """Base interface for Workflow Worklist Handler."""
-
-    def getWorkitems():
-        """Return a sequence of workitem."""
-
-
 class IProcessDefinitionImportHandler(Interface):
     """Handler for Import of ProcessDefinitions."""
 
@@ -92,6 +75,7 @@
 
         Returns a ProcessDefinition Instance."""
 
+
 class IProcessDefinitionExportHandler(Interface):
     """Handler for Export of ProcessDefinitions."""
 

Modified: Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/stateful/browser/configure.zcml
===================================================================
--- Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/stateful/browser/configure.zcml	2004-09-18 21:49:13 UTC (rev 27635)
+++ Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/stateful/browser/configure.zcml	2004-09-18 21:54:13 UTC (rev 27636)
@@ -11,6 +11,14 @@
       permission="zope.ManageServices"
       />
 
+  <editform
+      schema="zope.app.workflow.stateful.interfaces.IStatefulProcessDefinition"
+      name="edit.html"
+      menu="zmi_views"
+      label="Edit a Stateful ProcessDefinition"
+      class=".definition.StatefulProcessDefinitionEdit"
+      permission="zope.workflow.ManageProcessDefinitions" />
+
   <page
       for="zope.app.workflow.stateful.interfaces.IStatefulProcessDefinition"
       name="index.html"
@@ -18,14 +26,6 @@
       permission="zope.ManageServices"
       template="definition_index.pt" />
 
-  <editform
-      schema="zope.app.workflow.stateful.interfaces.IStatefulProcessDefinition"
-      name="edit.html"
-      template="definition_edit.pt"
-      class=".definition.RelevantDataSchemaEdit"
-      menu="zmi_views" title="Relevant Data Schema"
-      permission="zope.workflow.ManageProcessDefinitions"/>
-
   <menuItems
       for="zope.app.workflow.stateful.interfaces.IStatefulProcessDefinition"
       menu="zmi_actions">
@@ -60,14 +60,12 @@
 
 
 <!-- State -->
-  <!-- nothing to edit yet
   <editform
       schema="zope.app.workflow.stateful.interfaces.IState"
       name="edit.html"
       menu="zmi_views"
       label="Edit a State"
       permission="zope.workflow.ManageProcessDefinitions" />
-  -->
 
   <addform
       name="AddState"
@@ -135,25 +133,6 @@
       menu="zmi_views" title="Content/Process Registry"/>
 
 
-<!-- ProcessInstanceContainerAdaptable -->
-  <pages
-      for="zope.app.workflow.interfaces.IProcessInstanceContainerAdaptable"
-      permission="zope.workflow.UseProcessInstances"
-      class=".instance.ManagementView">
-
-    <page name="workflows.html" template="instance_manage.pt"
-          menu="zmi_views" title="Workflows"/>
-    <page name="fireTransition.html" attribute="fireTransition" />
-  </pages>
-
-
-  <page
-      for="zope.app.container.interfaces.IContentContainer"
-      permission="zope.View"
-      class=".content_filter.FilterList"
-      name="published_content.html"
-      attribute="published_content" />
-
 <!-- uhm ... this seems to be too generic in its definition
      and not really nice as well. -->
   <zope:adapter

Modified: Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/stateful/browser/definition.py
===================================================================
--- Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/stateful/browser/definition.py	2004-09-18 21:49:13 UTC (rev 27635)
+++ Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/stateful/browser/definition.py	2004-09-18 21:54:13 UTC (rev 27636)
@@ -30,6 +30,14 @@
 from zope.security.proxy import removeSecurityProxy
 from zope.app.form.utility import setUpWidget
 
+class StatefulProcessDefinitionEdit(object):
+    """ Custom adding for StatefulProcessDefinitions. """
+
+    def changed(self):
+        # XXX provide Adapter for this instance
+        print "REGISTER ADAPTER" 
+        
+
 class StatesContainerAdding(Adding):
     """Custom adding view for StatesContainer objects."""
     menu_id = "add_stateful_states"
@@ -60,100 +68,7 @@
         return """I'm a stateful ProcessInstance"""
 
 
-class RelevantDataSchemaEdit(EditView):
 
-    def __init__(self, context, request):
-        super(RelevantDataSchemaEdit, self).__init__(context, request)
-        self.buildPermissionWidgets()
-
-    def buildPermissionWidgets(self):
-        schema = self.context.relevantDataSchema
-        if schema is not None:
-            for name, field in getFields(schema).items():
-
-                if self.context.schemaPermissions.has_key(name):
-                    get_perm, set_perm = self.context.schemaPermissions[name]
-                    try:
-                        get_perm_id = get_perm.id
-                    except:
-                        get_perm_id = None
-                    try:
-                        set_perm_id = set_perm.id
-                    except:
-                        set_perm_id = None
-                else:
-                    get_perm_id, set_perm_id = None, None
-
-                # Create the Accessor Permission Widget for this field
-                permField = Choice(
-                    __name__=name+'_get_perm',
-                    title=u"Accessor Permission",
-                    vocabulary="Permission Ids",
-                    default=CheckerPublic,
-                    required=False)
-                setUpWidget(self, name + '_get_perm', permField, IInputWidget, 
-                            value=get_perm_id)
-
-                # Create the Mutator Permission Widget for this field
-                permField = Choice(
-                    __name__=name+'_set_perm',
-                    title=u"Mutator Permission",
-                    default=CheckerPublic,
-                    vocabulary="Permission Ids",
-                    required=False)
-                setUpWidget(self, name+'_set_perm', permField, IInputWidget, 
-                            value=set_perm_id)
-
-    def update(self):
-        status = ''
-
-        if Update in self.request:
-            status = super(RelevantDataSchemaEdit, self).update()
-            self.buildPermissionWidgets()
-        elif 'CHANGE' in self.request:
-            schema = self.context.relevantDataSchema
-            perms = removeSecurityProxy(self.context.schemaPermissions)
-            for name, field in getFields(schema).items():
-                
-                getPermWidget = getattr(self, name+'_get_perm_widget')
-                setPermWidget = getattr(self, name+'_set_perm_widget')
-                
-                # get the selected permission id from the from request
-                get_perm_id = getPermWidget.getInputValue()
-                set_perm_id = setPermWidget.getInputValue()
-
-                # get the right permission from the given id
-                get_perm = zapi.getUtility(IPermission, get_perm_id)
-                set_perm = zapi.getUtility(IPermission, set_perm_id)
-                
-                # set the permission back to the instance
-                perms[name] = (get_perm, set_perm)
-
-                # update widget ohterwise we see the old value
-                getPermWidget.setRenderedValue(get_perm_id)
-                setPermWidget.setRenderedValue(set_perm_id)
-                
-                
-                
-            status = 'Fields permissions mapping updated.'
-
-        return status
-
-    def getPermissionWidgets(self):
-        schema = self.context.relevantDataSchema
-        if schema is None:
-            return None
-        info = []
-        for name, field in getFields(schema).items():
-            field = removeSecurityProxy(field)
-            info.append(
-                {'fieldName': name,
-                 'fieldTitle': field.title,
-                 'getter': getattr(self, name+'_get_perm_widget'),
-                 'setter': getattr(self, name+'_set_perm_widget')} )
-        return info
-
-
 class AddState(BrowserView):
 
     def action(self, id):

Modified: Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/stateful/browser/filteradapter.py
===================================================================
--- Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/stateful/browser/filteradapter.py	2004-09-18 21:49:13 UTC (rev 27635)
+++ Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/stateful/browser/filteradapter.py	2004-09-18 21:54:13 UTC (rev 27636)
@@ -16,14 +16,10 @@
 $Id$
 """
 from zope.interface import implements
-from zope.app.workflow.interfaces import IProcessInstanceContainerAdaptable
-from zope.app.workflow.interfaces import IProcessInstanceContainer
-
 from interfaces import IContentFilterAdapter
 
 class FilterAdapter(object):
     
-    __used_for__ = IProcessInstanceContainerAdaptable
     implements(IContentFilterAdapter)
 
     def __init__(self, context):
@@ -41,6 +37,7 @@
 
     def filterObjectByState(self, object, state, workflow='default'):
         """See IContentFilterAdapter"""
+        # XXX
         adapter = IProcessInstanceContainer(object, None)
         if not adapter:
             return False

Modified: Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/stateful/browser/instance.py
===================================================================
--- Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/stateful/browser/instance.py	2004-09-18 21:49:13 UTC (rev 27635)
+++ Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/stateful/browser/instance.py	2004-09-18 21:54:13 UTC (rev 27636)
@@ -29,12 +29,9 @@
 from zope.app.servicenames import Utilities
 
 from zope.app.workflow.interfaces import IProcessDefinition
-from zope.app.workflow.interfaces import IProcessInstanceContainer
-from zope.app.workflow.interfaces import IProcessInstanceContainerAdaptable
 
 class ManagementView(BrowserView):
 
-    __used_for__ = IProcessInstanceContainerAdaptable
 
     def __init__(self, context, request):
         super(ManagementView, self).__init__(context, request)

Modified: Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/stateful/configure.zcml
===================================================================
--- Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/stateful/configure.zcml	2004-09-18 21:49:13 UTC (rev 27635)
+++ Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/stateful/configure.zcml	2004-09-18 21:54:13 UTC (rev 27636)
@@ -91,8 +91,9 @@
       />
 </content>
 
-<!-- ContentWorkflowsManager -->
 
+
+<!-- ContentWorkflowsManager -->
 <content 
     class=".contentworkflow.ContentWorkflowsManager">
   <factory
@@ -113,14 +114,14 @@
     />
 </content>
 
-<class class=".instance.StatefulProcessInstance">
-  <require
-    permission="zope.workflow.UseProcessInstances"
-    interface=".interfaces.IStatefulProcessInstance"
-    />  
-</class>
+<subscriber
+  factory=".contentworkflow.NewObjectStatefulProcessInitializer"
+  for="zope.app.event.interfaces.IObjectCreatedEvent"/>
 
+
+
 <!-- Stateful workflow import/Export -->
+<!--
 <adapter
    for=".interfaces.IStatefulProcessDefinition"
    provides="zope.app.workflow.interfaces.IProcessDefinitionExportHandler"
@@ -132,18 +133,9 @@
    provides="zope.app.workflow.interfaces.IProcessDefinitionImportHandler"
    factory=".xmlimportexport.XMLImportHandler"
    />
+ -->
 
 
-<subscriber
-   for="..interfaces.IProcessInstanceContainerAdaptable
-        zope.app.event.objectevent.IObjectCreatedEvent"
-   factory=".contentworkflow.NewObjectProcessInstanceCreator"
-   >
-
-   Cause workflow instances to be added to content objects when they
-   are created.
-</subscriber>
-
 <!-- Test Object for testing Stateful Workflows -->
 <!--include file="testobject.zcml"/-->
 

Modified: Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/stateful/contentworkflow.py
===================================================================
--- Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/stateful/contentworkflow.py	2004-09-18 21:49:13 UTC (rev 27635)
+++ Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/stateful/contentworkflow.py	2004-09-18 21:54:13 UTC (rev 27636)
@@ -24,19 +24,17 @@
 from zope.app.event.interfaces import IObjectCreatedEvent
 from zope.app.servicenames import Utilities
 
-from zope.app.workflow.interfaces import IProcessInstanceContainer
-from zope.app.workflow.interfaces import IProcessInstanceContainerAdaptable
 from zope.app.workflow.stateful.interfaces import IContentWorkflowsManager
-from zope.app.workflow.instance import createProcessInstance
+from zope.app.workflow.stateful.instance import initializeStatefulProcessFor
 from zope.interface import implements, providedBy
 from zope.app.container.contained import Contained
 
 
-def NewObjectProcessInstanceCreator(obj, event):
-    #  used for: IProcessInstanceContainerAdaptable, IObjectCreatedEvent
+def NewObjectStatefulProcessInitializer(event):
+    # used for IContentType?, IObjectCreatedEvent
 
-    pi_container = IProcessInstanceContainer(obj)
-
+    obj = event.object
+    
     for (ignored, cwf) in zapi.getUtilitiesFor(IContentWorkflowsManager):
         # here we will lookup the configured processdefinitions
         # for the newly created compoent. For every pd_name
@@ -47,14 +45,14 @@
 
         for pd_name in cwf.getProcessDefinitionNamesForObject(obj):
 
-            if pd_name in pi_container.keys():
-                continue
-            try:
-                pi = createProcessInstance(cwf, pd_name)
-            except KeyError:
-                # No registered PD with that name..
-                continue
-            pi_container[pd_name] = pi
+            print "initializing content with: ", pd_name
+            # XXX try/except needed here
+            initializeStatefulProcessFor(obj, pd_name)
+
+            # XXX for now we cannot create more than one instance
+            # due to using a single string-attribute for storing
+            # the processdefinition-name in the content-component.
+            break
         
 
 class ContentWorkflowsManager(Persistent, Contained):

Modified: Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/stateful/definition.py
===================================================================
--- Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/stateful/definition.py	2004-09-18 21:49:13 UTC (rev 27635)
+++ Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/stateful/definition.py	2004-09-18 21:54:13 UTC (rev 27636)
@@ -29,23 +29,32 @@
 from zope.app.workflow.definition import ProcessDefinition
 from zope.app.workflow.definition import ProcessDefinitionElementContainer
 from zope.app.workflow.stateful.interfaces import IStatefulProcessDefinition
-from zope.app.workflow.stateful.interfaces import IState, ITransition, INITIAL
+from zope.app.workflow.stateful.interfaces import IState, IStateContained
+from zope.app.workflow.stateful.interfaces import ITransition, ITransitionContained, INITIAL
 from zope.app.workflow.stateful.interfaces import IStatefulStatesContainer
 from zope.app.workflow.stateful.interfaces import IStatefulTransitionsContainer
 from zope.app.workflow.stateful.interfaces import MANUAL
-from zope.app.workflow.stateful.instance import StatefulProcessInstance
 
 
 class State(Persistent, Contained):
     """State."""
-    implements(IState)
+    implements(IState,IStateContained)
 
+    # see IState
+    targetInterface = None
 
+    def __init__(self, targetInterface=None):
+        self.targetInterface=targetInterface
+
+
+
 class StatesContainer(ProcessDefinitionElementContainer):
     """Container that stores States."""
     implements(IStatefulStatesContainer)
 
 
+
+
 class StateNamesVocabulary(SimpleVocabulary):
     """Vocabulary providing the names of states in a local process definition.
     """
@@ -64,10 +73,11 @@
         raise 'NoLocalProcessDefinition', 'No local process definition found.'
 
 
+
 class Transition(Persistent, Contained):
     """Transition from one state to another."""
 
-    implements(ITransition)
+    implements(ITransition, ITransitionContained)
 
     # See ITransition
     sourceState = None
@@ -91,11 +101,13 @@
         return self.__parent__.getProcessDefinition()
 
 
+
 class TransitionsContainer(ProcessDefinitionElementContainer):
     """Container that stores Transitions."""
     implements(IStatefulTransitionsContainer)
 
 
+
 class StatefulProcessDefinition(ProcessDefinition):
     """Stateful workflow process definition."""
 
@@ -103,11 +115,11 @@
 
     def __init__(self):
         super(StatefulProcessDefinition, self).__init__()
+        self.__targetInterface = None
         self.__states = StatesContainer()
         initial = State()
         self.__states[self.getInitialStateName()] = initial
         self.__transitions = TransitionsContainer()
-        self.__schema = None
         self._publishModified('transitions', self.__transitions)
         self._publishModified('states', self.__states)
         # See workflow.stateful.IStatefulProcessDefinition
@@ -121,17 +133,22 @@
             notify(event)
             modified(self)
 
-    def getRelevantDataSchema(self):
-        return self.__schema
+    def getTargetInterface(self):
+        return self.__targetInterface
 
-    def setRelevantDataSchema(self, schema):
-        self.__schema = schema
+    def setTargetInterface(self, i):
+        self.__targetInterface = i
+        
+        # XXX register an Adapter for targetInterface
+        # that provides IStatefulProcessDefinition here
 
+
+
     # See workflow.stateful.IStatefulProcessDefinition
-    relevantDataSchema = property(getRelevantDataSchema,
-                                  setRelevantDataSchema,
-                                  None,
-                                  "Schema for RelevantData.")
+    targetInterface = property(getTargetInterface,
+                               setTargetInterface,
+                               None,
+                               "Interface for this Process.")
 
     # See workflow.stateful.IStatefulProcessDefinition
     states = property(lambda self: self.__states)
@@ -179,25 +196,7 @@
         """See workflow.stateful.IStatefulProcessDefinition"""
         return self.transitions.keys()
 
-    def createProcessInstance(self, definition_name):
-        """See workflow.IProcessDefinition"""
-        pi_obj = StatefulProcessInstance(definition_name)
 
-        # TODO:
-        # Process instances need to have a place, so they can look things
-        # up.  It's not clear to me (Jim) what place they should have.
-
-        # The parent of the process instance should be the object it is
-        # created for!!! This will cause all sorts of head-aches, but at this
-        # stage we do not have the object around; it would need some API
-        # changes to do that. (SR)
-        pi_obj.__parent__ = self
-
-
-        pi_obj.initialize()
-        return pi_obj
-
-
     def __getitem__(self, key):
         "See Interface.Common.Mapping.IReadMapping"
 

Modified: Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/stateful/instance.py
===================================================================
--- Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/stateful/instance.py	2004-09-18 21:49:13 UTC (rev 27635)
+++ Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/stateful/instance.py	2004-09-18 21:54:13 UTC (rev 27636)
@@ -22,21 +22,21 @@
 from zope.event import notify
 from zope.app.workflow.interfaces import IProcessDefinition
 from zope.app.workflow.stateful.interfaces import AUTOMATIC
+from zope.app.workflow.stateful.interfaces import ITransitionEvent
 from zope.app.workflow.stateful.interfaces import IAfterTransitionEvent
 from zope.app.workflow.stateful.interfaces import IBeforeTransitionEvent
-from zope.app.workflow.stateful.interfaces import IRelevantDataChangeEvent
-from zope.app.workflow.stateful.interfaces import IStatefulProcessInstance
-from zope.app.workflow.stateful.interfaces import ITransitionEvent
-from zope.app.workflow.stateful.interfaces import IBeforeRelevantDataChangeEvent
-from zope.app.workflow.stateful.interfaces import IAfterRelevantDataChangeEvent
+from zope.app.workflow.stateful.interfaces import IStatefulPIAdapter
+
 from zope.app.servicenames import Utilities
 from zope.app.traversing.api import getParent
-from zope.app.workflow.instance import ProcessInstance
+from zope.app.workflow.instance import PIAdapter
 from zope.app.container.contained import Contained
 
 from zope.security.interfaces import Unauthorized
 from zope.interface import directlyProvides, implements
+from zope.interface import directlyProvidedBy
 from zope.proxy import removeAllProxies
+from zope.security.proxy import removeSecurityProxy
 from zope.schema import getFields
 from zope.security.management import queryInteraction
 from zope.security.checker import CheckerPublic, Checker
@@ -49,9 +49,8 @@
     """A simple implementation of the transition event."""
     implements(ITransitionEvent)
 
-    def __init__(self, object, process, transition):
-        self.object = object
-        self.process = process
+    def __init__(self, context, transition):
+        self.context = context
         self.transition = transition
 
 class BeforeTransitionEvent(TransitionEvent):
@@ -61,87 +60,11 @@
     implements(IAfterTransitionEvent)
 
 
-class RelevantDataChangeEvent(object):
-    """A simple implementation of the transition event."""
-    implements(IRelevantDataChangeEvent)
 
-    def __init__(self, process, schema, attributeName, oldValue, newValue):
-        self.process = process
-        self.schema = schema
-        self.attributeName = attributeName
-        self.oldValue = oldValue
-        self.newValue = newValue
 
-class BeforeRelevantDataChangeEvent(RelevantDataChangeEvent):
-    implements(IBeforeRelevantDataChangeEvent)
 
-class AfterRelevantDataChangeEvent(RelevantDataChangeEvent):
-    implements(IAfterRelevantDataChangeEvent)
 
 
-class RelevantData(Persistent, Contained):
-    """The relevant data object can store data that is important to the
-    workflow and fires events when this data is changed.
-
-    If you don't understand this code, don't worry, it is heavy lifting.
-    """
-
-    def __init__(self, schema=None, schemaPermissions=None):
-        super(RelevantData, self).__init__()
-        self.__schema = None
-        # Add the new attributes, if there was a schema passed in
-        if schema is not None:
-            for name, field in getFields(schema).items():
-                setattr(self, name, field.default)
-            self.__schema = schema
-            directlyProvides(self, schema)
-
-            # Build up a Checker rules and store it for later
-            self.__checker_getattr = {}
-            self.__checker_setattr = {}
-            for name in getFields(schema):
-                get_perm, set_perm = schemaPermissions.get(name, (None, None))
-                self.__checker_getattr[name] = get_perm or CheckerPublic
-                self.__checker_setattr[name] = set_perm or CheckerPublic
-
-            # Always permit our class's two public methods
-            self.__checker_getattr['getChecker'] = CheckerPublic
-            self.__checker_getattr['getSchema'] = CheckerPublic
-
-
-    def __setattr__(self, key, value):
-        # The '__schema' attribute has a sepcial function
-        if key in ('_RelevantData__schema',
-                   '_RelevantData__checker_getattr',
-                   '_RelevantData__checker_setattr',
-                   'getChecker', 'getSchema') or \
-               key.startswith('_p_'):
-            return super(RelevantData, self).__setattr__(key, value)
-
-        is_schema_field = (self.__schema is not None and 
-                           key in getFields(self.__schema).keys())
-
-        if is_schema_field:
-            process = self.__parent__ 
-            # Send an Event before RelevantData changes
-            oldvalue = getattr(self, key, None)
-            notify(BeforeRelevantDataChangeEvent(
-                process, self.__schema, key, oldvalue, value))
-
-        super(RelevantData, self).__setattr__(key, value)
-
-        if is_schema_field:
-            # Send an Event after RelevantData has changed
-            notify(AfterRelevantDataChangeEvent(
-                process, self.__schema, key, oldvalue, value))
-
-    def getChecker(self):
-        return Checker(self.__checker_getattr, self.__checker_setattr)
-
-    def getSchema(self):
-        return self.__schema
-
-
 class StateChangeInfo(object):
     """Immutable StateChangeInfo."""
 
@@ -154,112 +77,85 @@
     new_state = property(lambda self: self.__new_state)
 
 
-class StatefulProcessInstance(ProcessInstance, Persistent):
-    """Stateful Workflow ProcessInstance."""
 
-    implements(IStatefulProcessInstance)
 
-    def getData(self):
-        if self._data is None:
-            return None
-        # Always give out the data attribute as proxied object.
-        return Proxy(self._data, self._data.getChecker())
-        
-    data = property(getData) 
+class StatefulPIAdapter(PIAdapter):
+    """Stateful Workflow ProcessInstance Adapter."""
 
+    implements(IStatefulPIAdapter)
+
     def initialize(self):
-        """See zope.app.workflow.interfaces.IStatefulProcessInstance"""
-        pd = self.getProcessDefinition()
-        clean_pd = removeAllProxies(pd)
-        self._status = clean_pd.getInitialStateName()
+        """See zope.app.workflow.interface.IStatefulProcessInstance"""
+        clean_pd = removeAllProxies(self.processDefinition)
 
-        # resolve schema class
-        # This should really always return a schema
-        schema = clean_pd.getRelevantDataSchema()
-        if schema:
-            # create relevant-data
-            self._data = RelevantData(schema, clean_pd.schemaPermissions)
-        else:
-            self._data = None
-        # setup permission on data
-
         # check for Automatic Transitions
         self._checkAndFireAuto(clean_pd)
+        
 
+
     def getOutgoingTransitions(self):
         """See zope.app.workflow.interfaces.IStatefulProcessInstance"""
-        pd = self.getProcessDefinition()
-        clean_pd = removeAllProxies(pd)
+        clean_pd = removeAllProxies(self.processDefinition)
         return self._outgoingTransitions(clean_pd)
 
-    def fireTransition(self, id):
+
+    # XXX API change here !!!
+    def fireTransition(self, trans_id, event=None):
         """See zope.app.workflow.interfaces.IStatefulProcessInstance"""
-        pd = self.getProcessDefinition()
-        clean_pd = removeAllProxies(pd)
-        if not id in self._outgoingTransitions(clean_pd):
-            raise KeyError, 'Invalid Transition Id: %s' % id
-        transition = clean_pd.transitions[id]
+        
+        clean_pd = removeAllProxies(self.processDefinition)
+        if not trans_id in self._outgoingTransitions(clean_pd, event):
+            raise KeyError, 'Invalid Transition Id: %s' % trans_id
+        transition = clean_pd.transitions[trans_id]
+        
         # Get the object whose status is being changed.
-        obj = getParent(self)
+        obj = removeSecurityProxy(self.context)
 
         # Send an event before the transition occurs.
-        notify(BeforeTransitionEvent(obj, self, transition))
+        notify(BeforeTransitionEvent(obj, transition))
 
+        # XXX Jim suggests to send out ObjectStateChanging/Changed Events instead
+        # of Before/AfterTransition. Need to check the side effects (Phase2)
+        
         # change status
-        self._status = transition.destinationState
+        # XXX change self.context to implement the new interface
+        # and remove the old state's interface
 
+        oldStateIF = clean_pd.states[transition.sourceState].targetInterface
+        newStateIF = clean_pd.states[transition.destinationState].targetInterface
+
+        directlyProvides(obj, directlyProvidedBy(obj) + newStateIF - oldStateIF)
+
         # Send an event after the transition occured.
-        notify(AfterTransitionEvent(obj, self, transition))
+        notify(AfterTransitionEvent(obj, transition))
 
         # check for automatic transitions and fire them if necessary
         self._checkAndFireAuto(clean_pd)
 
-    def getProcessDefinition(self):
-        """Get the ProcessDefinition object from WorkflowService."""
-        return zapi.getUtility(IProcessDefinition, self.processDefinitionName)
 
-    def _getContext(self):
-        ctx = {}
+
+    def _getContext(self, context={}):
         # data should be readonly for condition-evaluation
-        ctx['data'] = self.data
-        ctx['principal'] = None
+        context['principal'] = None
         interaction = queryInteraction()
         if interaction is not None:
             principals = [p.principal for p in interaction.participations]
             if principals:
                 # There can be more than one principal
                 assert len(principals) == 1
-                ctx['principal'] = principals[0]
+                context['principal'] = principals[0]
 
-        # TODO This needs to be discussed:
-        # how can we know if this ProcessInstance is annotated
-        # to a Content-Object and provide secure ***READONLY***
-        # Access to it for evaluating Transition Conditions ???
+        content = removeSecurityProxy(self.context)
+        context['content'] = content
 
-        #content = self.__parent__
+        return context
 
-        # TODO: How can i make sure that nobody modifies content
-        # while the condition scripts/conditions are evaluated ????
-        # this hack only prevents from directly setting an attribute
-        # using a setter-method directly is not protected :((
-        #try:
-        #    checker = getChecker(content)
-        #    checker.set_permissions = {}
-        #except TypeError:
-        #    # got object without Security Proxy
-        #    checker = selectChecker(content)
-        #    checker.set_permissions = {}
-        #    content = Proxy(content, checker)
 
-        #ctx['content'] = content
-
-        return ctx
-
-
     def _extendContext(self, transition, ctx={}):
         ctx['state_change'] = StateChangeInfo(transition)
         return ctx
 
+
     def _evaluateCondition(self, transition, contexts):
         """Evaluate a condition in context of relevant-data."""
         if not transition.condition:
@@ -267,6 +163,7 @@
         expr = Engine.compile(transition.condition)
         return expr(Engine.getContext(contexts=contexts))
 
+
     def _evaluateScript(self, transition, contexts):
         """Evaluate a script in context of relevant-data."""
         script = transition.script
@@ -277,15 +174,20 @@
             script = sm.resolve(script)
         return script(contexts)
 
-    def _outgoingTransitions(self, clean_pd):
+
+    def _outgoingTransitions(self, clean_pd, event=None):
         ret = []
-        contexts = self._getContext()
+        contexts = self._getContext({'event':event})
 
+        # XXX
+        context = removeSecurityProxy(self.context)
+        context_spec = directlyProvidedBy(context)
+
         for name, trans in clean_pd.transitions.items():
-            if self.status == trans.sourceState:
+            if context_spec.extends(clean_pd.states[trans.sourceState].targetInterface):
                 # check permissions
                 permission = trans.permission
-                if not checkPermission(permission, self):
+                if not checkPermission(permission, context):
                     continue
 
                 ctx = self._extendContext(trans, contexts)
@@ -317,3 +219,26 @@
             if trans.triggerMode == AUTOMATIC:
                 self.fireTransition(name)
                 return
+
+
+def initializeStatefulProcessFor(obj, pd_name):
+    """provide a component and a processdefinition_name and
+       to give that component behaviour.
+    """
+    # XXX For now we just add an attribute to the component
+    # to remember which processdefinition specifies the behaviour.
+    # This solution is not final and does not support multiple
+    # processes for the same component. A smarter solution using
+    # named Adapters providing (IProcessDefinition, [name])
+    # for (ISomeStatefulProcess, ISomeContentType)
+    obj.__processdefinition_name__ = pd_name
+    
+    pd = zapi.getUtility(IProcessDefinition, pd_name)
+    clean_pd = removeAllProxies(pd)
+    
+    # XXX Jim suggests to send out ObjectStateChanging/Changed Events here (Phase2)
+    
+    # XXX Set Initial Interface to self.context here !!!
+    directlyProvides(obj, pd.states[pd.getInitialStateName()].targetInterface)
+
+    IStatefulPIAdapter(obj).initialize()

Modified: Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/stateful/interfaces.py
===================================================================
--- Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/stateful/interfaces.py	2004-09-18 21:49:13 UTC (rev 27635)
+++ Zope3/branches/jack-e_interfacebased_workflow/src/zope/app/workflow/stateful/interfaces.py	2004-09-18 21:54:13 UTC (rev 27636)
@@ -20,9 +20,13 @@
 
 from zope.interface import Interface, Attribute
 from zope.app.i18n import ZopeMessageIDFactory as _
+from zope.app.container.interfaces import IContained, IContainer
+from zope.app.container.constraints import ContainerTypesConstraint
+from zope.app.container.constraints import ItemTypePrecondition
+
 from zope.app.workflow.interfaces import IWorkflowEvent
 from zope.app.workflow.interfaces import IProcessDefinition
-from zope.app.workflow.interfaces import IProcessInstance
+from zope.app.workflow.interfaces import IProcessInstance, IPIAdapter
 from zope.app.workflow.interfaces import IProcessDefinitionElementContainer
 
 AUTOMATIC = u'Automatic'
@@ -54,41 +58,34 @@
     objects that might change permissions when changing the status."""
 
 
-class IRelevantDataChangeEvent(IWorkflowEvent):
-    """This event is fired, when the object's data changes and the data is
-    considered 'relevant' to the workflow. The attributes of interest are
-    usually defined by a so called Relevant Data Schema."""
+class IState(Interface):
+    """Interface for state of a stateful workflow process definition."""
+    # TODO: Should at least have a title, if not a value as well
 
-    process = Attribute("""The process instance that is doing the
-                           transition. Note that this object really represents
-                           the workflow.""")
+    targetInterface = zope.schema.Choice(
+        title=_(u"State Interface"),
+        description=_(u"An Interface that is used to mark Instances "
+                      u"representing that it is in this state."),
+        vocabulary="Interfaces",
+        default=None,
+        required=False)
 
-    schema = Attribute("""The schema that defines the relevant data
-                          attributes.""")
 
-    attributeName = Attribute("""Name of the attribute that is changed.""")
+class IStatefulStatesContainer(IProcessDefinitionElementContainer):
+    """Container that stores States."""
 
-    oldValue = Attribute("""The old value of the attribute.""")
+    def __setitem__(name, object):
+        """Add a state"""
 
-    newValue = Attribute("""The new value of the attribute.""")
+    __setitem__.precondition = ItemTypePrecondition(IState)
+    
 
 
-class IBeforeRelevantDataChangeEvent(IRelevantDataChangeEvent):
-    """This event is triggered before some of the workflow-relevant data is
-    being changed."""
-
-
-class IAfterRelevantDataChangeEvent(IRelevantDataChangeEvent):
-    """This event is triggered after some of the workflow-relevant data has
-    been changed."""
-
-
-class IState(Interface):
+class IStateContained(IContained):
     """Interface for state of a stateful workflow process definition."""
-    # TODO: Should at least have a title, if not a value as well
 
-class IStatefulStatesContainer(IProcessDefinitionElementContainer):
-    """Container that stores States."""
+    __parent__ = zope.schema.Field(
+             constraint = ContainerTypesConstraint(IStatefulStatesContainer))
 
 
 
@@ -139,22 +136,33 @@
 class IStatefulTransitionsContainer(IProcessDefinitionElementContainer):
     """Container that stores Transitions."""
 
+    def __setitem__(name, object):
+        """Add a transition"""
 
+    __setitem__.precondition = ItemTypePrecondition(ITransition)
+
+
+
+class ITransitionContained(IContained):
+    """Stateful workflow transition that lives in a StatefulTansitionsContainer."""
+
+    __parent__ = zope.schema.Field(
+             constraint = ContainerTypesConstraint(IStatefulTransitionsContainer))
+
+
+
+
 class IStatefulProcessDefinition(IProcessDefinition):
     """Interface for stateful workflow process definition."""
 
-    relevantDataSchema = zope.schema.Choice(
-        title=_(u"Workflow-Relevant Data Schema"),
-        description=_(u"Specifies the schema that characterizes the workflow "
-                    u"relevant data of a process instance, found in pd.data."),
+    targetInterface = zope.schema.Choice(
+        title=_(u"Process Interface"),
+        description=_(u"Interface that represents the Process and "
+                      u"is extended by this Process's States."),
         vocabulary="Interfaces",
         default=None,
         required=False)
 
-    schemaPermissions = Attribute(u"A dictionary that maps set/get permissions"
-                                  u"on the schema's fields. Entries looks as"
-                                  u"follows: {fieldname:(set_perm, get_perm)}")
-
     states = Attribute("State objects container.")
 
     transitions = Attribute("Transition objects container.")
@@ -194,19 +202,17 @@
 
 
 
-class IStatefulProcessInstance(IProcessInstance):
-    """Workflow process instance.
+class IStatefulPIAdapter(IPIAdapter):
+    """Workflow process instance Adapter.
 
-    Represents the instance of a process defined by a
+    Handles Behaviour for a process defined by a
     StatefulProcessDefinition.
     """
 
-    data = Attribute("Relevant Data object.")
-
     def initialize():
-        """Initialize the ProcessInstance.
+        """Initialize the Process.
 
-        set Initial State and create relevant Data.
+        set Initial State.
         """
 
     def getOutgoingTransitions():
@@ -215,10 +221,11 @@
     def fireTransition(id):
         """Fire a outgoing transitions."""
 
-    def getProcessDefinition():
-        """Get the process definition for this instance."""
 
 
+
+
+
 class IContentProcessRegistry(Interface):
     """Content Type <-> Process Definitions Registry
 



More information about the Zope3-Checkins mailing list