Index: /main/waeup.sirp/trunk/src/waeup/sirp/applicants/browser.py
===================================================================
--- /main/waeup.sirp/trunk/src/waeup/sirp/applicants/browser.py	(revision 6352)
+++ /main/waeup.sirp/trunk/src/waeup/sirp/applicants/browser.py	(revision 6353)
@@ -59,5 +59,5 @@
     IApplicantsContainer, IApplicantsContainerAdd, application_types_vocab
     )
-from waeup.sirp.applicants.workflow import create_workflow, INITIALIZED, STARTED
+from waeup.sirp.applicants.workflow import INITIALIZED, STARTED
 
 results_widget = CustomWidgetFactory(
@@ -73,5 +73,5 @@
     MultiListDisplayWidget, subwidget=results_display_widget)
 
-TRANSITION_OBJECTS = create_workflow()
+#TRANSITION_OBJECTS = create_workflow()
 
 #TRANSITION_DICT = dict([
@@ -538,4 +538,5 @@
         datepicker.need() # Enable jQuery datepicker in date fields.
         super(EditApplicantFull, self).update()
+        self.wf_info = IWorkflowInfo(self.context)
         return
 
@@ -551,14 +552,11 @@
     def getTransitions(self):
         """Return a list of dicts of allowed transition ids and titles.
+
+        Each list entry provides keys ``name`` and ``title`` for
+        internal name and (human readable) title of a single
+        transition.
         """
-        allowed_transitions_ids = IWorkflowInfo(
-            self.context).getManualTransitionIds()
-        null_transition = [{'name': '', 'title':'No transition'}]
-        transitions = null_transition + [dict(
-            name=transition_object.transition_id,
-            title=transition_object.title)
-            for transition_object in TRANSITION_OBJECTS
-            if transition_object.transition_id in allowed_transitions_ids]
-        return transitions
+        allowed_transitions = self.wf_info.getManualTransitions()
+        return [dict(name=x, title=y) for x, y in allowed_transitions]
 
     @grok.action('Save')
@@ -569,5 +567,5 @@
         if form.has_key('transition') and form['transition']:
             transition_id = form['transition']
-            IWorkflowInfo(self.context).fireTransition(transition_id)
+            self.wf_info.fireTransition(transition_id)
         self.flash('Form has been saved.')
         self.context.getApplicantsRootLogger().info('Saved')
Index: /main/waeup.sirp/trunk/src/waeup/sirp/applicants/workflow.py
===================================================================
--- /main/waeup.sirp/trunk/src/waeup/sirp/applicants/workflow.py	(revision 6352)
+++ /main/waeup.sirp/trunk/src/waeup/sirp/applicants/workflow.py	(revision 6353)
@@ -3,12 +3,10 @@
 import grok
 from datetime import datetime
-from hurry.workflow.workflow import (
-    Transition, Workflow, WorkflowVersions, WorkflowInfo, WorkflowState,
-    NullCondition)
-from hurry.workflow.interfaces import (
-    IWorkflow, IWorkflowState, IWorkflowInfo, IWorkflowVersions,
-    InvalidTransitionError, IWorkflowTransitionEvent)
+from hurry.workflow.workflow import Transition, WorkflowState, NullCondition
+from hurry.workflow.interfaces import IWorkflowState, IWorkflowTransitionEvent
 from waeup.sirp.applicants.interfaces import IApplicantBaseData
-from waeup.sirp.interfaces import IObjectHistory
+from waeup.sirp.interfaces import IObjectHistory, IWAeUPWorkflowInfo
+from waeup.sirp.workflow import (
+    WAeUPWorkflow, WAeUPWorkflowInfo, NULL_TRANSITION)
 
 INITIALIZED = 'initialized'
@@ -19,14 +17,8 @@
 CREATED = 'created'
 
-NULL_TRANSITION = Transition(
-    transition_id = '',
-    title = 'No transition',
-    source = None,
-    condition = NullCondition,
-    msg = '',
-    destination = None,)
+APPLICATION_TRANSISIONS = (
+    NULL_TRANSITION,
 
-def create_workflow():
-    init_transition = Transition(
+    Transition(
         transition_id = 'init',
         title = 'Initialize application',
@@ -34,134 +26,78 @@
         condition = NullCondition,
         msg = 'application process initialized',
-        destination = INITIALIZED)
+        destination = INITIALIZED),
 
-    start_transition = Transition(
+    Transition(
         transition_id = 'start',
         title = 'Start application',
         msg = 'application process started',
         source = INITIALIZED,
-        destination = STARTED)
+        destination = STARTED),
 
-    submit_transition = Transition(
+    Transition(
         transition_id = 'submit',
         title = 'Submit application',
         msg = 'application record submitted',
         source = STARTED,
-        destination = SUBMITTED)
+        destination = SUBMITTED),
 
-    admit_transition = Transition(
+    Transition(
         transition_id = 'admit',
         title = 'Admit applicant',
         msg = 'applicant admitted',
         source = SUBMITTED,
-        destination = ADMITTED)
+        destination = ADMITTED),
 
-    refuse1_transition = Transition(
+    Transition(
         transition_id = 'refuse1',
         title = 'Refuse application',
         msg = 'application refused',
         source = SUBMITTED,
-        destination = NOT_ADMITTED)
+        destination = NOT_ADMITTED),
 
-    refuse2_transition = Transition(
+    Transition(
         transition_id = 'refuse2',
         title = 'Refuse application',
         msg = 'application refused',
         source = ADMITTED,
-        destination = NOT_ADMITTED)
+        destination = NOT_ADMITTED),
 
-    create_transition = Transition(
+    Transition(
         transition_id = 'create',
         title = 'Create student record',
         msg = 'student record created',
         source = ADMITTED,
-        destination = CREATED)
+        destination = CREATED),
 
-    reset1_transition = Transition(
+    Transition(
         transition_id = 'reset1',
         title = 'Reset application',
         msg = 'application record reset',
         source = SUBMITTED,
-        destination = STARTED)
+        destination = STARTED),
 
-    reset2_transition = Transition(
+    Transition(
         transition_id = 'reset2',
         title = 'Reset application',
         msg = 'application record reset',
         source = ADMITTED,
-        destination = STARTED)
+        destination = STARTED),
 
-    reset3_transition = Transition(
+    Transition(
         transition_id = 'reset3',
         title = 'Reset application',
         msg = 'application record reset',
         source = NOT_ADMITTED,
-        destination = STARTED)
+        destination = STARTED),
 
-    reset4_transition = Transition(
+    Transition(
         transition_id = 'reset4',
         title = 'Reset application',
         msg = 'application record reset',
         source = CREATED,
-        destination = STARTED)
+        destination = STARTED),
+    )
 
-    return [NULL_TRANSITION, init_transition, start_transition,
-            submit_transition, admit_transition, create_transition,
-            refuse1_transition, refuse2_transition, reset1_transition,
-            reset2_transition, reset3_transition, reset4_transition]
-
-
-class ApplicationWorkflow(Workflow):
-    """A hurry.workflow Workflow with more appropriate error messages.
-    """
-    grok.provides(IWorkflow)
-    def __init__(self):
-        super(Workflow, self).__init__()
-        self.refresh(create_workflow())
-
-    def getTransition(self, source, transition_id):
-        transition = self._id_transitions[transition_id]
-        if transition.source != source:
-            raise InvalidTransitionError(
-                "Transition '%s' requires '%s' as source state (is: '%s')" % (
-                    transition_id, transition.source, source))
-        return transition
-
-
-class ApplicationWorkflowNullVersions(WorkflowVersions):
-    """A workflow versions manager that does not handle versions.
-
-    Sounds odd, but the default implementation of
-    :class:`hurry.workflow.workflow.WorkflowVersions` is a base
-    implementation that raises :exc:`NotImplemented` exceptions for
-    most of the methods defined below.
-
-    If we want to register a versionless workflow, an utility
-    implementing IWorkflowVersions is looked up nevertheless by
-    WorkflowInfo and WorkflowState components so we **have** to
-    provide workflow versions, even if we do not support versioned
-    workflows.
-
-    This implementation returns empty result sets for any requests,
-    but does not raise :exc:`NotImplemented`.
-    """
-    def getVersions(self, state, id):
-        return []
-
-    def getVersionsWithAutomaticTransitions(self):
-        return []
-
-    def hasVersion(self, id, state):
-        return False
-
-    def hasVersionId(self, id):
-        return False
-
-# Register global utilities for workflows and workflow versions...
-#grok.global_utility(ApplicationWorkflow, IWorkflow, name=WORKFLOW_NAME)
-#grok.global_utility(ApplicationWorkflowNullVersions, IWorkflowVersions,
-#                    name=WORKFLOW_NAME)
-
-application_workflow = ApplicationWorkflow()
+application_workflow = WAeUPWorkflow(APPLICATION_TRANSISIONS)
 
 class ApplicationWorkflowState(WorkflowState, grok.Adapter):
@@ -174,9 +110,9 @@
     state_id = 'wf.application.id'
 
-class ApplicationWorkflowInfo(WorkflowInfo, grok.Adapter):
+class ApplicationWorkflowInfo(WAeUPWorkflowInfo, grok.Adapter):
     """Adapter to adapt Applicant objects to workflow info objects.
     """
     grok.context(IApplicantBaseData)
-    grok.provides(IWorkflowInfo)
+    grok.provides(IWAeUPWorkflowInfo)
 
     def __init__(self, context):
Index: /main/waeup.sirp/trunk/src/waeup/sirp/interfaces.py
===================================================================
--- /main/waeup.sirp/trunk/src/waeup/sirp/interfaces.py	(revision 6352)
+++ /main/waeup.sirp/trunk/src/waeup/sirp/interfaces.py	(revision 6353)
@@ -1,4 +1,5 @@
 ##
 ## interfaces.py
+from hurry.workflow.interfaces import IWorkflow, IWorkflowInfo
 from zc.sourcefactory.basic import BasicSourceFactory
 from zope import schema
@@ -430,2 +431,14 @@
         """
         pass
+
+class IWAeUPWorkflowInfo(IWorkflowInfo):
+    """A :class:`hurry.workflow.workflow.WorkflowInfo` with additional
+       methods for convenience.
+    """
+    def getManualTransitions():
+        """Get allowed manual transitions.
+
+        Get a sorted list of tuples containing the `transition_id` and
+        `title` of each allowed transition.
+        """
+        pass
Index: /main/waeup.sirp/trunk/src/waeup/sirp/workflow.py
===================================================================
--- /main/waeup.sirp/trunk/src/waeup/sirp/workflow.py	(revision 6353)
+++ /main/waeup.sirp/trunk/src/waeup/sirp/workflow.py	(revision 6353)
@@ -0,0 +1,106 @@
+##
+## workflow.py
+## Login : <uli@pu.smp.net>
+## Started on  Sat Jun 11 19:52:12 2011 Uli Fouquet
+## $Id$
+## 
+## Copyright (C) 2011 Uli Fouquet
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+## 
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+## 
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+"""Workflow components of general use.
+"""
+import grok
+from hurry.workflow.interfaces import IWorkflow, MANUAL, InvalidTransitionError
+from hurry.workflow.workflow import (
+    Transition, Workflow, WorkflowVersions, WorkflowInfo,
+    NullCondition, nullCheckPermission)
+from zope.security.interfaces import NoInteraction
+from zope.security.management import getInteraction
+from waeup.sirp.interfaces import IWAeUPWorkflowInfo
+
+#: A transition that is not a real transition. Use it when you want a
+#: transition that does not change the state of the connected object.
+NULL_TRANSITION = Transition(
+    transition_id = '',
+    title = 'No transition',
+    source = None,
+    condition = NullCondition,
+    msg = '',
+    destination = None,)
+
+class WAeUPWorkflow(Workflow):
+    """A :mod:`hurry.workflow` workflow with more appropriate error
+       messages.
+    """
+    grok.provides(IWorkflow)
+
+    def getTransition(self, source, transition_id):
+        transition = self._id_transitions[transition_id]
+        if transition.source != source:
+            raise InvalidTransitionError(
+                "Transition '%s' requires '%s' as source state (is: '%s')" % (
+                    transition_id, transition.source, source))
+        return transition
+
+
+class WorkflowNullVersions(WorkflowVersions):
+    """A workflow versions manager that does not handle versions.
+
+    Sounds odd, but the default implementation of
+    :class:`hurry.workflow.workflow.WorkflowVersions` is a base
+    implementation that raises :exc:`NotImplemented` exceptions for
+    most of the methods defined below.
+
+    If we want to register a versionless workflow, an utility
+    implementing IWorkflowVersions is looked up nevertheless by
+    WorkflowInfo and WorkflowState components so we **have** to
+    provide workflow versions, even if we do not support versioned
+    workflows.
+
+    This implementation returns empty result sets for any requests,
+    but does not raise :exc:`NotImplemented`.
+    """
+    def getVersions(self, state, id):
+        return []
+
+    def getVersionsWithAutomaticTransitions(self):
+        return []
+
+    def hasVersion(self, id, state):
+        return False
+
+    def hasVersionId(self, id):
+        return False
+
+class WAeUPWorkflowInfo(WorkflowInfo):
+    """A workflow info that provides a convenience transition getter.
+    """
+
+    grok.provides(IWAeUPWorkflowInfo)
+
+    def getManualTransitions(self):
+        """Get allowed manual transitions.
+
+        Get a sorted list of tuples containing the `transition_id` and
+        `title` of each allowed transition.
+        """
+        try:
+            checkPermission = getInteraction().checkPermission
+        except NoInteraction:
+            checkPermission = nullCheckPermission
+        return [(transition.transition_id, transition.title)
+                for transition in sorted(self._getTransitions(MANUAL))
+                if transition.condition(self, self.context) and
+                checkPermission(transition.permission, self.context)]
