[ZODB-Dev] Excellent overview of ODBMS and my take on ZODB

Patrick K. O'Brien pobrien@orbtech.com
Tue, 26 Feb 2002 18:58:20 -0600


Steve Alexander said:

[snip]
>
> The ObjectHub, as checked into Zope3, is basically a means of
> associating uniquely generated location-independent integer identifiers
> with objects.
>
> There's no particular dependency on Zope. There is a dependency on
> Interfaces.
>
> --
> Steve Alexander


It just seems pretty elaborate for the stated purpose. I don't understand
the need for a hub with publishers and subscribers in this context. Here is
how I'm solving the problem:


"""Entity base classes."""

__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
__cvsid__ = "$Id: entity.py,v 1.6 2002/02/25 22:28:19 pobrien Exp $"
__version__ = "$Revision: 1.6 $"[11:-2]

import ZODB
from Persistence import Persistent
from bdoz import field
from bdoz import keygenerator
from bdoz import transaction
from BTrees.IOBTree import IOBTree


class Entity(Persistent):
    """Entity class. Keeps track of all its instances."""

    # This _entitySet class attribute will be established by the application
    # because the actual EntitySet instance will be retrieved from the
database.
    # The net result will be something like the following:
    # _entitySet = EntitySet()

    def __init__(self):
        """Create an entity instance."""
        self._key = None
        key = keygenerator.new()
        while not self._entitySet._insert(key=key, entity=self):
            key = keygenerator.new()
        self._key = key
        transaction.commit(1)

    def key(self):
        """Return the unique identifier, or key."""
        return self._key

    def fields(self):
        """Return a list of fields used by the Entity class."""
        pass # Not yet implemented.

    def getEntitySet(self):
        """Return the EntitySet object that tracks this instances
siblings."""
        return self._entitySet


class EntitySet(Persistent):
    """EntitySet class. Keeps track of all instances of an Entity class."""

    def __init__(self):
        """Create an EntitySet instance."""
        self._entities = IOBTree()

    def _insert(self, key, entity):
        """Insert an entity into the set."""
        return self._entities.insert(key, entity)

    def count(self):
        """Return the number of entities in the set."""
        return len(self._entities)

    def delete(self, entity):
        """Remove the entity from the set."""
        if self._entities.has_key(entity._key):
            del self._entities[entity._key]

    def get(self, key, default=None):
        """Return the entity, or the default if the entity is not found."""
        return self._entities.get(key, default)

    def all(self):
        """Return all entities in the set."""
        return self._entities.values()

    def first(self):
        """Return the first entity in the set."""
        return self._entities[self._entities.minKey()]

    def last(self):
        """Return the last entity in the set."""
        return self._entities[self._entities.maxKey()]

    def next(self, entity):
        """Return the next entity in the set."""
        if entity._key != self._entities.maxKey():
            key = self._entities.minKey(entity._key + 1)
            entity = self._entities[key]
        return entity

    def prev(self, entity):
        """Return the previous entity in the set."""
        if entity._key != self._entities.minKey():
            key = self._entities.maxKey(entity._key - 1)
            entity = self._entities[key]
        return entity

    def values(self, fieldName):
        """Return a dictionary of value, entity list pairs."""
        values = {}
        for entity in self.all():
            try:
                value = getattr(entity, fieldName).get()
                if values.has_key(value):
                    values[value].append(entity)
                else:
                    values[value] = [entity]
            except AttributeError:
                pass
        return values


This works for me. It isn't complete yet. And it may have some flaws. But
for the kinds of standalone applications that I'm using it on, I'm pretty
happy with it. Your thoughts?

---
Patrick K. O'Brien
Orbtech