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


from DataManagers import DataManager
from SheetProviders import SheetProvider
from AttributeProviders import AttributeProvider
from Providers import LinkToParentProviders
from Globals import HTMLFile, default__class_init__, PersistentMapping
from ComputedAttribute import ComputedAttribute
from Transactions import Kept
from App.Common import absattr
from DataSkins import DataSkin
from Products.PlugIns import MakePICBase
import Products


SelfKey = 'ZPatterns.Rack','Self'

00042 class Rack(DataManager, Kept):

    Basic Rack - supports sheet and attribute provider plugins, as
    well as persistent storage of any ZClass object and arbitrary
    associated data (using "slots").

    # Template (i.e. abstract) methods, should be left as-is

00052     def getItem(self, key):
        """Get an item from the rack by key"""
        # Borrow canonicals map for per-transaction item cache
        item = self._fromCache(key,_marker)
        if item is _marker:
            item = self.retrieveItem(key)
            self._toCache(key,item) # XXX Should we cache non-existence?
        return item

00065     def newItem(self, key=None):
        """Create a new item - attempts to generate key if not supplied"""

        if key is None:
            key=key and key()
            if key is None: return None

        return self.createItem(key)

    def _objectDeleting(self,client):

    # Methods to be overridden in subclasses for non-ZODB storage

    loadAttrib = ''  # If not empty, attribute to use when loading an item

    def retrieveItem(self,key):

        # Retrieve an object, identified by key

        a = self.loadAttrib
        item = None

        if a:
            item = self._RawItem(key)
            if hasattr(item.aq_base, a):
                return item

            # The block below is what you want to replace
            # if you're creating a non-ZODB storage.
            # In practice, from version 0.4.0 on, there's
            # no reason to do such a thing in the first place.
            slot = self._readableSlot(key)

            if slot:
                item = slot[SelfKey]

                # XXX class remapping should go here??

                self = self.aq_inner
                return item.__of__(self.aq_parent)

    def createItem(self,key):

        # Create a new object, identified by key

        item = self.getItem(key)

        # XXX What if all items potentially exist?
        if item is not None:
            raise KeyError,("'%s' already exists" % key)

        item = self._RawItem(key)

        a = self.loadAttrib
        if not a:
            slot = self._writeableSlot(key)
            slot[SelfKey] = item.aq_base    # strip acquisition wrapping
            item._setSlot(slot)             # Not needed for non-ZODB storage


        self._toCache(key,item) # XXX Should we cache non-creation?
        return item

    # Optionally overrideable methods for additional functionality

    #def newKey(self):
    #    """Generate a new object key"""
    #    pass    # must be defined if key autogeneration is desired
    # def countItems(self): pass
    # def deleteAll(self): pass

    _initialized = 0
    def _setup(self):
        # set up default providers
        if self._initialized:
            # We must only initialize once, since _setup gets called on pastes,
            # imports, etc.
                title='Plug-ins from parent Specialist')
            SheetProvider('PersistentSheets', title='Sheets stored in Rack slots')
                title='Attributes stored persistently in objects')
        self._initialized = 1

    # ZClass Machinery (Optionally overrideable)

    _defaultClass = None

    def _v_itemConstructor(self):
        c = getattr(self, '_zclass', None) or self._defaultClass

        if c:
            if type(c) is type(''):
                c = self._unifiedZClassRegistry()[c][1]   #Products.meta_classes[c]
            def err(key):
                raise TypeError, "No ZClass set - please use 'Storage' tab"
            return err

        c = getattr(c,'_zclass_',c)
        self._v_itemConstructor = c
        return c

    _v_itemConstructor = ComputedAttribute(lambda s,v=ComputedAttribute(_v_itemConstructor): v)  

00227     def _RawItem(self, key):
        Create an empty object of the right class
        self = self.aq_inner
        item = self._v_itemConstructor(key)
        item._setRack(self)                 # Connect to rack
        item = item.__of__(self.aq_parent.aq_inner)  # Link to Specialist
        return item

    def _isSelected(self, name, path, klass):
        Z = self._v_itemConstructor
        Z = getattr(Z, 'aq_self', Z)
        return klass._zclass_ is Z

    # Caching

    def _v_cache(self):
        l = self._v_cache = {}
        return l

    _v_cache = ComputedAttribute(_v_cache)

    __per_transaction_cache_attrs__ = ('_v_cache',)

    def _fromCache(self, key, default=None):
        return self._v_cache.get(key,default)

    def _toCache(self, key, item):
        self._v_cache[key] = item

    # Persistence Machinery - little need to override, but to be extended
    # for future multi-ZODB support

    storageInfo = ''    # Reserved for configuring future multi-ZODB support
    __storage = None    # This rack's storage object for sheets and/or objects

00294     def storageInUse(self):
        """How many racked items have persistent storage use?"""
        return len(self.__readableStorage)

00298     def __writeableStorage(self):
        """Create new a mapping-like object for storing 'persistent' stuff and save it in self"""
        from BTree import BTree
        s = self.__readableStorage = self.__writeableStorage = BTree()
        return s
    __readableStorage = {}
    __writeableStorage = ComputedAttribute(__writeableStorage)

00308     def _migrateStorage(self,storage):
        """Move existing data to new kind of storage"""

        #if self.storageInUse():
        #    raise ValueError, "Cannot change storage with contents present"

        raise "NotImplemented", "Only self-storage is currently supported"

        # XXX self.storageInfo = storage; del self.__storage

00318     def manage_storageOptions(self):
        """Return a list of key-value pair tuples listing storage options"""
        return [('', 'Directly in this object')]

    def _getClientID(self,client):
        return absattr(client.id)

    def _readableSlotFor(self, client):
        slot = self._readableSlot(self._getClientID(client),_marker)
        if slot is not _marker: 
            return slot
            return {}

    def _writeableSlotFor(self, client):
        slot = self._writeableSlot(self._getClientID(client))
        return slot

    def _readableSlot(self, key, default={}):
        return self.__readableStorage.get(key,default)

    def _writeableSlot(self, key):
        r = self.__writeableStorage.get(key,_marker)
        if r is _marker:
            r = self.__writeableStorage[key] = PersistentMapping()
        return r

00352     def _delSlotFor(self, client):

        """Delete persistent mapping for client, if present"""

        id = self._getClientID(client)
        if self.__readableStorage.has_key(id): del self.__writeableStorage[id]
    def getPersistentItemIDs(self):
        return self.__readableStorage.keys()

    # Management interface

    manage_storageForm = HTMLFile('www/storageForm', globals())

00374     def manage_setStorage(self, zclass=None, storage=None, use_attrib=None, \
        load_attrib=None, REQUEST=None):

        Change class of returned items, and persistent storage used
        to store them

        if zclass is not None:
            if self._unifiedZClassRegistry().has_key(zclass):
                #if Products.meta_classes.has_key(zclass):
                    self._zclass = zclass
                #    self._zclass = self._unifiedZClassRegistry()[zclass][1]
                    if self.__dict__.has_key('_v_itemConstructor'):
                         del self._v_itemConstructor
                raise NameError,("Invalid/nonexistent ZClass '%s'" % zclass)

        if storage is not None and storage != self.storageInfo:

        if use_attrib is not None and load_attrib is not None:
            self.loadAttrib = (use_attrib=="YES") and load_attrib or ""

        if REQUEST is not None:
            return self.manage_storageForm(self, REQUEST,
                manage_tabs_message='Updated storage settings.')

00411     def manage_pack(self,REQUEST=None):
        """Pack storage and remove unused objects"""

        if self.__readableStorage:
            for id in self.getPersistentItemIDs():
                if self.getItem(id) is None: del w[id]
                c=(c+1) % 1000
                if not c: get_transaction().commit(1)

        if REQUEST is not None:
            return self.manage_storageForm(self, REQUEST,
                manage_tabs_message='Pack completed.')

    manage_options_right = (
    ) + DataManager.manage_options_right

    meta_type = "Rack"
    __plugin_kind__ = "Rack"
    icon = 'misc_/ZPatterns/rack'

    __ac_permissions__ = (
        ('Change Rack storage settings',

        ('Access contents information',

        ('Add Items to Racks', ('newItem','createItem','newKey'), ),

default__class_init__(Rack); MakePICBase(Rack)

manage_addRackForm = HTMLFile('addRack', globals())

def manage_addRack(self, id, title='', REQUEST=None):
    """Add a Rack"""
    ob = Rack(id, title)
    return self.Destination()._installPlugIn(ob,'Added Rack.',REQUEST)

class RackMountable(DataSkin):

def initialize(context):

        permission = 'Add Racks',
        constructors = (manage_addRackForm,
        icon = 'www/rack.gif',


Generated by  Doxygen 1.6.0   Back to index