"""$URL: svn+ssh://svn.mems-exchange.org/repos/trunk/dulcinea/lib/keyed.py $
$Id: keyed.py 23930 2004-04-07 19:37:47Z dbinger $
"""

from durus.persistent_dict import PersistentDict
from dulcinea.spec import require, get_spec_problems, anything, mapping

class Keyed:

    """
    An item with an int key used as a key in an KeyedMap.
    Note that the key attribute is set when the item is put in the KeyedMap,
    so there is no set_key() method.

    Instance attributes:
      key : int
    """
    key_is = int

    def __init__(self):
        self.key = None

    def get_key(self):
        return self.key


class KeyedMap:
    """
    A mixin for a simple database that stores a map objects by key.

    Instance attributes:
        mapping : PersistentDict { int: Keyed }
        value_spec : any
            Specifies the type of values allowed in mapping
        key_counter : int
            Next available key number.
    """

    mapping_is = mapping({int:Keyed}, PersistentDict)
    value_spec_is = anything
    key_counter_is = int

    def __init__(self, value_spec=Keyed):
        self.key_counter = 1
        self.value_spec = value_spec
        self.mapping = PersistentDict()

    def get(self, key, *args):
        return self.mapping.get(key, *args)

    def get_mapping(self):
        return self.mapping

    def add(self, value):
        require(value, self.value_spec)
        assert value.key is None
        value.key = self.key_counter
        if get_spec_problems(value):
            value.key = None
            raise TypeError(''.join(get_spec_problems(value)))
        self.key_counter += 1
        self.mapping[value.key] = value

