[Zope-Checkins] CVS: Zope3/lib/python/Zope/ObjectHub - IObjectHub.py:1.1.2.1 ObjectHub.py:1.1.2.1 __init__.py:1.1.2.1

Steve Alexander steve@cat-box.net
Fri, 22 Feb 2002 15:05:45 -0500


Update of /cvs-repository/Zope3/lib/python/Zope/ObjectHub
In directory cvs.zope.org:/tmp/cvs-serv1471

Added Files:
      Tag: Zope-3x-branch
	IObjectHub.py ObjectHub.py __init__.py 
Log Message:
Added in object hub naive implementation, interface and unit test.


=== Added File Zope3/lib/python/Zope/ObjectHub/IObjectHub.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
# 
##############################################################################
"""

Revision information:
$Id: IObjectHub.py,v 1.1.2.1 2002/02/22 20:05:45 stevea Exp $
"""

from Zope.Event.IEventChannel import IEventChannel

class IObjectHub(IEventChannel):
    """ObjectHub.
    
       Receives Object Modify Events from the Event Service, and
       changes these into RUID Object Modify Events, then passes
       these on to its PlugIns (possibly via some other EventChannels).
       
       To map Object Modify Events onto RUID Object Modify Events, take
       the location from the Object Modify Event, look up the RUID for this
       location, and create an equivalent RUID Object Modify Event using this
       RUID.
       
       Note that we are concerned with locations and not with Objects.
       An object may have more than one location. That doesn't concern
       us here.
       
       Table of decisions about maintaining the location<->ruid lookup:
       
         Add
         
            if location already in lookup:
                raise ObjectHubError, as this is not an interesting object
            generate new ruid
            place ruid<->location into lookup, to say that we have an
                interesting object
            send out ruid object add event to plug-ins, via event channels
         
         Modify
         
            if location not in lookup:
                ignore this event, as we're not interested in this object
            else:
                look up ruid for the location
                send out ruid object modify event to plug-ins,
                    via event channels
                
         Move 

            if old_location not in lookup:
                ignore this event, as we're not interested in this object
            elif new_location is in lookup:
                raise ObjectHubError
            else:
                look up ruid for old_location
                change lookup:
                    remove ruid<->old_location
                    add ruid<->new_location
                send out ruid object context-change event to plug-ins,
                    via event channels
         
         Remove

            if old_location not in lookup:
                ignore this event, as we're not interested in this object
            else:
                look up ruid for old_location
                change lookup:
                    remove ruid<->old_location
                send out ruid object remove event to plug-ins,
                    via event channels
    
        # XXX: Possibly add Link to EventChannel.
        #      This implies multiple locations for a ruid. 
        #      We'll refactor later if needed.
    
    """

        
    def lookupRuid(location):
        """Returns the ruid int that is mapped to the given location.
        
        Location is either a string, or a sequence of strings.
        It must be absolute, so if it is a string it must start with a '/',
        and if it is a sequence, it must start with an empty string.
        
        ('','whatever','whatever2')
        '/whatever/whatever2'
        
        If there is no ruid, raise Zope.Exceptions.NotFoundError.
        
        """
        
    def lookupLocation(ruid):
        """Returns a location as a string.
        
        If there is no location, raise Zope.Exceptions.NotFoundError.
        
        """
        
        


=== Added File Zope3/lib/python/Zope/ObjectHub/ObjectHub.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
# 
##############################################################################
"""

Revision information:
$Id: ObjectHub.py,v 1.1.2.1 2002/02/22 20:05:45 stevea Exp $
"""

from IObjectHub import IObjectHub
from Zope.Event.IObjectEvent import IObjectAddedEvent, IObjectModifiedEvent
from Zope.Event.IObjectEvent import IObjectRemovedEvent, IObjectMovedEvent

from Zope.Exceptions import NotFoundError
from Persistence import Persistent

from Interface import objectImplements

from types import StringTypes

class ObjectHubError(Exception): pass

class ObjectHub(Persistent):

    __implements__ =  IObjectHub

    def __init__(self):
        self.__lookup={}
        self.__uid=0
        

    ############################################################
    # Implementation methods for interface
    # Zope.ObjectHub.IObjectHub

    def subscribe(self, subscriber, event_types=None, filter=None):
        '''See interface ISubscribable'''

    def unsubscribe(self, subscriber):
        '''See interface ISubscribable'''

    def notify(self, event):
        '''See interface ISubscriber'''
        if IObjectAddedEvent.isImplementedBy(event):
            self._objectAdded(event.getLocation())
            
        elif IObjectModifiedEvent.isImplementedBy(event):
            self._objectModified(event.getLocation())
            
        elif IObjectMovedEvent.isImplementedBy(event):
            self._objectMoved(event.getFromLocation(),
                              event.getLocation())
                              
        elif IObjectRemovedEvent.isImplementedBy(event):
            self._objectRemoved(event.getLocation())
            
        # otherwise, ignore the event

    def lookupRuid(self, location):
        '''See interface IObjectHub'''
        try:
            return self.__lookup[self._canonical(location)]
        except KeyError:
            raise NotFoundError, self._canonical(location)
    
    def lookupLocation(self, ruid):
        '''See interface IObjectHub'''
        try:
            return self.__lookup[ruid]
        except KeyError:
            raise NotFoundError, ruid
        
    #
    ############################################################

    def _generateRuid(self):
        # XXX: bad default implementation. Change me!
        self.__uid += 1
        self._p_changed = 1
        return self.__uid

    def _canonical(location):
        if not isinstance(location, StringTypes):
            location='/'.join(location)
        # URIs are ascii, right?
        return str(location)
        
    _canonical=staticmethod(_canonical)

    def _objectAdded(self, location):
        ruid = self._generateRuid()
        canonical_location = self._canonical(location)
        lookup = self.__lookup
        if lookup.has_key(canonical_location):
            raise ObjectHubError, 'location %s already in object hub' % \
                canonical_location
        lookup[canonical_location] = ruid
        lookup[ruid] = canonical_location
        self._p_changed = 1
    
    def _objectModified(self, location):
        pass
        
    
    def _objectMoved(self, old_location, new_location):
        lookup = self.__lookup
        canonical_location = self._canonical(old_location)
        canonical_new_location = self._canonical(new_location)
        if lookup.has_key(canonical_new_location):
            raise ObjectHubError, \
                'Cannot move to location %s, '\
                'as there is already something there' % canonical_new_location
        if not lookup.has_key(canonical_location):
            # we're not interested in this event
            return

        ruid = lookup[canonical_location]
        del lookup[canonical_location]
        lookup[canonical_new_location]=ruid
        lookup[ruid]=canonical_new_location
        self._p_changed = 1
            
    
    def _objectRemoved(self, location):
        lookup = self.__lookup
        canonical_location = self._canonical(location)
        try:
            ruid = lookup[canonical_location]
            del lookup[ruid]
            del lookup[canonical_location]
            self._p_changed = 1
        except KeyError:
            pass
            


=== Added File Zope3/lib/python/Zope/ObjectHub/__init__.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
# 
##############################################################################
"""

Revision information:
$Id: __init__.py,v 1.1.2.1 2002/02/22 20:05:45 stevea Exp $
"""