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:
parent
1b67c54099
commit
f9e8a3f45c
4 changed files with 64 additions and 32 deletions
|
@ -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))
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
"""
|
||||
|
|
|
@ -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):
|
||||
|
|
Loading…
Add table
Reference in a new issue