Back to index

plone3  3.1.7
Public Member Functions | Public Attributes | Static Public Attributes | Private Member Functions | Private Attributes | Static Private Attributes
DCWorkflow.DCWorkflow.DCWorkflowDefinition Class Reference
Inheritance diagram for DCWorkflow.DCWorkflow.DCWorkflowDefinition:
Inheritance graph
[legend]
Collaboration diagram for DCWorkflow.DCWorkflow.DCWorkflowDefinition:
Collaboration graph
[legend]

List of all members.

Public Member Functions

def __init__
def getCatalogVariablesFor
def listObjectActions
def listGlobalActions
def isActionSupported
def doActionFor
def isInfoSupported
def getInfoFor
def allowCreate
def notifyCreated
def notifyBefore
def notifySuccess
def notifyException
def updateRoleMappingsFor

Public Attributes

 id

Static Public Attributes

string title = 'DC Workflow Definition'
string description = ''
string state_var = 'state'
 initial_state = None
 states = None
 transitions = None
 variables = None
 worklists = None
 scripts = None
tuple permissions = ()
tuple groups = ()
 roles = None
 creation_guard = None
int manager_bypass = 0
tuple manage_options
tuple security = ClassSecurityInfo()

Private Member Functions

def _addObject
def _getStatusOf
def _getWorkflowStateOf
def _getPortalRoot
def _checkTransitionGuard
def _findAutomaticTransition
def _changeStateOf
def _executeTransition

Private Attributes

 _objects

Static Private Attributes

 __implements__ = z2IWorkflowDefinition

Detailed Description

This class is the workflow engine and the container for the
workflow definition.
UI methods are in WorkflowUIMixin.

Definition at line 60 of file DCWorkflow.py.


Constructor & Destructor Documentation

Definition at line 106 of file DCWorkflow.py.

00106 
00107     def __init__(self, id):
00108         self.id = id
00109         from States import States
00110         self._addObject(States('states'))
00111         from Transitions import Transitions
00112         self._addObject(Transitions('transitions'))
00113         from Variables import Variables
00114         self._addObject(Variables('variables'))
00115         from Worklists import Worklists
00116         self._addObject(Worklists('worklists'))
00117         from Scripts import Scripts
00118         self._addObject(Scripts('scripts'))


Member Function Documentation

def DCWorkflow.DCWorkflow.DCWorkflowDefinition._addObject (   self,
  ob 
) [private]

Definition at line 119 of file DCWorkflow.py.

00119 
00120     def _addObject(self, ob):
00121         id = ob.getId()
00122         setattr(self, id, ob)
00123         self._objects = self._objects + (
00124             {'id': id, 'meta_type': ob.meta_type},)

Here is the caller graph for this function:

def DCWorkflow.DCWorkflow.DCWorkflowDefinition._changeStateOf (   self,
  ob,
  tdef = None,
  kwargs = None 
) [private]
Changes state.  Can execute multiple transitions if there are
automatic transitions.  tdef set to None means the object
was just created.

Definition at line 421 of file DCWorkflow.py.

00421 
00422     def _changeStateOf(self, ob, tdef=None, kwargs=None):
00423         '''
00424         Changes state.  Can execute multiple transitions if there are
00425         automatic transitions.  tdef set to None means the object
00426         was just created.
00427         '''
00428         moved_exc = None
00429         while 1:
00430             try:
00431                 sdef = self._executeTransition(ob, tdef, kwargs)
00432             except ObjectMoved, moved_exc:
00433                 ob = moved_exc.getNewObject()
00434                 sdef = self._getWorkflowStateOf(ob)
00435                 # Re-raise after all transitions.
00436             if sdef is None:
00437                 break
00438             tdef = self._findAutomaticTransition(ob, sdef)
00439             if tdef is None:
00440                 # No more automatic transitions.
00441                 break
00442             # Else continue.
00443         if moved_exc is not None:
00444             # Re-raise.
00445             raise moved_exc

Here is the call graph for this function:

Here is the caller graph for this function:

def DCWorkflow.DCWorkflow.DCWorkflowDefinition._checkTransitionGuard (   self,
  t,
  ob,
  kw 
) [private]

Definition at line 403 of file DCWorkflow.py.

00403 
00404     def _checkTransitionGuard(self, t, ob, **kw):
00405         guard = t.guard
00406         if guard is None:
00407             return 1
00408         if guard.check(getSecurityManager(), self, ob, **kw):
00409             return 1
00410         return 0

Here is the caller graph for this function:

def DCWorkflow.DCWorkflow.DCWorkflowDefinition._executeTransition (   self,
  ob,
  tdef = None,
  kwargs = None 
) [private]
Private method.
Puts object in a new state.

Definition at line 446 of file DCWorkflow.py.

00446 
00447     def _executeTransition(self, ob, tdef=None, kwargs=None):
00448         '''
00449         Private method.
00450         Puts object in a new state.
00451         '''
00452         sci = None
00453         econtext = None
00454         moved_exc = None
00455 
00456         # Figure out the old and new states.
00457         old_sdef = self._getWorkflowStateOf(ob)
00458         old_state = old_sdef.getId()
00459         if tdef is None:
00460             new_state = self.initial_state
00461             former_status = {}
00462         else:
00463             new_state = tdef.new_state_id
00464             if not new_state:
00465                 # Stay in same state.
00466                 new_state = old_state
00467             former_status = self._getStatusOf(ob)
00468         new_sdef = self.states.get(new_state, None)
00469         if new_sdef is None:
00470             msg = _(u'Destination state undefined: ${state_id}',
00471                     mapping={'state_id': new_state})
00472             raise WorkflowException(msg)
00473 
00474         # Fire "before" event
00475         notify(BeforeTransitionEvent(ob, self, old_sdef, new_sdef, tdef, former_status, kwargs))
00476 
00477         # Execute the "before" script.
00478         if tdef is not None and tdef.script_name:
00479             script = self.scripts[tdef.script_name]
00480             # Pass lots of info to the script in a single parameter.
00481             sci = StateChangeInfo(
00482                 ob, self, former_status, tdef, old_sdef, new_sdef, kwargs)
00483             try:
00484                 script(sci)  # May throw an exception.
00485             except ObjectMoved, moved_exc:
00486                 ob = moved_exc.getNewObject()
00487                 # Re-raise after transition
00488 
00489         # Update variables.
00490         state_values = new_sdef.var_values
00491         if state_values is None: state_values = {}
00492         tdef_exprs = None
00493         if tdef is not None: tdef_exprs = tdef.var_exprs
00494         if tdef_exprs is None: tdef_exprs = {}
00495         status = {}
00496         for id, vdef in self.variables.items():
00497             if not vdef.for_status:
00498                 continue
00499             expr = None
00500             if state_values.has_key(id):
00501                 value = state_values[id]
00502             elif tdef_exprs.has_key(id):
00503                 expr = tdef_exprs[id]
00504             elif not vdef.update_always and former_status.has_key(id):
00505                 # Preserve former value
00506                 value = former_status[id]
00507             else:
00508                 if vdef.default_expr is not None:
00509                     expr = vdef.default_expr
00510                 else:
00511                     value = vdef.default_value
00512             if expr is not None:
00513                 # Evaluate an expression.
00514                 if econtext is None:
00515                     # Lazily create the expression context.
00516                     if sci is None:
00517                         sci = StateChangeInfo(
00518                             ob, self, former_status, tdef,
00519                             old_sdef, new_sdef, kwargs)
00520                     econtext = createExprContext(sci)
00521                 value = expr(econtext)
00522             status[id] = value
00523 
00524         # Update state.
00525         status[self.state_var] = new_state
00526         tool = aq_parent(aq_inner(self))
00527         tool.setStatusOf(self.id, ob, status)
00528 
00529         # Update role to permission assignments.
00530         self.updateRoleMappingsFor(ob)
00531 
00532         # Execute the "after" script.
00533         if tdef is not None and tdef.after_script_name:
00534             script = self.scripts[tdef.after_script_name]
00535             # Pass lots of info to the script in a single parameter.
00536             sci = StateChangeInfo(
00537                 ob, self, status, tdef, old_sdef, new_sdef, kwargs)
00538             script(sci)  # May throw an exception.
00539 
00540         # Fire "after" event
00541         notify(AfterTransitionEvent(ob, self, old_sdef, new_sdef, tdef, status, kwargs))
00542 
00543         # Return the new state object.
00544         if moved_exc is not None:
00545             # Propagate the notification that the object has moved.
00546             raise moved_exc
00547         else:
00548             return new_sdef
00549 
00550 InitializeClass(DCWorkflowDefinition)

Here is the call graph for this function:

Here is the caller graph for this function:

def DCWorkflow.DCWorkflow.DCWorkflowDefinition._findAutomaticTransition (   self,
  ob,
  sdef 
) [private]

Definition at line 411 of file DCWorkflow.py.

00411 
00412     def _findAutomaticTransition(self, ob, sdef):
00413         tdef = None
00414         for tid in sdef.transitions:
00415             t = self.transitions.get(tid, None)
00416             if t is not None and t.trigger_type == TRIGGER_AUTOMATIC:
00417                 if self._checkTransitionGuard(t, ob):
00418                     tdef = t
00419                     break
00420         return tdef

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 151 of file DCWorkflow.py.

00151 
00152     def _getPortalRoot(self):
00153         return aq_parent(aq_inner(aq_parent(aq_inner(self))))

Here is the caller graph for this function:

def DCWorkflow.DCWorkflow.DCWorkflowDefinition._getStatusOf (   self,
  ob 
) [private]

Definition at line 129 of file DCWorkflow.py.

00129 
00130     def _getStatusOf(self, ob):
00131         tool = aq_parent(aq_inner(self))
00132         status = tool.getStatusOf(self.id, ob)
00133         if status is None:
00134             return {}
00135         else:
00136             return status

Here is the caller graph for this function:

def DCWorkflow.DCWorkflow.DCWorkflowDefinition._getWorkflowStateOf (   self,
  ob,
  id_only = 0 
) [private]

Definition at line 137 of file DCWorkflow.py.

00137 
00138     def _getWorkflowStateOf(self, ob, id_only=0):
00139         tool = aq_parent(aq_inner(self))
00140         status = tool.getStatusOf(self.id, ob)
00141         if status is None:
00142             state = self.initial_state
00143         else:
00144             state = status.get(self.state_var, None)
00145             if state is None:
00146                 state = self.initial_state
00147         if id_only:
00148             return state
00149         else:
00150             return self.states.get(state, None)

Here is the caller graph for this function:

def DCWorkflow.DCWorkflow.DCWorkflowDefinition.allowCreate (   self,
  container,
  type_name 
)
Returns true if the user is allowed to create a workflow instance.

The object passed to the guard is the prospective container.

Definition at line 331 of file DCWorkflow.py.

00331 
00332     def allowCreate(self, container, type_name):
00333         """Returns true if the user is allowed to create a workflow instance.
00334 
00335         The object passed to the guard is the prospective container.
00336         """
00337         if self.creation_guard is not None:
00338             return self.creation_guard.check(
00339                 getSecurityManager(), self, container)
00340         return 1

def DCWorkflow.DCWorkflow.DCWorkflowDefinition.doActionFor (   self,
  ob,
  action,
  comment = '',
  kw 
)
Allows the user to request a workflow action.  This method
must perform its own security checks.

Definition at line 273 of file DCWorkflow.py.

00273 
00274     def doActionFor(self, ob, action, comment='', **kw):
00275         '''
00276         Allows the user to request a workflow action.  This method
00277         must perform its own security checks.
00278         '''
00279         kw['comment'] = comment
00280         sdef = self._getWorkflowStateOf(ob)
00281         if sdef is None:
00282             raise WorkflowException(_(u'Object is in an undefined state.'))
00283         if action not in sdef.transitions:
00284             raise Unauthorized(action)
00285         tdef = self.transitions.get(action, None)
00286         if tdef is None or tdef.trigger_type != TRIGGER_USER_ACTION:
00287             msg = _(u"Transition '${action_id}' is not triggered by a user "
00288                     u"action.", mapping={'action_id': action})
00289             raise WorkflowException(msg)
00290         if not self._checkTransitionGuard(tdef, ob, **kw):
00291             raise Unauthorized(action)
00292         self._changeStateOf(ob, tdef, kw)

Here is the call graph for this function:

Allows this workflow to make workflow-specific variables
available to the catalog, making it possible to implement
worklists in a simple way.
Returns a mapping containing the catalog variables
that apply to ob.

Definition at line 155 of file DCWorkflow.py.

00155 
00156     def getCatalogVariablesFor(self, ob):
00157         '''
00158         Allows this workflow to make workflow-specific variables
00159         available to the catalog, making it possible to implement
00160         worklists in a simple way.
00161         Returns a mapping containing the catalog variables
00162         that apply to ob.
00163         '''
00164         res = {}
00165         status = self._getStatusOf(ob)
00166         for id, vdef in self.variables.items():
00167             if vdef.for_catalog:
00168                 if status.has_key(id):
00169                     value = status[id]
00170 
00171                 # Not set yet.  Use a default.
00172                 elif vdef.default_expr is not None:
00173                     ec = createExprContext(StateChangeInfo(ob, self, status))
00174                     value = vdef.default_expr(ec)
00175                 else:
00176                     value = vdef.default_value
00177 
00178                 res[id] = value
00179         # Always provide the state variable.
00180         state_var = self.state_var
00181         res[state_var] = status.get(state_var, self.initial_state)
00182         return res

Here is the call graph for this function:

def DCWorkflow.DCWorkflow.DCWorkflowDefinition.getInfoFor (   self,
  ob,
  name,
  default 
)
Allows the user to request information provided by the
workflow.  This method must perform its own security checks.

Definition at line 306 of file DCWorkflow.py.

00306 
00307     def getInfoFor(self, ob, name, default):
00308         '''
00309         Allows the user to request information provided by the
00310         workflow.  This method must perform its own security checks.
00311         '''
00312         if name == self.state_var:
00313             return self._getWorkflowStateOf(ob, 1)
00314         vdef = self.variables[name]
00315         if vdef.info_guard is not None and not vdef.info_guard.check(
00316             getSecurityManager(), self, ob):
00317             return default
00318         status = self._getStatusOf(ob)
00319         if status is not None and status.has_key(name):
00320             value = status[name]
00321 
00322         # Not set yet.  Use a default.
00323         elif vdef.default_expr is not None:
00324             ec = createExprContext(StateChangeInfo(ob, self, status))
00325             value = vdef.default_expr(ec)
00326         else:
00327             value = vdef.default_value
00328 
00329         return value

Here is the call graph for this function:

def DCWorkflow.DCWorkflow.DCWorkflowDefinition.isActionSupported (   self,
  ob,
  action,
  kw 
)
Returns a true value if the given action name
is possible in the current state.

Definition at line 256 of file DCWorkflow.py.

00256 
00257     def isActionSupported(self, ob, action, **kw):
00258         '''
00259         Returns a true value if the given action name
00260         is possible in the current state.
00261         '''
00262         sdef = self._getWorkflowStateOf(ob)
00263         if sdef is None:
00264             return 0
00265         if action in sdef.transitions:
00266             tdef = self.transitions.get(action, None)
00267             if (tdef is not None and
00268                 tdef.trigger_type == TRIGGER_USER_ACTION and
00269                 self._checkTransitionGuard(tdef, ob, **kw)):
00270                 return 1
00271         return 0

Here is the call graph for this function:

Returns a true value if the given info name is supported.

Definition at line 294 of file DCWorkflow.py.

00294 
00295     def isInfoSupported(self, ob, name):
00296         '''
00297         Returns a true value if the given info name is supported.
00298         '''
00299         if name == self.state_var:
00300             return 1
00301         vdef = self.variables.get(name, None)
00302         if vdef is None:
00303             return 0
00304         return 1

Allows this workflow to
include actions to be displayed in the actions box.
Called on every request.
Returns the actions to be displayed to the user.

Definition at line 213 of file DCWorkflow.py.

00213 
00214     def listGlobalActions(self, info):
00215         '''
00216         Allows this workflow to
00217         include actions to be displayed in the actions box.
00218         Called on every request.
00219         Returns the actions to be displayed to the user.
00220         '''
00221         if not self.worklists:
00222             return None  # Optimization
00223         sm = getSecurityManager()
00224         portal = self._getPortalRoot()
00225         res = []
00226         fmt_data = None
00227         for id, qdef in self.worklists.items():
00228             if qdef.actbox_name:
00229                 guard = qdef.guard
00230                 if guard is None or guard.check(sm, self, portal):
00231                     searchres = None
00232                     var_match_keys = qdef.getVarMatchKeys()
00233                     if var_match_keys:
00234                         # Check the catalog for items in the worklist.
00235                         catalog = getToolByName(self, 'portal_catalog')
00236                         kw = {}
00237                         for k in var_match_keys:
00238                             v = qdef.getVarMatch(k)
00239                             kw[k] = [ x % info for x in v ]
00240                         searchres = catalog.searchResults(**kw)
00241                         if not searchres:
00242                             continue
00243                     if fmt_data is None:
00244                         fmt_data = TemplateDict()
00245                         fmt_data._push(info)
00246                     fmt_data._push({'count': len(searchres)})
00247                     res.append((id, {'id': id,
00248                                      'name': qdef.actbox_name % fmt_data,
00249                                      'url': qdef.actbox_url % fmt_data,
00250                                      'permissions': (),  # Predetermined.
00251                                      'category': qdef.actbox_category}))
00252                     fmt_data._pop()
00253         res.sort()
00254         return [ result[1] for result in res ]

Here is the call graph for this function:

Allows this workflow to
include actions to be displayed in the actions box.
Called only when this workflow is applicable to
info.object.
Returns the actions to be displayed to the user.

Definition at line 184 of file DCWorkflow.py.

00184 
00185     def listObjectActions(self, info):
00186         '''
00187         Allows this workflow to
00188         include actions to be displayed in the actions box.
00189         Called only when this workflow is applicable to
00190         info.object.
00191         Returns the actions to be displayed to the user.
00192         '''
00193         ob = info.object
00194         sdef = self._getWorkflowStateOf(ob)
00195         if sdef is None:
00196             return None
00197         res = []
00198         for tid in sdef.transitions:
00199             tdef = self.transitions.get(tid, None)
00200             if tdef is not None and tdef.trigger_type == TRIGGER_USER_ACTION:
00201                 if tdef.actbox_name:
00202                     if self._checkTransitionGuard(tdef, ob):
00203                         res.append((tid, {
00204                             'id': tid,
00205                             'name': tdef.actbox_name % info,
00206                             'url': tdef.actbox_url % info,
00207                             'permissions': (),  # Predetermined.
00208                             'category': tdef.actbox_category,
00209                             'transition': tdef}))
00210         res.sort()
00211         return [ result[1] for result in res ]

Here is the call graph for this function:

def DCWorkflow.DCWorkflow.DCWorkflowDefinition.notifyBefore (   self,
  ob,
  action 
)
Notifies this workflow of an action before it happens,
allowing veto by exception.  Unless an exception is thrown, either
a notifySuccess() or notifyException() can be expected later on.
The action usually corresponds to a method name.

Definition at line 352 of file DCWorkflow.py.

00352 
00353     def notifyBefore(self, ob, action):
00354         '''
00355         Notifies this workflow of an action before it happens,
00356         allowing veto by exception.  Unless an exception is thrown, either
00357         a notifySuccess() or notifyException() can be expected later on.
00358         The action usually corresponds to a method name.
00359         '''
00360         pass

Notifies this workflow after an object has been created and added.

Definition at line 342 of file DCWorkflow.py.

00342 
00343     def notifyCreated(self, ob):
00344         """Notifies this workflow after an object has been created and added.
00345         """
00346         try:
00347             self._changeStateOf(ob, None)
00348         except ( ObjectDeleted, ObjectMoved ):
00349             # Swallow.
00350             pass

Here is the call graph for this function:

def DCWorkflow.DCWorkflow.DCWorkflowDefinition.notifyException (   self,
  ob,
  action,
  exc 
)
Notifies this workflow that an action failed.

Definition at line 369 of file DCWorkflow.py.

00369 
00370     def notifyException(self, ob, action, exc):
00371         '''
00372         Notifies this workflow that an action failed.
00373         '''
00374         pass

def DCWorkflow.DCWorkflow.DCWorkflowDefinition.notifySuccess (   self,
  ob,
  action,
  result 
)
Notifies this workflow that an action has taken place.

Definition at line 362 of file DCWorkflow.py.

00362 
00363     def notifySuccess(self, ob, action, result):
00364         '''
00365         Notifies this workflow that an action has taken place.
00366         '''
00367         pass

Changes the object permissions according to the current state.

Definition at line 376 of file DCWorkflow.py.

00376 
00377     def updateRoleMappingsFor(self, ob):
00378         """Changes the object permissions according to the current state.
00379         """
00380         changed = 0
00381         sdef = self._getWorkflowStateOf(ob)
00382         if sdef is None:
00383             return 0
00384         # Update the role -> permission map.
00385         if self.permissions:
00386             for p in self.permissions:
00387                 roles = []
00388                 if sdef.permission_roles is not None:
00389                     roles = sdef.permission_roles.get(p, roles)
00390                 if modifyRolesForPermission(ob, p, roles):
00391                     changed = 1
00392         # Update the group -> role map.
00393         groups = self.getGroups()
00394         managed_roles = self.getRoles()
00395         if groups and managed_roles:
00396             for group in groups:
00397                 roles = ()
00398                 if sdef.group_roles is not None:
00399                     roles = sdef.group_roles.get(group, ())
00400                 if modifyRolesForGroup(ob, group, roles, managed_roles):
00401                     changed = 1
00402         return changed

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

DCWorkflow.DCWorkflow.DCWorkflowDefinition.__implements__ = z2IWorkflowDefinition [static, private]

Definition at line 69 of file DCWorkflow.py.

Definition at line 122 of file DCWorkflow.py.

Definition at line 88 of file DCWorkflow.py.

Definition at line 72 of file DCWorkflow.py.

Definition at line 84 of file DCWorkflow.py.

Definition at line 107 of file DCWorkflow.py.

Definition at line 75 of file DCWorkflow.py.

Initial value:
(
        {'label': 'Properties', 'action': 'manage_properties'},
        {'label': 'States', 'action': 'states/manage_main'},
        {'label': 'Transitions', 'action': 'transitions/manage_main'},
        {'label': 'Variables', 'action': 'variables/manage_main'},
        {'label': 'Worklists', 'action': 'worklists/manage_main'},
        {'label': 'Scripts', 'action': 'scripts/manage_main'},
        {'label': 'Permissions', 'action': 'manage_permissions'},
        {'label': 'Groups', 'action': 'manage_groups'},
        )

Definition at line 92 of file DCWorkflow.py.

Definition at line 90 of file DCWorkflow.py.

Definition at line 83 of file DCWorkflow.py.

Definition at line 85 of file DCWorkflow.py.

Definition at line 81 of file DCWorkflow.py.

tuple DCWorkflow.DCWorkflow.DCWorkflowDefinition.security = ClassSecurityInfo() [static]

Definition at line 103 of file DCWorkflow.py.

Definition at line 74 of file DCWorkflow.py.

Definition at line 77 of file DCWorkflow.py.

string DCWorkflow.DCWorkflow.DCWorkflowDefinition.title = 'DC Workflow Definition' [static]

Definition at line 71 of file DCWorkflow.py.

Definition at line 78 of file DCWorkflow.py.

Definition at line 79 of file DCWorkflow.py.

Definition at line 80 of file DCWorkflow.py.


The documentation for this class was generated from the following file: