work in progress: rules and action handling

git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@2144 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2007-11-03 16:59:11 +00:00
parent 1b67c54099
commit f9e8a3f45c
4 changed files with 64 additions and 32 deletions

View file

@ -8,6 +8,10 @@ Rule-based Execution of Actions
>>> from cybertools.composer.rule.base import RuleManager, Rule, Action
>>> from cybertools.composer.rule.base import EventType, Event
>>> from cybertools.composer.rule.base import ActionHandler
>>> component.provideAdapter(ActionHandler, name='message')
>>> component.provideAdapter(ActionHandler, name='sendmail')
>>> manager = RuleManager()
>>> loginEvent = EventType('login')
@ -18,7 +22,7 @@ Rule-based Execution of Actions
>>> checkoutRule.actions.append(Action('message',
... parameters = dict(messageName='confirmation_mail')))
>>> checkoutRule.actions.append(Action('sendmail'))
>>> manager.rules.append(checkoutRule)
>>> manager.addRule(checkoutRule)
>>> manager.handleEvent(Event(loginEvent))

View file

@ -22,6 +22,8 @@ Basic classes for rules and actions.
$Id$
"""
from zope import component
from zope.component import adapts
from zope.interface import implements
from cybertools.composer.base import Component, Element, Compound
@ -42,12 +44,29 @@ class RuleManager(object):
rulesFactory = Jeep
rules = None
def __init__(self):
if self.rulesFactory is not None:
def addRule(self, rule):
rule.manager = self
if self.rules is None:
self.rules = self.rulesFactory()
for e in rule.events:
entry = self.rules.setdefault(e.name, [])
entry.append(rule)
def getRulesForEvent(self, event):
return self.rules.get(event.name, [])
def handleEvent(self, event):
pass
rules = self.getRulesForEvent(event)
for r in rules:
for c in r.conditions:
cond = component.getAdapter(r, ICondition, name=c)
if not cond(event):
continue
data = None
for action in r.actions:
handler = component.getAdapter(action, IActionHandler,
name=action.handlerName)
data = handler(data, event)
class Rule(Template):
@ -101,21 +120,13 @@ class Event(object):
# conditions
class ConditionType(object):
def __init__(self, name, title):
self.name = name
self.title = title
class Condition(object):
implements(ICondition)
adapts(IRule)
def __init__(self, conditionType):
self.conditionType = conditionType
self.name = conditionType.name
self.title = conditionType.title
def __init__(self, context):
self.context = context
def __call__(self, context, params):
return True
@ -123,7 +134,7 @@ class Condition(object):
# actions
class Action(object):
class Action(Component):
implements(IAction)
@ -133,17 +144,22 @@ class Action(object):
rule = None
def __init__(self, name, **kw):
self.name = name
for k, v in kw.items():
setattr(self, k, v)
if self.parameters is None:
self.parameters = {}
if not self.handlerName:
self.handlerName = self.name
self.handlerName = name
class ActionHandler(object):
implements(IActionHandler)
adapts(IAction)
def __call__(self, data, params):
def __init__(self, context):
self.context = context
def __call__(self, data, event, params={}):
pass

View file

@ -40,11 +40,21 @@ class IRuleManager(Interface):
description=_(u'The title of the object.'),
required=True,)
rules = Attribute('An ordered collection of rules managed by this object.')
#rules = Attribute('An ordered collection of rules managed by this object.')
def addRule(rule):
""" Add the rule given to the rule manager's collection of rules,
registering it for the event types that are handled by
the rule.
"""
def getRulesForEvent(event):
""" Retrieve the rules that may handle the event given.
"""
def handleEvent(event):
""" Handle the event given and apply the corresponding rules
to the client object.
to the event's context object.
"""
@ -66,9 +76,10 @@ class IRule(ITemplate):
required=False,)
manager = Attribute('The associated rule manager.')
events = Attribute('The events to be handled by this rule.')
events = Attribute('The events (the event types, to be more precise) '
'to be handled by this rule.')
conditions = Attribute('Conditions to be checked.'
'This is typically a list of names of ICondition adapters.')
'This is typically a list of names of ICondition adapters.')
actions = Attribute('Sequence of actions to be carried out by this rule.')
@ -81,7 +92,7 @@ class IEvent(Interface):
class ICondition(Interface):
def __call__(context, params):
def __call__(context, event, params):
""" Should return True if the condition should be fulfilled;
will allow the rule to call its actions.
"""

View file

@ -45,18 +45,16 @@ from cybertools.organize.interfaces import IRegistration, IRegistrationTemplate
from cybertools.organize.interfaces import IClientRegistrations
class ServiceManager(RuleManager):
class ServiceManager(object):
implements(IServiceManager, IClientManager)
servicesFactory = Jeep
clientSchemasFactory = Jeep
clientsFactory = OOBTree
rulesFactory = Jeep
services = None
clients = None
rules = None
allowRegWithNumber = False
allowDirectRegistration = True
@ -66,8 +64,6 @@ class ServiceManager(RuleManager):
self.services = self.servicesFactory()
if self.clientSchemasFactory is not None:
self.clientSchemas = self.clientSchemasFactory()
if self.rulesFactory is not None:
self.rules = self.rulesFactory()
def getServices(self, categories=[]):
return self.services
@ -94,9 +90,6 @@ class ServiceManager(RuleManager):
def checkClientName(self, name):
return name not in self.getClients()
def getRules(self):
return self.rules
class Registration(object):
@ -351,13 +344,21 @@ class StatefulRegistration(StatefulAdapter):
statesDefinition = registrationStates
# event types for rule-based processing
# rules and events
eventTypes = Jeep((
EventType('service.checkout'),
))
class RuleManagerAdapter(RuleManager):
adapts(IServiceManager)
def __init__(self, context):
self.context = context
# Zope event handlers
def clientRemoved(obj, event):