[Zope-Checkins] CVS: Zope3/lib/python/Zope/ObjectHub - IRuidObjectEvent.py:1.1.2.1 RuidObjectEvent.py:1.1.2.1 IObjectHub.py:1.1.2.2 ObjectHub.py:1.1.2.4

Steve Alexander steve@cat-box.net
Sun, 24 Feb 2002 16:35:39 -0500


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

Modified Files:
      Tag: Zope-3x-branch
	IObjectHub.py ObjectHub.py 
Added Files:
      Tag: Zope-3x-branch
	IRuidObjectEvent.py RuidObjectEvent.py 
Log Message:
Added RuidObjectEvents and tests. Updated ObjectHub to act as a persistent EventChannel. Updated tests for ObjectHub to test that it sends out the correct kindsof event for the events it receives. That bit was fun! :-)



=== Added File Zope3/lib/python/Zope/ObjectHub/IRuidObjectEvent.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: IRuidObjectEvent.py,v 1.1.2.1 2002/02/24 21:35:38 stevea Exp $
"""
from Zope.Event.IEvent import IEvent

class IRuidObjectEvent(IEvent):
    """Something has happened to an object for which there is an ruid.
       An ruid is a way or refering to an object independent of location.
    """

    def getRuid():
        """Returns the object's ruid."""
        
    def getLocation():
        """Returns the object's current location."""
        
    def getObject():
        """Returns the object."""
        


class IRuidObjectRegisteredEvent(IRuidObjectEvent):
    """An ruid has been freshly created and mapped against an object."""


class IRuidObjectUnregisteredEvent(IRuidObjectEvent):
    """We are no longer interested in this object."""


class IRuidObjectAddedEvent(IRuidObjectRegisteredEvent):
    """An ruid has been freshly created and mapped against an object.
       Also, implies the object has been newly added."""
    
    
class IRuidObjectModifiedEvent(IRuidObjectEvent):
    """An object with an ruid has been modified."""
    
    
class IRuidObjectContextChangedEvent(IRuidObjectEvent):
    """An object with an ruid has had its context changed. Typically, this
       means that it has been moved."""

       
class IRuidObjectRemovedEvent(IRuidObjectUnregisteredEvent):
    """An object with an ruid has been removed."""

    def getLocation():
        """Returns the object's location before it was removed."""

    def getObject():
        """Returns the object, or None if the object is unavailable."""


=== Added File Zope3/lib/python/Zope/ObjectHub/RuidObjectEvent.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: RuidObjectEvent.py,v 1.1.2.1 2002/02/24 21:35:38 stevea Exp $
"""

from IRuidObjectEvent import IRuidObjectRegisteredEvent
from IRuidObjectEvent import IRuidObjectAddedEvent
from IRuidObjectEvent import IRuidObjectUnregisteredEvent
from IRuidObjectEvent import IRuidObjectModifiedEvent
from IRuidObjectEvent import IRuidObjectContextChangedEvent
from IRuidObjectEvent import IRuidObjectRemovedEvent

class RuidObjectEvent:
    """Conenient mix-in for RuidObjectEvents"""
    
    def __init__(self, objecthub, ruid, location):
        # we keep all three, to avoid unnecessary lookups
        # and to give the objecthub an opportunity to do
        # caching of objects
        self.__objecthub = objecthub
        self.__ruid = ruid
        self.__location = location
        
    def getRuid(self):
        return self.__ruid
        
    def getLocation(self):
        return self.__location
        
    def getObject(self):
        if hasattr(self, '_v_object'):
            return self._v_object
        obj = self._v_object = self.__objecthub.getObject(self.__ruid)
        return obj


class RuidObjectRegisteredEvent(RuidObjectEvent):
    """An ruid has been freshly created and mapped against an object."""

    __implements__ = IRuidObjectRegisteredEvent


class RuidObjectUnregisteredEvent(RuidObjectEvent):
    """We are no longer interested in this object."""

    __implements__ = IRuidObjectUnregisteredEvent


class RuidObjectAddedEvent(RuidObjectEvent):
    """An ruid has been freshly created and mapped against an object.
       Also, implies the object has been newly added."""
    
    __implements__ = IRuidObjectAddedEvent
    
    
class RuidObjectModifiedEvent(RuidObjectEvent):
    """An object with an ruid has been modified."""
    
    __implements__ = IRuidObjectModifiedEvent
    
    
class RuidObjectContextChangedEvent(RuidObjectEvent):
    """An object with an ruid has had its context changed. Typically, this
       means that it has been moved."""
       
    __implements__ = IRuidObjectContextChangedEvent


class RuidObjectRemovedEvent(RuidObjectEvent):
    """An object with an ruid has been removed."""

    __implements__ = IRuidObjectRemovedEvent

    def __init__(self, obj, ruid, location):
        self.__object = obj
        self.__ruid = ruid
        self.__location = location

    def getRuid(self):
        return self.__ruid
        
    def getLocation(self):
        return self.__location

    def getObject(self):
        return self.__object


=== Zope3/lib/python/Zope/ObjectHub/IObjectHub.py 1.1.2.1 => 1.1.2.2 ===
        Table of decisions about maintaining the location<->ruid lookup:
        
-         Add
+         Register
          
             if location already in lookup:
-                raise ObjectHubError, as this is not an interesting object
+                raise ObjectHubError, as this is implies bad state somewhere
             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
+             
+            send out ruid object register event to plug-ins, via event channels
+         
+         Unregister
+         
+            if location not in lookup:
+                raise ObjectHubError, as this is implies bad state somewhere
+            remove location<->ruid from lookup
+            
+            send out ruid unregister event to plug-ins, via event channels
+       
+         Add (specialises Register)
+         
+            as Register, except at the end send out ruid object add event
+            instead
          
          Modify
          
@@ -69,7 +83,7 @@
                 send out ruid object context-change event to plug-ins,
                     via event channels
          
-         Remove
+         Remove (specialises Unregister)
 
             if old_location not in lookup:
                 ignore this event, as we're not interested in this object
@@ -83,6 +97,10 @@
         # XXX: Possibly add Link to EventChannel.
         #      This implies multiple locations for a ruid. 
         #      We'll refactor later if needed.
+        
+        # Possibly also add registerObject and unregisterObject methods
+        # unless these are better handled by events, or unless we don't
+        # need them.
     
     """
 
@@ -108,4 +126,10 @@
         
         """
         
+    def getObject(ruid):
+        """Returns an object for the given ruid.
         
+        If there is no such ruid, raise Zope.Exceptions.NotFoundError.
+        If there is no such object, passes through whatever error
+        the traversal service raises.
+        """


=== Zope3/lib/python/Zope/ObjectHub/ObjectHub.py 1.1.2.3 => 1.1.2.4 ===
 from Zope.Event.IObjectEvent import IObjectAddedEvent, IObjectModifiedEvent
 from Zope.Event.IObjectEvent import IObjectRemovedEvent, IObjectMovedEvent
+from Zope.Event.EventChannel import EventChannel
+from RuidObjectEvent import RuidObjectRegisteredEvent
+from RuidObjectEvent import RuidObjectUnregisteredEvent
+from RuidObjectEvent import RuidObjectAddedEvent
+from RuidObjectEvent import RuidObjectModifiedEvent
+from RuidObjectEvent import RuidObjectContextChangedEvent
+from RuidObjectEvent import RuidObjectRemovedEvent
 
 from Zope.Exceptions import NotFoundError
 from Persistence import Persistent
@@ -28,6 +35,9 @@
 from Persistence.BTrees.IOBTree import IOBTree
 from Persistence.BTrees.OIBTree import OIBTree
 
+from Zope.App.Traversing.ITraverser import ITraverser
+from Zope.ComponentArchitecture import getAdapter
+
 # Code taken from PluginIndexes/common/randid.py
 import whrandom
 def randid(randint=whrandom.randint, choice=whrandom.choice, signs=(-1,1)):
@@ -43,18 +53,22 @@
     def __init__(self):
         self.__ruid_to_location = IOBTree()
         self.__location_to_ruid = OIBTree()
+        self.__eventchannel = EventChannel()
         
+    _clear = __init__
+
 
     ############################################################
     # Implementation methods for interface
     # Zope.ObjectHub.IObjectHub
 
-    def subscribe(self, subscriber, event_types=None, filter=None):
+    def subscribe(self, subscriber, event_types=(None,), filter=None):
         '''See interface ISubscribable'''
-        
+        self.__eventchannel.subscribe(subscriber, event_types, filter)
 
     def unsubscribe(self, subscriber):
         '''See interface ISubscribable'''
+        self.__eventchannel.unsubscribe(subscriber)
 
     def notify(self, event):
         '''See interface ISubscriber'''
@@ -87,6 +101,12 @@
         except KeyError:
             raise NotFoundError, ruid
         
+    def getObject(self, ruid):
+        '''See interface IObjectHub'''
+        location = self.lookupLocation(ruid)
+        adapter = getAdapter(object, ITraverser)
+        return adapter.restrictedTraverse(location)
+        
     #
     ############################################################
 
@@ -117,9 +137,28 @@
                 canonical_location
         ruid = self._generateRuid(canonical_location)
         location_to_ruid[canonical_location] = ruid
+        
+        # send out to plugins IRuidObjectAddedEvent
+        event = RuidObjectAddedEvent(
+            self, 
+            ruid,
+            canonical_location)
+        self.__eventchannel.notify(event)
+        
     
     def _objectModified(self, location):
-        pass
+        location_to_ruid = self.__location_to_ruid
+        canonical_location = self._canonical(location)
+        if not location_to_ruid.has_key(canonical_location):
+            # we're not interested in this event
+            return
+            
+        # send out to plugins IRuidObjectModifiedEvent
+        event = RuidObjectModifiedEvent(
+            self, 
+            location_to_ruid[canonical_location],
+            canonical_location)
+        self.__eventchannel.notify(event)
         
     
     def _objectMoved(self, old_location, new_location):
@@ -138,8 +177,15 @@
         del location_to_ruid[canonical_location]
         location_to_ruid[canonical_new_location] = ruid
         self.__ruid_to_location[ruid] = canonical_new_location
+        
+        # send out to plugins IRuidObjectContextChangedEvent
+        event = RuidObjectContextChangedEvent(
+            self, 
+            ruid,
+            canonical_new_location)
+        self.__eventchannel.notify(event)
+
             
-    
     def _objectRemoved(self, location):
         location_to_ruid = self.__location_to_ruid
         ruid_to_location = self.__ruid_to_location
@@ -154,4 +200,9 @@
         del ruid_to_location[ruid]
         del location_to_ruid[canonical_location]
             
-
+        # send out to plugins IRuidObjectRemovedEvent
+        event = RuidObjectRemovedEvent(
+            None,   # no object to give
+            ruid,
+            canonical_location)
+        self.__eventchannel.notify(event)