--- a/entities/wfobjs.py Tue Aug 25 13:36:02 2009 +0200
+++ b/entities/wfobjs.py Tue Aug 25 18:24:54 2009 +0200
@@ -94,9 +94,7 @@
# wf construction methods ##################################################
def add_state(self, name, initial=False, **kwargs):
- """method to ease workflow definition: add a state for one or more
- entity type(s)
- """
+ """add a state to this workflow"""
state = self.req.create_entity('State', name=unicode(name), **kwargs)
self.req.execute('SET S state_of WF WHERE S eid %(s)s, WF eid %(wf)s',
{'s': state.eid, 'wf': self.eid}, ('s', 'wf'))
@@ -107,12 +105,9 @@
{'s': state.eid, 'wf': self.eid}, ('s', 'wf'))
return state
- def add_transition(self, name, fromstates, tostate,
- requiredgroups=(), conditions=(), **kwargs):
- """method to ease workflow definition: add a transition for one or more
- entity type(s), from one or more state and to a single state
- """
- tr = self.req.create_entity('Transition', name=unicode(name), **kwargs)
+ def _add_transition(self, trtype, name, fromstates,
+ requiredgroups=(), conditions=(), **kwargs):
+ tr = self.req.create_entity(trtype, name=unicode(name), **kwargs)
self.req.execute('SET T transition_of WF '
'WHERE T eid %(t)s, WF eid %(wf)s',
{'t': tr.eid, 'wf': self.eid}, ('t', 'wf'))
@@ -122,12 +117,32 @@
self.req.execute('SET S allowed_transition T '
'WHERE S eid %(s)s, T eid %(t)s',
{'s': state, 't': tr.eid}, ('s', 't'))
+ tr.set_transition_permissions(requiredgroups, conditions, reset=False)
+ return tr
+
+ def add_transition(self, name, fromstates, tostate,
+ requiredgroups=(), conditions=(), **kwargs):
+ """add a transition to this workflow from some state(s) to another"""
+ tr = self._add_transition('Transition', name, fromstates,
+ requiredgroups, conditions, **kwargs)
if hasattr(tostate, 'eid'):
tostate = tostate.eid
self.req.execute('SET T destination_state S '
'WHERE S eid %(s)s, T eid %(t)s',
{'t': tr.eid, 's': tostate}, ('s', 't'))
- tr.set_transition_permissions(requiredgroups, conditions, reset=False)
+ return tr
+
+ def add_wftransition(self, name, subworkflow, fromstates, exitpoints,
+ requiredgroups=(), conditions=(), **kwargs):
+ """add a workflow transition to this workflow"""
+ tr = self._add_transition('WorkflowTransition', name, fromstates,
+ requiredgroups, conditions, **kwargs)
+ if hasattr(subworkflow, 'eid'):
+ subworkflow = subworkflow.eid
+ self.req.execute('SET T subworkflow WF WHERE WF eid %(wf)s,T eid %(t)s',
+ {'t': tr.eid, 'wf': subworkflow}, ('wf', 't'))
+ for fromstate, tostate in exitpoints:
+ tr.add_exit_point(fromstate, tostate)
return tr
@@ -191,7 +206,6 @@
self.req.execute('DELETE T condition R WHERE T eid %(x)s',
{'x': self.eid}, 'x')
for gname in requiredgroups:
- ### XXX ensure gname validity
rset = self.req.execute('SET T require_group G '
'WHERE T eid %(x)s, G name %(gn)s',
{'x': self.eid, 'gn': gname}, 'x')
@@ -232,6 +246,50 @@
def destination(self):
return self.subwf.initial
+ def add_exit_point(self, fromstate, tostate):
+ if hasattr(fromstate, 'eid'):
+ fromstate = fromstate.eid
+ if hasattr(tostate, 'eid'):
+ tostate = tostate.eid
+ self.req.execute('INSERT SubWorkflowExitPoint X: T subworkflow_exit X, '
+ 'X subworkflow_state FS, X destination_state TS '
+ 'WHERE T eid %(t)s, FS eid %(fs)s, TS eid %(ts)s',
+ {'t': self.eid, 'fs': fromstate, 'ts': tostate},
+ ('t', 'fs', 'ts'))
+
+ def get_exit_point(self, state):
+ """if state is an exit point, return its associated destination state"""
+ if hasattr(state, 'eid'):
+ state = state.eid
+ stateeid = self.exit_points().get(state)
+ if stateeid is not None:
+ return self.req.entity_from_eid(stateeid)
+ return None
+
+ @cached
+ def exit_points(self):
+ result = {}
+ for ep in self.subworkflow_exit:
+ result[ep.subwf_state.eid] = ep.destination.eid
+ return result
+
+ def clear_all_caches(self):
+ super(WorkflowableMixIn, self).clear_all_caches()
+ clear_cache(self, 'exit_points')
+
+
+class SubWorkflowExitPoint(AnyEntity):
+ """customized class for SubWorkflowExitPoint entities"""
+ id = 'SubWorkflowExitPoint'
+
+ @property
+ def subwf_state(self):
+ return self.subworkflow_state[0]
+
+ @property
+ def destination(self):
+ return self.destination_state[0]
+
class State(AnyEntity):
"""customized class for State entities"""