Logo Search packages:      
Sourcecode: zope-loginmanager version File versions

Agents.py

from Proxy import ProxyManager
from Providers import Provider
from ComputedAttribute import ComputedAttribute
from DataSkins import AddedStatus, ChangedStatus, DeletedStatus, NOT_FOUND
# XXX from zLOG import LOG, INFO, ERROR
from Products.PlugIns import defaultConstructors
from Expressions import *
from string import split,strip

































class AgentMixin:

    def namesForRegistration(self,container):
        "Agents provide 'handlers'; subclasses may add attributes and sheets"
        return { 'provides': ('handlers',) }


    def _objectAdding(self, client, 
        _tmap={ None:AddedStatus,
                DeletedStatus:ChangedStatus,
                ChangedStatus:AddedStatus
              }
        ):
        t = client._getTokenFor(self)
        s = t.status
        t.status = _tmap.get(s,s)


    def _objectDeleting(self,client):

        t = client._getTokenFor(self)
        s = t.status

        if s is None:
            t.status  = DeletedStatus
            t.memento = self._getMementoFor(client)
        elif s is AddedStatus:
            t.status = None
        elif s is ChangedStatus:
            t.status = DeletedStatus


    def _objectChanging(self,client):

        t = client._getTokenFor(self)

        if t.status is None:
            t.status  = ChangedStatus
            t.memento = self._getMementoFor(client)


    def commit(self, token, transaction):

        s, c = token.status, token.client

        if s is ChangedStatus:
            self._objectChanged(c, token.memento)
                    
        elif s is AddedStatus:
            self._objectAdded(c)
                    
        elif s is DeletedStatus:
            self._objectDeleted(c, token.memento)

        

    # Ignore all other transactional messages

    def abort(self, *args): pass

    tpc_abort = abort_sub = tpc_begin = tpc_finish = commit_sub = tpc_vote = abort





















00124 class Agent(AgentMixin, Provider):

    """Thing that monitors DataSkin events"""
    
    __plugin_kind__ = 'Monitoring Agent'

    def _getMementoFor(self,client):
        # Override to return a memento object relevant to the agent
        pass

    def _objectChanged(self,client,memento):
        pass

    def _objectDeleted(self,client,memento):
        pass

    def _objectAdded(self,client):
        pass























class GTMixin:
    def _getMementoFor(self,client):
    
        if not self._mementos:
            return _emptyMemento
            
        memento = _memento()
        d=memento.__dict__

        t = NamespaceStack()
        t._push(InstanceDict(client, t))
        pushProxy(self)
        
        try:
            for n,e in self._mementos:
                d[n] = e.eval(t)                
        finally:
            popProxy(self)
            t._pop()

        return memento

    def _objectChanged(self,client,memento):
        self._notify('CHANGE',client,memento)

    def _objectDeleted(self,client,memento):
        self._notify('DELETE',client,memento)

    def _objectAdded(self,client):
        self._notify('ADD',client,_emptyMemento)

    def namesForRegistration(self,container):
        if self.handle_set_for:
            return {
                'provides': ('handlers','attributes'),
                'setattr': self.handle_set_for,
                'delattr': self.handle_set_for,
            }    
        return { 'provides': ('handlers',) }


    _onlySaveAttrs = 0

    def _notify(self,event,client,memento):

        if event not in self.applicable_events or self._expr is None:
            return
            
        changed = client._v_changedAttrs_
        CHANGED = changed.has_key

        if self._onlySaveAttrs and not ('*' in self.handle_set_for and changed):
            # Don't call unless one of the attrs is changed
            for a in self.handle_set_for:
                if CHANGED(a): break
            else:
                return

        #LOG('ZPatterns', INFO, 'Object %s from [%s] to [%s]' %
        #    (event,memento.__dict__,self._getMementoFor(client).__dict__)
        #) XXX 

        t = NamespaceStack()

        t._push(InstanceDict(self, t))
        t._push({
            'self':client, 'TRIGGER_EVENT':event, 'OLD':memento,
            'CHANGED': CHANGED, 'HAS_CHANGED': CHANGED, 
            'CHANGED_ATTRS': changed.keys,
            'ORIGINAL': changed.copy(), 'NOT_FOUND': NOT_FOUND,
        })

        pushProxy(self)
                
        try:
            result = self._expr.eval(t)
        finally:
            popProxy(self)
            t._pop(2)

        return result

    def _SetAttributeFor(self,client,name,value):
        client._getCache()[name]=value
        return 1

    def _DelAttributeFor(self,client,name):
        """Delete the attribute and return true if successful"""
        client._getCache()[name]=NOT_FOUND
        if client._v_changedAttrs_[name] is NOT_FOUND: del client._v_changedAttrs_[name]
        return 1
































00288 class GenericTrigger(GTMixin,Agent,ProxyManager):

    """Call an expression upon change to an object"""
    
    meta_type = 'Generic Trigger'
    manage_options = Agent.manage_options + ProxyManager.manage_options
    _mementos = memento_exprs = handle_set_for = ()
    _expr = None
    callexpr = ''
    applicable_events = event_kinds = 'ADD', 'CHANGE', 'DELETE'
    
    def _propertiesChanged(self):
        m = self._mementos = []
        
        if self.callexpr: self._expr = Expression(self.callexpr)
        else:             self._expr = None

        for l in self.memento_exprs:
            if strip(l):
                if '=' in l:
                    a,e = split(strip(l), '=', 1)
                    m.append(a,Expression(e))
                else:
                    m.append(l,Name(l))

    _properties=(
        {'id':'title', 'type': 'string', 'mode': 'w'},
        {'id':'applicable_events', 'type': 'multiple selection',
            'mode': 'w', 'select_variable':'event_kinds'},
        {'id':'callexpr', 'type': 'string', 'mode': 'w'},
        {'id':'memento_exprs', 'type': 'lines', 'mode': 'w'},
        {'id':'handle_set_for','type': 'lines', 'mode': 'w'},
    )
    
    propertyLabels = {
        'title':'Title',
        'applicable_events': 'Upon:',
        'callexpr':'Execute:',
        'memento_exprs': 'Keeping:', 'handle_set_for':'Set Attrs:'
    }
    
class _memento: pass
_emptyMemento=_memento()


def initialize(context):
    return

    # disabled
    context.registerPlugInClass(
        GenericTrigger,
        permission = 'Add Generic Triggers',
        constructors = defaultConstructors(GenericTrigger,globals()),
        icon = 'www/trigger.gif'
    )


Generated by  Doxygen 1.6.0   Back to index