[Zope-CVS] SVN: eventworkflow/ Initial import of the event subscriber based

Thomas Förster t.foerster at biologie.hu-berlin.de
Wed Oct 20 15:43:47 EDT 2004


Log message for revision 28222:
  Initial import of the event subscriber based 
  workflow prototype from IsarSprint
  

Changed:
  A   eventworkflow/
  A   eventworkflow/branches/
  A   eventworkflow/tags/
  A   eventworkflow/trunk/
  A   eventworkflow/trunk/README.txt
  A   eventworkflow/trunk/__init__.py
  A   eventworkflow/trunk/doc/
  A   eventworkflow/trunk/doc/mappings.txt
  A   eventworkflow/trunk/doc/problems.txt
  A   eventworkflow/trunk/event.py
  A   eventworkflow/trunk/interfaces.py
  A   eventworkflow/trunk/publication/
  A   eventworkflow/trunk/publication/README.txt
  A   eventworkflow/trunk/publication/__init__.py
  A   eventworkflow/trunk/publication/configure.zcml
  A   eventworkflow/trunk/publication/definition.py
  A   eventworkflow/trunk/publication/interfaces.py
  A   eventworkflow/trunk/publication/simplesub.txt
  A   eventworkflow/trunk/publication/tests.py
  A   eventworkflow/trunk/review/
  A   eventworkflow/trunk/review/README.txt
  A   eventworkflow/trunk/review/__init__.py
  A   eventworkflow/trunk/review/configure.zcml
  A   eventworkflow/trunk/review/definition.py
  A   eventworkflow/trunk/review/interfaces.py
  A   eventworkflow/trunk/review/tests/
  A   eventworkflow/trunk/review/tests/__init__.py
  A   eventworkflow/trunk/review/tests/reviewWithWorkitems.txt
  A   eventworkflow/trunk/review/tests/reviewWithWorkitemsParallelReviewers.txt
  A   eventworkflow/trunk/review/tests/reviewWithWorkitemsReject.txt
  A   eventworkflow/trunk/review/tests/reviewprocess.txt
  A   eventworkflow/trunk/review/tests/setup.py
  A   eventworkflow/trunk/review/tests/test_ReviewHighlevel.py
  A   eventworkflow/trunk/review/tests/test_ReviewWithWorkitems.py
  A   eventworkflow/trunk/tests/
  A   eventworkflow/trunk/tests/__init__.py
  A   eventworkflow/trunk/tests/test_worklistUtility.py
  A   eventworkflow/trunk/worklist.py

-=-
Added: eventworkflow/trunk/README.txt
===================================================================
--- eventworkflow/trunk/README.txt	2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/README.txt	2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,9 @@
+Prototype for a subscriber based activity workflow (WfMC style)
+===============================================================
+
+This  package contains a prototype for workflow definitions, 
+that solely uses Zope's event subscriptions as the workflow "engine".
+It is meant as a proof of concept.
+
+The subpackages 'review' and 'publication' each contain a complete 
+concrete workflow.


Property changes on: eventworkflow/trunk/README.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: eventworkflow/trunk/__init__.py
===================================================================
--- eventworkflow/trunk/__init__.py	2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/__init__.py	2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,16 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+#
+# This file is necessary to make this directory a package.
+


Property changes on: eventworkflow/trunk/__init__.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: eventworkflow/trunk/doc/mappings.txt
===================================================================
--- eventworkflow/trunk/doc/mappings.txt	2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/doc/mappings.txt	2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,49 @@
+Mappings of WfMC terms -> Zope3 Event Model
+=======================================
+
+ProcessDefinition and Activity(=ActivityDefinition) map to 
+class definitions. That way its easy to instantiate them, 
+meaning that ProcessInstance and ActivityInstance map to 
+objects. Each Activity defines its own interface (mostly 
+just a marker to subscribe to).
+
+A SubProcess is a ProcessInstance that behaves like an 
+ActivityInstance in the parent process (see e.g. the reuse of the 
+review workflow within the publication workflow) Storing of the 
+results of the sub process can be done by a subscriber to 
+ProcessFinishedEvent of the sub process.
+
+Transitions are subscribers to workflow related events (process 
+started, activity finished, process finished, ...). 
+
+Splits & Joins
+--------------
+
+Since you can control the starting of activities using the full
+expressive power of Python, implementing AND, OR, XOR-Splits is
+straight forward. Just start as many activity instances as 
+needed.
+
+Joins are a bit more complicated:
+
+OR-Joins (1 of many parallel activities finished suffices to 
+start next) can be modelled using a single subscriber which is 
+subscribed to ActivityFinished events of multiple activities. 
+State has to be tracked somewhere though, if the following 
+activity should be fired once only.
+
+AND-Joins depend on the nature of the join condition
+
+a) If you just want to keep track that the all previous activities are 
+finished you can put an annotation to the follow up activity which
+is generated in an inactive state. On meeting the precondition 
+this instance is activated (i.e. generates the work items). The 
+annotation stores the state of the join. A single multiple interface 
+subscriber cares about tracking state and condition.
+
+b) The condition is about workflow data, so there is no need for the 
+annotation. State is stored implicitly in the workflow data. 
+A single subscriber is sufficient checking the precondition every 
+time one of the previous activities finishes. There is no need for 
+having a stateful follow up activity, since it is created after the
+precondition is met.


Property changes on: eventworkflow/trunk/doc/mappings.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: eventworkflow/trunk/doc/problems.txt
===================================================================
--- eventworkflow/trunk/doc/problems.txt	2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/doc/problems.txt	2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,32 @@
+Areas in subscriber based workflow I (TF) feel uneasy about
+== i.e. need more brain storming
+
+Subprocesses
+------------
+
+A nested subprocess is mapped to a process that also implements
+IActivity. This naturally fits to the adapter model.
+
+I wasn't able yet to come up with an adapter solution though.
+
+Passing data from subprocess to parent process
+----------------------------------------------
+
+At the moment the data is just copied over the parents 
+process data. No unique ids. No removal of attributes. E.g.
+there is the reviewComment data hanging around in the workflow data 
+but it is obsolete when the object under review is accepted.
+
+AND Join
+--------
+
+The AND join is implemented using annotations. That requires 
+stateful activities (inactive -> active). Maybe we could get 
+around this storing the JOIN state somewhere else. Workflow data?
+Annotations to process instance?
+
+Workflow data handling
+----------------------
+
+This is a simple dict of the process instance as of now. Depending
+on the complexity of the data that might not be sufficient.


Property changes on: eventworkflow/trunk/doc/problems.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: eventworkflow/trunk/event.py
===================================================================
--- eventworkflow/trunk/event.py	2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/event.py	2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,29 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+import zope.interface
+import eventworkflow.interfaces
+
+from zope.app.event.objectevent import ObjectEvent
+
+class ProcessStartedEvent(ObjectEvent):
+	zope.interface.implements(eventworkflow.interfaces.IProcessStartedEvent)
+
+class ProcessFinishedEvent(ObjectEvent):
+	zope.interface.implements(eventworkflow.interfaces.IProcessFinishedEvent)
+
+class ActivityFinishedEvent(ObjectEvent):
+	zope.interface.implements(eventworkflow.interfaces.IActivityFinishedEvent)
+
+class WorkitemFinishedEvent(ObjectEvent):
+	zope.interface.implements(eventworkflow.interfaces.IWorkitemFinishedEvent)


Property changes on: eventworkflow/trunk/event.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: eventworkflow/trunk/interfaces.py
===================================================================
--- eventworkflow/trunk/interfaces.py	2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/interfaces.py	2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,107 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+import zope.interface
+from zope.app.annotation.interfaces import IAttributeAnnotatable
+
+import zope.app.event.interfaces
+
+### Event Interfaces
+class IActivityFinishedEvent(zope.app.event.interfaces.IObjectEvent):
+	"""Signal a finished activity"""
+
+class IProcessStartedEvent(zope.app.event.interfaces.IObjectEvent):
+	"""Signal starting a process"""
+
+class IProcessFinishedEvent(zope.app.event.interfaces.IObjectEvent):
+	"""Signal finished process"""
+
+class IWorkitemFinishedEvent(zope.app.event.interfaces.IObjectEvent):
+	"""Signal a finished workitem"""
+	
+### WfMC type entities in a workflow
+# we're not heading for compliance yet
+class IProcess(zope.interface.Interface):
+	"""An instance of a process (definition)
+
+	An IProcessStartedEvent is generated in the constructor.
+	"""
+
+	activities = zope.interface.Attribute(
+		"list of current activities")
+
+	workflowData = zope.interface.Attribute(
+		"data associated with the process")
+	
+class IActivity(zope.interface.Interface):
+	"""An instance of a specific activity"""
+
+	processDefinition = zope.interface.Attribute(
+		"a reference to the process the activity belongs to")
+
+	def __init__(pi):
+		"""constructs new instance
+
+		pi - process instance the activity belongs to
+		"""
+		
+class IJoiningActivity(IActivity, IAttributeAnnotatable):
+	"""Activity that is activated after a join in the workflow
+
+	This is used for stateful activities, that are needed after
+	AND-joins without workflow data related preconditions, i.e.
+	all predecessors must be finished
+	"""
+	
+	state = zope.interface.Attribute(
+		"the state of the activity instance, one of waiting/active")
+	
+	def activate():
+		"""activate activity
+
+		activity instances start in a waiting state. This methods
+		propagates them to the active state and creates the
+		work items.
+		"""
+
+
+class IWorklistUtility(zope.interface.Interface):
+	"""Manage workitems in workflows"""
+	
+	def addWorkitem(item):
+		"""Add new IWorkitem"""
+	
+	def itemsFor(principalId):
+		"""Return list of all workitems for a principal
+
+		Returns empty list if no principal can be
+		retrieved for the given id. If the principal
+		belongs to groups, also the workitems assigned
+		to these groups are returned.
+		"""
+
+class IWorkitem(zope.interface.Interface):
+	"""A single workitem"""
+
+	activity = zope.interface.Attribute(
+		"activity this work item belongs to")
+
+	description = zope.schema.TextLine(
+		title = u'Description',
+		)
+	
+	principals = zope.schema.List(
+		title = u"Principals",
+		value_type = zope.schema.TextLine(),
+		)
+


Property changes on: eventworkflow/trunk/interfaces.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: eventworkflow/trunk/publication/README.txt
===================================================================
--- eventworkflow/trunk/publication/README.txt	2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/publication/README.txt	2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,2 @@
+This package constains a weird publication process for
+example reasons.


Property changes on: eventworkflow/trunk/publication/README.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: eventworkflow/trunk/publication/__init__.py
===================================================================
--- eventworkflow/trunk/publication/__init__.py	2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/publication/__init__.py	2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,13 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################


Property changes on: eventworkflow/trunk/publication/__init__.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: eventworkflow/trunk/publication/configure.zcml
===================================================================
--- eventworkflow/trunk/publication/configure.zcml	2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/publication/configure.zcml	2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,56 @@
+<configure 
+    xmlns='http://namespaces.zope.org/zope'
+    xmlns:browser='http://namespaces.zope.org/browser'
+    i18n_domain="pubwf"
+    xmlns:i18n="http://namespaces.zope.org/i18n"
+    >
+
+<!-- remove finished activities from the process -->
+<subscriber
+	factory=".definition.cleanupFinishedActivities"
+	for="workflow.interfaces.IActivityFinishedEvent"
+	/>
+
+
+<!-- TRANSITIONS -->
+
+<!-- initialize process -->
+<subscriber
+	factory=".definition.startCreateArticle"
+	for=".interfaces.IPublicationProcessInstance
+		 workflow.interfaces.IProcessStartedEvent"
+	/>
+
+<!-- normal transitions (between activities) -->
+<!-- one per activity ? -->
+<subscriber
+	factory=".definition.handleFinishedCreateArticle"
+	for=".interfaces.ICreateArticleActivity
+		 workflow.interfaces.IActivityFinishedEvent"
+	/>
+
+<subscriber
+	factory=".definition.handleFinishedReviewArticle"
+	for=".interfaces.IReviewArticleActivity
+		 .workflow.interfaces.IActivityFinishedEvent"
+	/>
+
+<!-- going for a press release, these two subscriptions comprise a single join -->
+<subscriber
+	factory=".workflow.handlePublications"
+	for=".interfaces.IPublishOnlineActivity
+		 .workflow.interfaces.IActivityFinishedEvent"
+	/>
+
+<subscriber
+	factory=".workflow.handlePublications"
+	for=".interfaces.IPublishDeadTreeActivity
+		 .workflow.interfaces.IActivityFinishedEvent"
+	/>
+
+
+
+
+
+
+</configure>


Property changes on: eventworkflow/trunk/publication/configure.zcml
___________________________________________________________________
Name: svn:eol-style
   + native

Added: eventworkflow/trunk/publication/definition.py
===================================================================
--- eventworkflow/trunk/publication/definition.py	2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/publication/definition.py	2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,168 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+
+# This process definition (re)uses a review subprocess defined
+# in eventworkflow.review
+
+import zope.interface
+import zope.event
+import zope.app.zapi
+import eventworkflow.event
+import interfaces
+
+from eventworkflow.review.definition import ReviewProcess
+from eventworkflow.interfaces import IActivity
+
+from zope.app.annotation.interfaces import IAnnotations, IAttributeAnnotatable
+
+class PublicationWorkflow:
+    zope.interface.implements(interfaces.IPublicationProcess)
+	
+    def __init__(self):
+		self.activities = []
+		self.workflowData = {}
+		zope.event.notify(eventworkflow.event.ProcessStartedEvent(self))
+
+# the activities
+class BaseActivity:
+	def __init__(self, pi):
+		self.processInstance = pi
+		
+class CreateArticleActivity(BaseActivity):
+	zope.interface.implements(interfaces.ICreateArticleActivity)
+	
+class PublishOnlineActivity(BaseActivity):
+	zope.interface.implements(interfaces.IPublishOnlineActivity)
+
+class PublishDeadTreeActivity(BaseActivity):
+	zope.interface.implements(interfaces.IPublishDeadTreeActivity)
+
+class DoPressReleaseActivity:
+	zope.interface.implements(interfaces.IDoPressReleaseActivity)
+
+	def __init__(self, pi):
+		self.processInstance = pi
+		self.state = 'waiting'
+
+	def activate(self):
+		self.state = 'active'
+		#XXXcreate work items
+
+
+# the review sub process
+
+#XXX I wonder if this could also be implemented using an adapter
+# from IReviewProcess to IActivity
+
+class ReviewSubProcess(ReviewProcess):
+	zope.interface.implements(IActivity,
+							  ReviewProcess.__provides__)
+
+	def __init__(self, pi):
+		self.processInstance = pi
+		ReviewProcess.__init__(self)
+
+
+# 2 more generic handlers
+
+def cleanupFinishedActivities(event):
+	"""Remove finished activities from process"""	
+	process = event.object.processInstance
+	process.activities.remove(event.object)
+
+def handleFinishedSubprocess(event):
+	"""What happens with subprocess data
+
+	This handler writes the subflow data to the parents
+	workflow data (dict update for now)
+	"""
+	pi = event.object
+	parent = pi.processInstance
+
+	if parent is None: # not a sub process
+		return
+	
+	data = pi.workflowData
+	parent.workflowData.update(data)
+
+	zope.event.notify(eventworkflow.event.ActivityFinishedEvent(pi))
+	
+def startCreateArticle(pi, event):
+	"""start the initial activities of the process"""
+	pi.activities.append(CreateArticleActivity(pi))
+
+def handleFinishedCreateArticle(activity, event):
+	"""Transitions from CreateArticleActivity"""
+
+	pi = activity.processInstance
+	
+	# start the review sub process
+	pi.activities.append(ReviewSubProcess(pi))
+
+def handleFinishedReviewArticle(activity, event):
+	"""Transitions from Review Article
+	"""
+	
+	pi = activity.processInstance
+	
+	data = pi.workflowData
+
+	# OR-split
+	if data.get('reviewDecision', None) == 'accept':
+		# AND-split
+		pi.activities.append(PublishOnlineActivity(pi))
+		pi.activities.append(PublishDeadTreeActivity(pi))
+
+	else:
+		pi.activities.append(CreateArticleActivity(pi))
+
+
+AnnotationKey="pubwf.activitycount"
+
+def handlePublications(activity, event):
+	"""Transitions from article publications to press release
+
+	This functions handles the transition to the
+	DoPressReleaseActivity.	It ensures that both
+	publication activities are finished before
+	activating the press release activity. (AND-Join)
+	"""
+	process = activity.processInstance
+
+	# get an IDoPressRelease from process activities, should be just 1
+	activities = [x for x in process.activities
+					 if interfaces.IDoPressReleaseActivity.providedBy(x)]
+
+	try:
+		next_activity = activities.pop()
+	except IndexError:
+		next_activity = None
+	
+	if not next_activity:
+		next_activity = DoPressReleaseActivity(activity.processInstance)
+		process.activities.append(next_activity)
+
+		# put an annotation onto activity
+		annotation = IAnnotations(next_activity)
+		annotation[AnnotationKey] = 1
+	else:
+		annotation = IAnnotations(next_activity)
+		count = annotation.get(AnnotationKey, 0)
+		count += 1
+
+		annotation[AnnotationKey] = count
+		
+		if count == 2:
+			next_activity.activate()
+			#XXX maybe remove annotation


Property changes on: eventworkflow/trunk/publication/definition.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: eventworkflow/trunk/publication/interfaces.py
===================================================================
--- eventworkflow/trunk/publication/interfaces.py	2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/publication/interfaces.py	2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,33 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+import eventworkflow.interfaces
+
+class IPublicationProcess(eventworkflow.interfaces.IProcess):
+	"""An instance of the example publication process.
+	"""
+	
+class ICreateArticleActivity(eventworkflow.interfaces.IActivity):
+	"""Marker interface for 'Create Article' activity"""
+
+class IReviewArticleActivity(eventworkflow.interfaces.IActivity):
+	"""Marker interface for 'Review Article' activity"""
+
+class IPublishOnlineActivity(eventworkflow.interfaces.IActivity):
+	"""Marker interface for 'Publish online' activity"""
+
+class IPublishDeadTreeActivity(eventworkflow.interfaces.IActivity):
+	"""Marker interface for 'Publish on paper' activity"""
+
+class IDoPressReleaseActivity(eventworkflow.interfaces.IJoiningActivity):
+	"""Marker interface for 'Leak press release' activity"""


Property changes on: eventworkflow/trunk/publication/interfaces.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: eventworkflow/trunk/publication/simplesub.txt
===================================================================
--- eventworkflow/trunk/publication/simplesub.txt	2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/publication/simplesub.txt	2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,138 @@
+Using the publication workflow
+==============================
+
+Ok, here we go
+	
+	>>> import eventworkflow.publication.definition
+	>>> pi = eventworkflow.publication.definition.PublicationWorkflow()
+
+Check the workflow for the right initialization
+
+	>>> len(pi.activities)
+	1
+	>>> a = pi.activities[0]
+	>>> eventworkflow.publication.interfaces.ICreateArticleActivity.providedBy(a)
+	True
+
+And now for the fun part, we're finished with that activity
+
+	>>> import zope.event
+	>>> zope.event.notify(eventworkflow.event.ActivityFinishedEvent(a))
+
+Lets check the workflow again. The current activity really is 
+a (sub-)process
+
+	 >>> len(pi.activities)
+	 1
+	 >>> subpi = pi.activities[0]
+	 >>> eventworkflow.review.interfaces.IReviewProcess.providedBy(subpi)
+	 True
+
+Lets drive straight through the review. We just reject this first
+try. Nothing's done right the first time. Except it is but then its 
+not worth publishing either :-)
+
+	 >>> a = subpi.activities[0] # take assignment
+	 >>> subpi.workflowData['reviewer'] = 'thomas'
+	 >>> zope.event.notify(eventworkflow.event.ActivityFinishedEvent(a))
+
+	 >>> a = subpi.activities[0] # decide work object
+	 >>> subpi.workflowData['reviewDecision'] = 'reject'
+	 >>> zope.event.notify(eventworkflow.event.ActivityFinishedEvent(a))
+
+	 >>> class FakeComment: 
+	 ...   def __init__(self, foo):
+	 ...     self.foo = foo
+
+	 >>> a = subpi.activities[0] # write comment
+	 >>> subpi.workflowData['reviewComment'] = FakeComment('You suck')
+	 >>> zope.event.notify(eventworkflow.event.ActivityFinishedEvent(a))
+
+That should bring us back to the create article activity, with
+all the comment and things available in the workflow data
+
+	>>> len(pi.activities)
+	1
+	>>> a = pi.activities[0]
+	>>> eventworkflow.publication.interfaces.ICreateArticleActivity.providedBy(a)
+	True
+
+Check out the workflow data
+
+	  >>> data = pi.workflowData
+	  >>> k = data.keys()
+	  >>> k.sort()
+	  >>> k
+	  ['reviewComment', 'reviewDecision', 'reviewer']
+	  >>> data['reviewer']
+	  'thomas'
+	  >>> data['reviewDecision']
+	  'reject'
+	  >>> data['reviewComment'].foo
+	  'You suck'
+
+OK, got this far. But you paid for another round. Here we go...
+
+	>>> zope.event.notify(eventworkflow.event.ActivityFinishedEvent(a))
+	
+	>>> subpi = pi.activities[0]
+	>>> a = subpi.activities[0] # take assignment
+	>>> subpi.workflowData['reviewer'] = 'jim'
+	>>> zope.event.notify(eventworkflow.event.ActivityFinishedEvent(a))
+
+	>>> a = subpi.activities[0] # decide work object
+	>>> subpi.workflowData['reviewDecision'] = 'accept'
+	>>> zope.event.notify(eventworkflow.event.ActivityFinishedEvent(a))
+
+That was the OR-split again, but now heavy publishing is going on
+	 
+	 >>> len(pi.activities)
+	 2
+	 >>> a,b = pi.activities
+	 >>> eventworkflow.publication.interfaces.IPublishOnlineActivity.providedBy(a)
+	 True
+	 >>> eventworkflow.publication.interfaces.IPublishDeadTreeActivity.providedBy(b)
+	 True
+
+But to be sure let's check the workflow data
+
+	>>> data = pi.workflowData
+	>>> k = data.keys()
+	>>> k.sort()
+	>>> k
+	['reviewComment', 'reviewDecision', 'reviewer']
+	>>> data['reviewer']
+	'jim'
+	>>> data['reviewDecision']
+	'accept'
+	>>> data['reviewComment'].foo
+	'You suck'
+	 
+Transitioning to the final state is more complicated, because this 
+involves an AND-join of the last two activities.
+
+	>>> zope.event.notify(eventworkflow.event.ActivityFinishedEvent(a))
+
+After finishing one, there should be the IDoPressReleaseActivity created
+but it is in the waiting state
+
+	>>> len(pi.activities)
+	2
+	>>> a,b = pi.activities
+	>>> eventworkflow.publication.interfaces.IPublishDeadTreeActivity.providedBy(a)
+	True
+	>>> eventworkflow.publication.interfaces.IDoPressReleaseActivity.providedBy(b)
+	True
+	>>> b.state
+	'waiting'
+
+#XXX check the annotation here
+
+Finishing the second parallel activity should start the press release
+	
+	>>> zope.event.notify(eventworkflow.event.ActivityFinishedEvent(a))
+	>>> len(pi.activities)
+	1
+	>>> a = pi.activities[0]
+	>>> eventworkflow.publication.interfaces.IDoPressReleaseActivity.providedBy(a)
+	True


Property changes on: eventworkflow/trunk/publication/simplesub.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: eventworkflow/trunk/publication/tests.py
===================================================================
--- eventworkflow/trunk/publication/tests.py	2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/publication/tests.py	2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,64 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+import unittest
+from zope.testing.doctest import DocFileSuite, DocTestSuite
+import eventworkflow.review.tests.setup
+
+from zope.app.tests import placelesssetup, ztapi
+from zope.app.tests.setup import setUpAnnotations
+
+import eventworkflow.interfaces
+import eventworkflow.publication.interfaces
+import eventworkflow.publication.definition
+import eventworkflow.review.interfaces
+
+def setUp(test):
+	eventworkflow.review.tests.setup.setUp(test)
+
+	ztapi.subscribe([eventworkflow.interfaces.IProcessFinishedEvent],
+   					None,
+   					eventworkflow.publication.definition.handleFinishedSubprocess)
+	
+	ztapi.subscribe([eventworkflow.publication.interfaces.IPublicationProcess,
+                     eventworkflow.interfaces.IProcessStartedEvent],
+   					None,
+   					eventworkflow.publication.definition.startCreateArticle)
+	ztapi.subscribe([eventworkflow.publication.interfaces.ICreateArticleActivity,
+                     eventworkflow.interfaces.IActivityFinishedEvent],
+   					None,
+   					eventworkflow.publication.definition.handleFinishedCreateArticle) 
+	ztapi.subscribe([eventworkflow.review.interfaces.IReviewProcess,
+                     eventworkflow.interfaces.IActivityFinishedEvent],
+   					None,
+   					eventworkflow.publication.definition.handleFinishedReviewArticle)
+	ztapi.subscribe([eventworkflow.publication.interfaces.IPublishOnlineActivity,
+                     eventworkflow.interfaces.IActivityFinishedEvent],
+   					None,
+   					eventworkflow.publication.definition.handlePublications)
+	ztapi.subscribe([eventworkflow.publication.interfaces.IPublishDeadTreeActivity,
+                     eventworkflow.interfaces.IActivityFinishedEvent],
+   					None,
+   					eventworkflow.publication.definition.handlePublications)
+	
+	setUpAnnotations()
+
+def test_suite():
+    suite = unittest.TestSuite((
+		DocFileSuite('simplesub.txt',
+					 setUp=setUp,
+					 tearDown=placelesssetup.tearDown),
+
+							   ))
+
+    return suite


Property changes on: eventworkflow/trunk/publication/tests.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: eventworkflow/trunk/review/README.txt
===================================================================
--- eventworkflow/trunk/review/README.txt	2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/review/README.txt	2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1 @@
+This package constains a process for reviewing an object.


Property changes on: eventworkflow/trunk/review/README.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: eventworkflow/trunk/review/__init__.py
===================================================================
--- eventworkflow/trunk/review/__init__.py	2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/review/__init__.py	2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,13 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################


Property changes on: eventworkflow/trunk/review/__init__.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: eventworkflow/trunk/review/configure.zcml
===================================================================
--- eventworkflow/trunk/review/configure.zcml	2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/review/configure.zcml	2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,54 @@
+<configure 
+    xmlns='http://namespaces.zope.org/zope'
+    xmlns:browser='http://namespaces.zope.org/browser'
+    i18n_domain="pubwf"
+    xmlns:i18n="http://namespaces.zope.org/i18n"
+    >
+
+<!-- remove finished activities from the process -->
+<subscriber
+	factory=".definition.cleanupFinishedActivities"
+	for="workflow.interfaces.IActivityFinishedEvent"
+	/>
+
+<!-- TRANSITIONS -->
+<!-- initialize process -->
+<subscriber
+	factory=".definition.startCreateArticle"
+	for=".interfaces.IPublicationProcessInstance
+		 workflow.interfaces.IProcessStartedEvent"
+	/>
+
+<!-- normal transitions (between activities) -->
+<!-- one per activity ? -->
+<subscriber
+	factory=".definition.handleFinishedCreateArticle"
+	for=".interfaces.ICreateArticleActivity
+		 workflow.interfaces.IActivityFinishedEvent"
+	/>
+
+<subscriber
+	factory=".definition.handleFinishedReviewArticle"
+	for=".interfaces.IReviewArticleActivity
+		 .workflow.interfaces.IActivityFinishedEvent"
+	/>
+
+<!-- going for a press release, these two subscriptions comprise a single join -->
+<subscriber
+	factory=".workflow.handlePublications"
+	for=".interfaces.IPublishOnlineActivity
+		 .workflow.interfaces.IActivityFinishedEvent"
+	/>
+
+<subscriber
+	factory=".workflow.handlePublications"
+	for=".interfaces.IPublishDeadTreeActivity
+		 .workflow.interfaces.IActivityFinishedEvent"
+	/>
+
+
+
+
+
+
+</configure>


Property changes on: eventworkflow/trunk/review/configure.zcml
___________________________________________________________________
Name: svn:eol-style
   + native

Added: eventworkflow/trunk/review/definition.py
===================================================================
--- eventworkflow/trunk/review/definition.py	2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/review/definition.py	2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,194 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+import zope.interface
+import zope.event
+import zope.app.zapi
+import eventworkflow.event
+import eventworkflow.interfaces
+import interfaces
+
+class ReviewProcess:
+    zope.interface.implements(interfaces.IReviewProcess)
+	
+    def __init__(self):
+		self.activities = []
+		self.workflowData = {}
+		zope.event.notify(eventworkflow.event.ProcessStartedEvent(self))
+
+class AcceptResponsibilityActivity:
+	zope.interface.implements(interfaces.IAcceptResponsibilityActivity)
+
+	def __init__(self, pi):
+		self.processInstance = pi
+
+		# initialize/reset workflow data
+		try:
+			del pi.workflowData['reviewer']
+		except KeyError:
+			pass
+		
+		worklist = zope.app.zapi.getUtility(
+			eventworkflow.interfaces.IWorklistUtility)
+		
+		item = AcceptReviewWI(self,
+			"Take responsibility",
+			['thomas', 'jim', 'stephan'])
+		
+		worklist.addWorkitem(item)
+
+	def checkPostCondition(self):
+		data = self.processInstance.workflowData
+		if data.has_key('reviewer'):
+			zope.event.notify(eventworkflow.event.ActivityFinishedEvent(self))
+
+class DecideDraftActivity:
+	zope.interface.implements(interfaces.IDecideDraftActivity)
+
+	def __init__(self, pi):
+		self.processInstance = pi
+
+	# initialize/reset workflow data
+		try:
+			del pi.workflowData['reviewDecision']
+		except KeyError:
+			pass
+
+		worklist = zope.app.zapi.getUtility(
+			eventworkflow.interfaces.IWorklistUtility)
+		
+		item = DecideReviewWI(self,
+			"Decide about publication of the reviewed object",
+			[pi.workflowData['reviewer']])
+		
+		worklist.addWorkitem(item)
+
+	def checkPostCondition(self):
+		data = self.processInstance.workflowData
+		if data.has_key('reviewDecision'):
+			zope.event.notify(eventworkflow.event.ActivityFinishedEvent(self))
+			
+class WriteCommentActivity:
+	zope.interface.implements(interfaces.IWriteCommentActivity)
+
+	def __init__(self, pi):
+		self.processInstance = pi
+
+		# initialize/reset workflow data
+		try:
+			del pi.workflowData['reviewComment']
+		except KeyError:
+			pass
+
+		worklist = zope.app.zapi.getUtility(
+			eventworkflow.interfaces.IWorklistUtility)
+		
+		item = WriteCommentWI(self,
+			"Write review comment",
+			[pi.workflowData['reviewer']])
+		
+		worklist.addWorkitem(item)
+
+	def checkPostCondition(self):
+		data = self.processInstance.workflowData
+		if data.has_key('reviewComment'):
+			zope.event.notify(eventworkflow.event.ActivityFinishedEvent(self))
+
+
+class Workitem:
+	"""Just a generic work item prototype
+
+	for testing
+	"""
+	zope.interface.implements(eventworkflow.interfaces.IWorkitem)
+	
+	def __init__(self, activity, description, principals):
+		self.activity = activity
+		self.description = description
+		self.principals = principals
+
+	def finish(self):
+		zope.event.notify(eventworkflow.event.WorkitemFinishedEvent(self))
+
+class AcceptReviewWI(Workitem):
+	def finish(self, reviewerid):
+		process = self.activity.processInstance
+		data = process.workflowData
+		data['reviewer'] = reviewerid
+
+		Workitem.finish(self)
+
+class DecideReviewWI(Workitem):
+	def finish(self, decision):
+		process = self.activity.processInstance
+		data = process.workflowData
+		data['reviewDecision'] = decision
+
+		Workitem.finish(self)
+
+class WriteCommentWI(Workitem):
+	def finish(self, comment):
+		process = self.activity.processInstance
+		data = process.workflowData
+		data['reviewComment'] = comment
+
+		Workitem.finish(self)
+
+
+
+#XXX These 2 handlers might be general workflow handlers
+
+def cleanupFinishedActivities(event):
+	"""Remove finished activities from process"""	
+	process = event.object.processInstance
+	process.activities.remove(event.object)
+
+def workitemFinished(event):
+	wi = event.object
+	activity = wi.activity
+
+	# remove from worklist
+	worklist = zope.app.zapi.getUtility(eventworkflow.interfaces.IWorklistUtility)
+	worklist.items.remove(wi)
+
+	# then notify the activity 
+	activity.checkPostCondition()
+
+
+
+### transition handlers (specific to this process)
+
+def processStarted(process, event):
+	"""Activate initial activities"""
+	a = AcceptResponsibilityActivity(process)
+	process.activities.append(a)
+
+def reviewerAssigned(activity, event):
+	pi = activity.processInstance
+	
+	a = DecideDraftActivity(pi)
+	pi.activities.append(a)
+
+def decisionMade(activity, event):
+	pi = activity.processInstance
+
+	if pi.workflowData.get('reviewDecision', 'reject') == 'accept':
+		zope.event.notify(eventworkflow.event.ProcessFinishedEvent(pi))
+
+	else:
+		a = WriteCommentActivity(pi)
+		pi.activities.append(a)
+
+def commentWritten(activity, event):
+	pi = activity.processInstance
+	zope.event.notify(eventworkflow.event.ProcessFinishedEvent(pi))


Property changes on: eventworkflow/trunk/review/definition.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: eventworkflow/trunk/review/interfaces.py
===================================================================
--- eventworkflow/trunk/review/interfaces.py	2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/review/interfaces.py	2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,26 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+import eventworkflow.interfaces
+
+class IReviewProcess(eventworkflow.interfaces.IProcess):
+	"""A review process"""
+
+class IAcceptResponsibilityActivity(eventworkflow.interfaces.IActivity):
+	""" Marker interface for activity"""
+
+class IDecideDraftActivity(eventworkflow.interfaces.IActivity):
+	""" Marker interface for activity"""
+
+class IWriteCommentActivity(eventworkflow.interfaces.IActivity):
+	""" Marker interface for activity"""


Property changes on: eventworkflow/trunk/review/interfaces.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: eventworkflow/trunk/review/tests/__init__.py
===================================================================
--- eventworkflow/trunk/review/tests/__init__.py	2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/review/tests/__init__.py	2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,13 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################


Property changes on: eventworkflow/trunk/review/tests/__init__.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: eventworkflow/trunk/review/tests/reviewWithWorkitems.txt
===================================================================
--- eventworkflow/trunk/review/tests/reviewWithWorkitems.txt	2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/review/tests/reviewWithWorkitems.txt	2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,94 @@
+Review process with workitems (straight accept)
+===============================================
+
+Ok, here we go
+
+	>>> import zope.event
+	>>> import eventworkflow.review.definition
+	>>> pi = eventworkflow.review.definition.ReviewProcess()
+
+Check the workflow for the right initialization
+
+	>>> len(pi.activities)
+	1
+	>>> a = pi.activities[0]
+	>>> eventworkflow.review.interfaces.IAcceptResponsibilityActivity.providedBy(a)
+	True
+
+Lets get a workitem for us
+
+	>>> from zope.app import zapi
+	>>> from eventworkflow.interfaces import IWorklistUtility
+	>>> worklist = zapi.getUtility(IWorklistUtility)
+	>>> len(worklist.itemsFor('thomas'))
+	1
+	>>> len(worklist.itemsFor('jim'))
+	1
+	>>> len(worklist.itemsFor('peter'))
+	0
+
+Damn, that is a really busy site. There are lots of processes 
+running in parallel
+
+	>>> pi2 = eventworkflow.review.definition.ReviewProcess()
+	>>> pi3 = eventworkflow.review.definition.ReviewProcess()
+
+That should put a bit of load to the reviewers
+
+	>>> len(worklist.itemsFor('thomas'))
+	3
+
+Ok, Ok. Got me. I'm to move my ass eventually 
+
+	>>> wi = worklist.itemsFor('thomas')[0]
+	>>> process = wi.activity.processInstance
+	>>> process.workflowData.has_key('reviewer')
+	False
+	>>> wi.finish('thomas')	
+
+Lets test the progress in the workflow
+
+	>>> process.workflowData['reviewer']
+	'thomas'
+	>>> len(process.activities)
+	1
+	>>> a = process.activities[0]
+	>>> eventworkflow.review.interfaces.IDecideDraftActivity.providedBy(a)
+	True
+
+Great but theres more to it, look...
+
+	>>> len(worklist.itemsFor('stephan'))
+	2
+	>>> len(worklist.itemsFor('jim'))
+	2
+
+Any volunteers? Especially since you can't complain, see
+
+	>>> len(worklist.itemsFor('thomas'))
+	3
+
+2 of them should be the same like before for the additional processes, the 
+third being the workitem to decide about the object to be reviewed
+
+	>>> wi = worklist.itemsFor('thomas')[2]
+	>>> assert wi.__class__ == eventworkflow.review.definition.DecideReviewWI
+
+I'm pretty quick (or kind of sloppy with QA ;-)), so I accept
+
+	>>> wi.finish('accept')
+
+I'm done now, equal positions for everyone 
+
+	>>> len(worklist.itemsFor('stephan'))
+	2
+	>>> len(worklist.itemsFor('jim'))
+	2
+	>>> len(worklist.itemsFor('thomas'))
+	2
+	>>> len(worklist.itemsFor('peter'))
+	0
+
+	>> process = wi.activity.processInstance
+	>> process.workflowData
+	{'reviewDecision':'accept', 'reviewer':'thomas'}


Property changes on: eventworkflow/trunk/review/tests/reviewWithWorkitems.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: eventworkflow/trunk/review/tests/reviewWithWorkitemsParallelReviewers.txt
===================================================================
--- eventworkflow/trunk/review/tests/reviewWithWorkitemsParallelReviewers.txt	2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/review/tests/reviewWithWorkitemsParallelReviewers.txt	2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,72 @@
+Review process with workitems (2 Reviewer, straight accept)
+===========================================================
+
+Ok, here we go, starting 2 review processes
+
+	>>> import zope.event
+	>>> import eventworkflow.review.definition
+	>>> pi = eventworkflow.review.definition.ReviewProcess()
+	>>> pi2 = eventworkflow.review.definition.ReviewProcess()
+
+Lets check the workitems 
+
+	>>> from zope.app import zapi
+	>>> from eventworkflow.interfaces import IWorklistUtility
+	>>> worklist = zapi.getUtility(IWorklistUtility)
+
+	>>> len(worklist.itemsFor('thomas'))
+	2
+	>>> len(worklist.itemsFor('jim'))
+	2
+	>>> len(worklist.itemsFor('peter'))
+	0
+
+Damn, that is a really busy site. There are lots of processes 
+running in parallel. After finishing the first activity all
+subsequent activities assign their workitems to a single principal
+Therefore 2 items for thomas (1 awaiting reviewer assignment + 
+1 awaiting review decision) and 1 for jim (reviewer assignment)
+
+	>>> wi = worklist.itemsFor('thomas')[0]
+	>>> wi.finish('thomas')	
+
+	>>> len(worklist.itemsFor('thomas'))
+	2
+	>>> len(worklist.itemsFor('jim'))
+	1
+
+Now its Jim's turn (both processes now awaiting review decision)
+
+	>>> wi = worklist.itemsFor('jim')[0]
+	>>> wi.finish('jim')	
+
+	>>> len(worklist.itemsFor('thomas'))
+	1
+	>>> len(worklist.itemsFor('jim'))
+	1
+
+
+For sake of simplicity both accept (jim first)
+
+	>>> wi = worklist.itemsFor('jim')[0]
+	>>> wi.finish('accept')	
+
+	>>> len(worklist.itemsFor('thomas'))
+	1
+	>>> len(worklist.itemsFor('jim'))
+	0
+
+	>>> wi = worklist.itemsFor('thomas')[0]
+	>>> wi.finish('accept')	
+
+	>>> len(worklist.itemsFor('thomas'))
+	0
+	>>> len(worklist.itemsFor('jim'))
+	0
+
+Workflow data should reflect this session
+
+	>> pi.workflowData
+	{'reviewDecision':'accept', 'reviewer':'thomas'}
+	>> pi2.workflowData
+	{'reviewDecision':'accept', 'reviewer':'jim'}


Property changes on: eventworkflow/trunk/review/tests/reviewWithWorkitemsParallelReviewers.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: eventworkflow/trunk/review/tests/reviewWithWorkitemsReject.txt
===================================================================
--- eventworkflow/trunk/review/tests/reviewWithWorkitemsReject.txt	2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/review/tests/reviewWithWorkitemsReject.txt	2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,64 @@
+Review process with workitems (rejection)
+=========================================
+
+Ok, here we go (same as in reviewWithWorkitems to the point were 
+'thomas' is to decide about the reviewed doc)
+
+	>>> import zope.event
+	>>> import eventworkflow.review.definition
+	>>> pi = eventworkflow.review.definition.ReviewProcess()
+
+	>>> from zope.app import zapi
+	>>> from eventworkflow.interfaces import IWorklistUtility
+	>>> worklist = zapi.getUtility(IWorklistUtility)
+
+	>>> len(worklist.itemsFor('thomas'))
+	1
+	>>> len(worklist.itemsFor('jim'))
+	1
+	>>> len(worklist.itemsFor('peter'))
+	0
+
+	>>> wi = worklist.itemsFor('thomas')[0]
+	>>> wi.finish('thomas')	
+
+	>>> len(worklist.itemsFor('jim'))
+	0
+	>>> len(worklist.itemsFor('thomas'))
+	1
+
+	>>> wi = worklist.itemsFor('thomas')[0]
+	>>> assert wi.__class__ == eventworkflow.review.definition.DecideReviewWI
+
+This time I'm really picky
+
+	>>> wi.finish('reject')
+
+	>>> len(worklist.itemsFor('jim'))
+	0
+	>>> len(worklist.itemsFor('thomas'))
+	1
+
+	>>> wi = worklist.itemsFor('thomas')[0]
+	>>> assert wi.__class__ == eventworkflow.review.definition.WriteCommentWI
+
+But then I'm to write a comment now
+
+	>>> class FakeComment:
+	...   def __init__(self, text):
+	...     self.text = text
+
+	>>> wi.finish(FakeComment('Your article sucks'))
+
+	>>> len(worklist.itemsFor('jim'))
+	0
+	>>> len(worklist.itemsFor('thomas'))
+	0
+
+	>> process = wi.activity.processInstance
+	>> process.workflowData['reviewDecision']
+	'reject'
+	>> process.workflowData['reviewer']
+	'thomas'
+	>> process.workflowData['reviewComment'].text
+	'Your article sucks'


Property changes on: eventworkflow/trunk/review/tests/reviewWithWorkitemsReject.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: eventworkflow/trunk/review/tests/reviewprocess.txt
===================================================================
--- eventworkflow/trunk/review/tests/reviewprocess.txt	2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/review/tests/reviewprocess.txt	2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,53 @@
+The review process (workflow)
+=============================
+
+Ok, here we go
+
+	>>> import zope.event
+	>>> import eventworkflow.review.definition
+	>>> pi = eventworkflow.review.definition.ReviewProcess()
+
+Check the workflow for the right initialization
+
+	>>> len(pi.activities)
+	1
+	>>> a = pi.activities[0]
+	>>> eventworkflow.review.interfaces.IAcceptResponsibilityActivity.providedBy(a)
+	True
+
+	>>> data = pi.workflowData
+	>>> data['reviewer'] = 'thomas'
+	>>> zope.event.notify(eventworkflow.event.ActivityFinishedEvent(a))
+
+Lets check the workflow again
+
+	 >>> len(pi.activities)
+	 1
+	 >>> a = pi.activities[0]
+	 >>> eventworkflow.review.interfaces.IDecideDraftActivity.providedBy(a)
+	 True
+
+	 >>> data = a.processInstance.workflowData
+	 >>> data['reviewDecision'] = 'reject'
+	 >>> zope.event.notify(eventworkflow.event.ActivityFinishedEvent(a))
+
+That article was real crap, but now I've to provide a comment
+
+     >>> len(pi.activities)
+     1
+	 >>> a = pi.activities[0]
+	 >>> eventworkflow.review.interfaces.IWriteCommentActivity.providedBy(a)
+	 True
+
+	 >>> class FakeComment: pass
+	 >>> data = a.processInstance.workflowData
+	 >>> data['reviewComment'] = FakeComment()
+
+The process is done, no activities left
+
+	 >>> zope.event.notify(eventworkflow.event.ActivityFinishedEvent(a))
+	 >>> len(pi.activities)
+	 0
+
+	 
+


Property changes on: eventworkflow/trunk/review/tests/reviewprocess.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: eventworkflow/trunk/review/tests/setup.py
===================================================================
--- eventworkflow/trunk/review/tests/setup.py	2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/review/tests/setup.py	2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,63 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+from zope.app.tests import placelesssetup, ztapi
+from zope.app.tests.setup import setUpAnnotations
+
+import eventworkflow.review.interfaces
+import eventworkflow.review.definition
+
+import eventworkflow.interfaces
+
+
+def setUpUtilities(test):
+	from eventworkflow.interfaces import IWorklistUtility
+	from eventworkflow.worklist import BasicWorklistUtility
+	
+	ztapi.provideUtility(IWorklistUtility, BasicWorklistUtility())
+
+
+def setUpSubscriptions(test):
+	ztapi.subscribe([eventworkflow.interfaces.IActivityFinishedEvent],
+   					None,
+   					eventworkflow.review.definition.cleanupFinishedActivities)
+
+	ztapi.subscribe([eventworkflow.interfaces.IWorkitemFinishedEvent],
+   					None,
+   					eventworkflow.review.definition.workitemFinished)
+	
+	ztapi.subscribe([eventworkflow.review.interfaces.IReviewProcess,
+		             eventworkflow.interfaces.IProcessStartedEvent],
+   					None,
+   					eventworkflow.review.definition.processStarted)
+
+	ztapi.subscribe([eventworkflow.review.interfaces.IAcceptResponsibilityActivity,
+		             eventworkflow.interfaces.IActivityFinishedEvent],
+   					None,
+   					eventworkflow.review.definition.reviewerAssigned)
+
+	ztapi.subscribe([eventworkflow.review.interfaces.IDecideDraftActivity,
+		             eventworkflow.interfaces.IActivityFinishedEvent],
+   					None,
+   					eventworkflow.review.definition.decisionMade)
+
+	ztapi.subscribe([eventworkflow.review.interfaces.IWriteCommentActivity,
+		             eventworkflow.interfaces.IActivityFinishedEvent],
+   					None,
+   					eventworkflow.review.definition.commentWritten)
+	
+def setUp(test):
+	placelesssetup.setUp(test)
+	setUpUtilities(test)
+	setUpSubscriptions(test)
+	setUpAnnotations()


Property changes on: eventworkflow/trunk/review/tests/setup.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: eventworkflow/trunk/review/tests/test_ReviewHighlevel.py
===================================================================
--- eventworkflow/trunk/review/tests/test_ReviewHighlevel.py	2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/review/tests/test_ReviewHighlevel.py	2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,22 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+import unittest
+from zope.testing.doctest import DocFileSuite, DocTestSuite
+from zope.app.tests import placelesssetup
+from setup import setUp
+
+def test_suite():
+	return DocFileSuite('reviewprocess.txt',
+					 setUp=setUp,
+					 tearDown=placelesssetup.tearDown)


Property changes on: eventworkflow/trunk/review/tests/test_ReviewHighlevel.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: eventworkflow/trunk/review/tests/test_ReviewWithWorkitems.py
===================================================================
--- eventworkflow/trunk/review/tests/test_ReviewWithWorkitems.py	2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/review/tests/test_ReviewWithWorkitems.py	2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,33 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+import unittest
+from zope.testing.doctest import DocFileSuite, DocTestSuite
+from zope.app.tests import placelesssetup
+
+from setup import setUp
+
+def test_suite():
+	return unittest.TestSuite((
+		DocFileSuite('reviewWithWorkitems.txt',
+					 setUp=setUp,
+					 tearDown=placelesssetup.tearDown),
+		DocFileSuite('reviewWithWorkitemsReject.txt',
+					 setUp=setUp,
+					 tearDown=placelesssetup.tearDown),
+		DocFileSuite('reviewWithWorkitemsParallelReviewers.txt',
+					 setUp=setUp,
+					 tearDown=placelesssetup.tearDown),
+		))
+		
+		


Property changes on: eventworkflow/trunk/review/tests/test_ReviewWithWorkitems.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: eventworkflow/trunk/tests/__init__.py
===================================================================
--- eventworkflow/trunk/tests/__init__.py	2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/tests/__init__.py	2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,13 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################


Property changes on: eventworkflow/trunk/tests/__init__.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: eventworkflow/trunk/tests/test_worklistUtility.py
===================================================================
--- eventworkflow/trunk/tests/test_worklistUtility.py	2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/tests/test_worklistUtility.py	2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,44 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+import eventworkflow.worklist
+from zope.testing.doctest import DocTestSuite
+
+def testService(test):
+	"""
+	>>> wl = eventworkflow.worklist.BasicWorklistUtility()
+	>>> wl.itemsFor('foo')
+	[]
+
+	Define a some work items
+
+	>>> class FakeWorkItem:
+	...   def __init__(self, principals=[], name=''):
+	...     self.principals = principals
+	...     self.name = name
+
+	>>> foo = FakeWorkItem(['thomas', 'peter'], 'Learn Zope 3')
+	>>> bar = FakeWorkItem(['thomas'], 'Find Zope 3 Zen')
+	>>> wl.addWorkitem(foo)
+	>>> wl.addWorkitem(bar)
+
+	>>> wl.itemsFor('foo')
+	[]
+	>>> [x.name for x in wl.itemsFor('peter')]
+	['Learn Zope 3']
+	>>> [x.name for x in wl.itemsFor('thomas')]
+	['Learn Zope 3', 'Find Zope 3 Zen']
+	"""
+
+def test_suite():
+	return DocTestSuite()


Property changes on: eventworkflow/trunk/tests/test_worklistUtility.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: eventworkflow/trunk/worklist.py
===================================================================
--- eventworkflow/trunk/worklist.py	2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/worklist.py	2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,31 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+import zope.interface
+from interfaces import IWorklistUtility
+
+class BasicWorklistUtility:
+	"""A simple worklist utility"""
+	zope.interface.implements(IWorklistUtility)
+
+	def __init__(self):
+		self.items = []
+		
+	def addWorkitem(self, item):
+		self.items.append(item)
+
+	def itemsFor(self, pid):
+		"""Return all wokitems for principal"""
+
+		#XXX groups support
+		return [x for x in self.items if pid in x.principals]


Property changes on: eventworkflow/trunk/worklist.py
___________________________________________________________________
Name: svn:eol-style
   + native



More information about the Zope-CVS mailing list