Beispiel #1
0
    def __contains__(self, item, excludeMutating=False, excludeIndexes=False):

        if item is None:
            return False

        kind = self.itsView[self._extent].kind

        if isuuid(item):
            instance = self.itsView.find(item, False)
            if instance is None:
                return kind.isKeyForInstance(item, self._recursive)
            else:
                item = instance

        if self._recursive:
            contains = item.isItemOf(kind)
        else:
            contains = item.itsKind is kind

        if contains:
            if (
                excludeMutating
                and item.isMutating()
                and (item._futureKind is None or not item._futureKind.isKindOf(kind))
            ):
                return False
            return not item.isDeferred()

        return False
    def _xmlValues(self, generator, withSchema, version):

        item = self._item
        kind = item._kind

        for name, value in self._dict.iteritems():
            attribute = kind.getAttribute(name, False, item)
            flags = self._flags.get(name, 0) & Values.SAVEMASK
            attrs = {'id': attribute.itsUUID.str64()}
            if flags:
                attrs['flags'] = str(flags)

            if value is None:
                attrs['name'] = name
                attrs['type'] = 'none'
                generator.startElement('ref', attrs)
                generator.endElement('ref')
            elif value is Empty:
                attrs['name'] = name
                attrs['type'] = 'empty'
                generator.startElement('ref', attrs)
                generator.endElement('ref')
            else:
                if withSchema and isuuid(value):
                    value = self._getRef(name, value)

                if value._isRefs():
                    value._xmlValue(name, item, generator, withSchema, version,
                                    attrs)
                else:
                    self._xmlRef(name, value(), generator, withSchema, version,
                                 attrs)

        return 0
Beispiel #3
0
    def _xmlValues(self, generator, withSchema, version):

        item = self._item
        kind = item._kind

        for name, value in self._dict.iteritems():
            attribute = kind.getAttribute(name, False, item)
            flags = self._flags.get(name, 0) & Values.SAVEMASK
            attrs = { 'id': attribute.itsUUID.str64() }
            if flags:
                attrs['flags'] = str(flags)

            if value is None:
                attrs['name'] = name
                attrs['type'] = 'none'
                generator.startElement('ref', attrs)
                generator.endElement('ref')
            elif value is Empty:
                attrs['name'] = name
                attrs['type'] = 'empty'
                generator.startElement('ref', attrs)
                generator.endElement('ref')
            else:
                if withSchema and isuuid(value):
                    value = self._getRef(name, value)
                    
                if value._isRefs():
                    value._xmlValue(name, item, generator, withSchema,
                                    version, attrs)
                else:
                    self._xmlRef(name, value(), generator, withSchema,
                                 version, attrs)

        return 0
    def readValue(self, itemReader, offset, data, withSchema, view, name,
                  afterLoadHooks):

        value = data[offset]
        if isuuid(value):
            value = ItemRef(value, view)

        return offset + 1, value
Beispiel #5
0
    def readValue(self, itemReader, offset, data, withSchema, view, name,
                  afterLoadHooks):

        value = data[offset]
        if isuuid(value):
            value = ItemRef(value, view)
        
        return offset+1, value
Beispiel #6
0
    def __init__(self, store, uItem, version, item):

        self.store = store
        self.uItem = uItem
        self.version = version

        (self.uKind, self.status, self.uParent, values, x, self.name, self.moduleName, self.className) = item.data

        self.uValues = tuple([uValue for uValue in values.data if isuuid(uValue)])
Beispiel #7
0
    def _prepareSource(self, source):

        if isinstance(source, AbstractSet):
            return source.itsView, source
        elif isinstance(source, Collection):
            return source.getSourceCollection()
        elif isuuid(source[0]):
            return None, source
        else:
            return source[0].itsView, (source[0].itsUUID, source[1])
Beispiel #8
0
    def __init__(self, store, uItem, version, item):

        self.store = store
        self.uItem = uItem
        self.version = version

        (self.uKind, self.status, self.uParent, values, x, self.name,
         self.moduleName, self.className) = item.data

        self.uValues = tuple(
            [uValue for uValue in values.data if isuuid(uValue)])
Beispiel #9
0
 def append(values, value):
     if value is not None:
         if isuuid(value) or isinstance(value, RefList):
             values.append(value)
         elif isitem(value) or isitemref(value):
             values.append(value.itsUUID)
         elif isinstance(value, PersistentCollection):
             values.extend(value._iterKeys())
         elif isinstance(value, AbstractSet):
             values.append(value)
         else:
             raise TypeError, type(value)
Beispiel #10
0
 def append(values, value):
     if value is not None:
         if isuuid(value) or isinstance(value, RefList):
             values.append(value)
         elif isitem(value) or isitemref(value):
             values.append(value.itsUUID)
         elif isinstance(value, PersistentCollection):
             values.extend(value._iterKeys())
         elif isinstance(value, AbstractSet):
             values.append(value)
         else:
             raise TypeError, type(value)
Beispiel #11
0
        def addAttr(attrs, attr, value):

            if value is not None:
                if isuuid(value):
                    attrs[attr + 'Type'] = 'uuid'
                    attrs[attr] = value.str64()
                elif isinstance(attr, str) or isinstance(attr, unicode):
                    attrs[attr] = value.encode('utf-8')
                elif isinstance(attr, Path):
                    attrs[attr + 'Type'] = 'path'
                    attrs[attr] = str(value).encode('utf-8')
                else:
                    raise TypeError, "%s, type: %s" %(value, type(value))
        def addAttr(attrs, attr, value):

            if value is not None:
                if isuuid(value):
                    attrs[attr + 'Type'] = 'uuid'
                    attrs[attr] = value.str64()
                elif isinstance(attr, str) or isinstance(attr, unicode):
                    attrs[attr] = value.encode('utf-8')
                elif isinstance(attr, Path):
                    attrs[attr + 'Type'] = 'path'
                    attrs[attr] = str(value).encode('utf-8')
                else:
                    raise TypeError, "%s, type: %s" % (value, type(value))
    def _xmlRef(self,
                name,
                other,
                generator,
                withSchema,
                version,
                attrs,
                previous=None,
                next=None,
                alias=None):
        def addAttr(attrs, attr, value):

            if value is not None:
                if isuuid(value):
                    attrs[attr + 'Type'] = 'uuid'
                    attrs[attr] = value.str64()
                elif isinstance(attr, str) or isinstance(attr, unicode):
                    attrs[attr] = value.encode('utf-8')
                elif isinstance(attr, Path):
                    attrs[attr + 'Type'] = 'path'
                    attrs[attr] = str(value).encode('utf-8')
                else:
                    raise TypeError, "%s, type: %s" % (value, type(value))

        attrs['type'] = 'uuid'

        addAttr(attrs, 'name', name)
        addAttr(attrs, 'previous', previous)
        addAttr(attrs, 'next', next)
        addAttr(attrs, 'alias', alias)

        if withSchema:
            item = self._item
            otherName = item.itsKind.getOtherName(name, item)
            otherCard = other.getAttributeAspect(otherName, 'cardinality',
                                                 False, None, 'single')
            attrs['otherName'] = otherName
            if otherCard != 'single':
                attrs['otherCard'] = otherCard
            uuid = other._uuid
        elif isuuid(other):
            uuid = other
        else:
            uuid = other.itsUUID

        generator.startElement('ref', attrs)
        generator.characters(uuid.str64())
        generator.endElement('ref')
Beispiel #14
0
    def _sourceChanged(self, source, op, change, sourceOwner, sourceName, other, dirties, actualSource):

        if isinstance(source, AbstractSet):
            if actualSource is not None:
                if source is not actualSource:
                    op = None
            else:
                op = source.sourceChanged(op, change, sourceOwner, sourceName, True, other, dirties)

        elif sourceName == source[1] and (
            isuuid(sourceOwner) and sourceOwner == source[0] or sourceOwner is self.itsView[source[0]]
        ):
            pass
        else:
            op = None

        return op
Beispiel #15
0
    def _xmlRef(self, name, other, generator, withSchema, version, attrs,
                previous=None, next=None, alias=None):

        def addAttr(attrs, attr, value):

            if value is not None:
                if isuuid(value):
                    attrs[attr + 'Type'] = 'uuid'
                    attrs[attr] = value.str64()
                elif isinstance(attr, str) or isinstance(attr, unicode):
                    attrs[attr] = value.encode('utf-8')
                elif isinstance(attr, Path):
                    attrs[attr + 'Type'] = 'path'
                    attrs[attr] = str(value).encode('utf-8')
                else:
                    raise TypeError, "%s, type: %s" %(value, type(value))

        attrs['type'] = 'uuid'

        addAttr(attrs, 'name', name)
        addAttr(attrs, 'previous', previous)
        addAttr(attrs, 'next', next)
        addAttr(attrs, 'alias', alias)

        if withSchema:
            item = self._item
            otherName = item.itsKind.getOtherName(name, item)
            otherCard = other.getAttributeAspect(otherName, 'cardinality',
                                                 False, None, 'single')
            attrs['otherName'] = otherName
            if otherCard != 'single':
                attrs['otherCard'] = otherCard
            uuid = other._uuid
        elif isuuid(other):
            uuid = other
        else:
            uuid = other.itsUUID

        generator.startElement('ref', attrs)
        generator.characters(uuid.str64())
        generator.endElement('ref')
Beispiel #16
0
    def _ref(self, item, name, value, version, flags, withSchema, attribute):

        self.indexes = []
        uValue = UUID()
        self.values.append((name, uValue))
        size = 0

        record = Record(Record.UUID, attribute.itsUUID, Record.BYTE, flags)

        refRecord = Record()
        if withSchema:
            refRecord += (Record.SYMBOL, name)

        if value is None:
            refRecord += (Record.BYTE, (DBItemWriter.NONE | DBItemWriter.REF | DBItemWriter.SINGLE))

        elif value is Empty:
            refRecord += (Record.BYTE, (DBItemWriter.NONE | DBItemWriter.REF | DBItemWriter.LIST))

        elif isuuid(value):
            if withSchema:
                raise AssertionError, "withSchema is True"
            refRecord += (Record.BYTE, DBItemWriter.SINGLE | DBItemWriter.REF, Record.UUID, value)

        elif isitemref(value):
            refRecord += (Record.BYTE, DBItemWriter.SINGLE | DBItemWriter.REF, Record.UUID, value.itsUUID)

        elif value._isRefs():
            attrCard = attribute.c.cardinality
            if attrCard == "list":
                flags = DBItemWriter.LIST | DBItemWriter.REF
                if withSchema:
                    flags |= DBItemWriter.TYPED
                refRecord += (Record.BYTE, flags, Record.UUID, value.uuid)
                if withSchema:
                    refRecord += (Record.SYMBOL, item.itsKind.getOtherName(name, item))
                size += value._saveValues(version)

            elif attrCard == "set":
                refRecord += (Record.BYTE, DBItemWriter.SET | DBItemWriter.REF, Record.STRING, value.makeString(value))

            elif attrCard == "dict":
                flags = DBItemWriter.DICT | DBItemWriter.REF
                if withSchema:
                    flags |= DBItemWriter.TYPED
                refRecord += (Record.BYTE, flags)
                if withSchema:
                    refRecord += (Record.SYMBOL, item.itsKind.getOtherName(name, item))
                refRecord += (Record.SHORT, len(value._dict))
                for key, refList in value._dict.iteritems():
                    refRecord += (Record.UUID_OR_SYMBOL, key, Record.UUID, refList.uuid)
                    if refList._isDirty():
                        size += refList._saveValues(version)

            else:
                raise NotImplementedError, attrCard

            if attrCard != "dict":
                size += self.writeIndexes(refRecord, item, version, value)

        else:
            raise TypeError, value

        record += (Record.RECORD, refRecord, Record.RECORD, Record())

        indexRecord = Record()
        for uuid in self.indexes:
            indexRecord += (Record.UUID, uuid)
        record += (Record.RECORD, indexRecord)

        size += self.store._values.c.saveValue(item.itsUUID, uValue, record)

        return size
Beispiel #17
0
    def iterKeys(self, key, firstValue=Default):

        view = self.itsView

        def append(values, value):
            if value is not None:
                if isuuid(value) or isinstance(value, RefList):
                    values.append(value)
                elif isitem(value) or isitemref(value):
                    values.append(value.itsUUID)
                elif isinstance(value, PersistentCollection):
                    values.extend(value._iterKeys())
                elif isinstance(value, AbstractSet):
                    values.append(value)
                else:
                    raise TypeError, type(value)

        if firstValue is not Default:
            names = self.attribute[1:]
            value = firstValue
        else:
            names = self.attribute
            value = key

        for name in names:
            if isinstance(value, PersistentCollection):
                values = []
                for v in value._iterKeys():
                    append(values, view.findValue(v, name, None))
                value = values
            elif isinstance(value, RefList):
                values = []
                for v in value.iterkeys():
                    append(values, view.findValue(v, name, None))
                value = values
            elif isinstance(value, AbstractSet):
                values = []
                for v in value.iterkeys():
                    append(values, view.findValue(v, name, None))
                value = values
            elif isinstance(value, list):
                values = []
                for v in value:
                    if isuuid(v):
                        append(values, view.findValue(v, name, None))
                    else:
                        for k in v.iterkeys():
                            append(values, view.findValue(k, name, None))
                value = values
            else:
                value = view.findValue(value, name, None)
                if value is None:
                    break
                if isitemref(value) or isitem(value):
                    value = value.itsUUID
                elif not (isuuid(value) or
                          isinstance(value, (PersistentCollection,
                                             RefList, AbstractSet))):
                    value = None
                    break

        if value is None:
            return []

        if isuuid(value):
            return [value]

        if isitemref(value) or isitem(value):
            return [value.itsUUID]

        if isinstance(value, PersistentCollection):
            return value._iterKeys()

        if isinstance(value, RefList):
            return value.iterkeys()

        return value
    def _dispatchHistory(self, history, refreshes, oldVersion, newVersion):

        refs = self.store._refs

        def dirtyNames():
            if kind is None:
                names = ()
            else:
                names = kind._nameTuple(dirties)
            if status & CItem.KDIRTY:
                names += ('itsKind',)
            return names

        for uItem, version, uKind, status, uParent, pKind, dirties in history:

            if not (pKind is None or pKind == DBItemWriter.NOITEM):
                kind = self.find(pKind)
                if kind is not None and kind.c.notify:
                    kind.extent._collectionChanged('refresh', 'collection',
                                                   'extent', uItem, ())

            kind = self.find(uKind)
            if kind is not None:
                names = dirtyNames()
                if kind.c.notify:
                    kind.extent._collectionChanged('refresh', 'collection',
                                                   'extent', uItem, names)

                watchers = self.findValue(uItem, 'watchers', None, version)
                if watchers:
                    isNew = (status & CItem.NEW) != 0
                    for attribute, watchers in watchers.iteritems():
                        if watchers:
                            if isuuid(attribute):  # item watchers
                                for watcher in watchers:
                                    if watcher is not None:
                                        watcher('refresh', uItem, names)
                            elif isNew or attribute in names:
                                value = self.findValue(uItem, attribute, None,
                                                       version)
                                if isinstance(value, RefList):
                                    value = value.uuid
                                else:
                                    continue
                                for uRef in refs.iterHistory(self, value, version - 1, version, True):
                                    if uRef in refreshes:
                                        for watcher in watchers:
                                            if watcher is not None:
                                                watcher('refresh', 'collection', uItem, attribute, uRef, ())

                for name in kind._iterNotifyAttributes():
                    value = self.findValue(uItem, name, None, version)
                    if isinstance(value, RefList):
                        otherName = kind.getOtherName(name, None)
                        for uRef in value.iterkeys():
                            watchers = self.findValue(uRef, 'watchers', None, version)
                            if watchers:
                                watchers = watchers.get(otherName, None)
                                if watchers:
                                    for watcher in watchers:
                                        if watcher is not None:
                                            watcher('changed', 'notification', uRef, otherName, uItem, names)

                watchers = self._watchers
                if watchers and uItem in watchers:
                    watchers = watchers[uItem].get(uItem)
                    if watchers:
                        for watcher in watchers:
                            watcher('refresh', uItem, names)
    def exportProcess(self, dom, key, element, changes, keys):

        view = self.itsView
        kind = view.kindForKey(key)

        attributes = changes.get(key, ())
        if attributes:
            attributes = tuple(attributes[0])

        if keys is None:
            keys = set()

        if key in keys:
            dom.openElement(element, kind.itsName, uuid=key.str64())
            dom.closeElement(element, kind.itsName)
            return None

        keys.add(key)

        pairs = [(name, Nil) for name in attributes]
        pairs.append((pim.Stamp.stamp_types.name, ()))
        values = list(view.findValues(key, *pairs))

        stampClasses = values.pop()
        elementName, classes = self._getElementName(kind, stampClasses)

        attrs = {'class': classes, 'uuid': key.str64()}
        item = dom.openElement(element, elementName, **attrs)

        for attrName, attrValue in izip(attributes, values):
            if attrValue is Nil:
                dom.openElement(item, 'value', name=attrName, status='nil')
                dom.closeElement(item, 'value')

            else:
                attribute = kind.getAttribute(attrName)
                attrType = attribute.getAspect('type')
                cardinality = attribute.getAspect('cardinality')
                otherName = attribute.getAspect('otherName', None)

                if otherName:
                    value = dom.openElement(item, 'value', name=attrName)

                    if isuuid(attrValue):
                        self.exportProcess(dom, attrValue, value, changes,
                                           keys)
                    elif cardinality == 'list':
                        for attrKey in attrValue.iterkeys():
                            self.exportProcess(dom, attrKey, value, changes,
                                               keys)

                    dom.closeElement(item, 'value')
                else:
                    if cardinality == 'single':
                        if isitemref(attrValue):
                            value = dom.openElement(item,
                                                    'value',
                                                    name=attrName)
                            attrValue = attrValue.itsUUID
                            self.exportProcess(dom, attrValue, value, changes,
                                               keys)
                            dom.closeElement(item, 'value')
                        else:
                            mimetype, encoding, attrValue = utility.serializeLiteral(
                                self.itsView, attrValue, attrType)

                            attrs = {'name': attrName}
                            if mimetype:
                                attrs['mimetype'] = mimetype
                            if encoding:
                                attrs['encoding'] = encoding
                                attrValue = unicode(attrValue, encoding)
                            else:
                                attrValue = unicode(attrValue, 'utf-8')

                            dom.openElement(item,
                                            'value',
                                            content=attrValue,
                                            **attrs)
                            dom.closeElement(item, 'value')

                    elif cardinality == 'list':
                        value = dom.openElement(item, 'value', name=attrName)
                        for v in attrValue:
                            attrs = {}
                            mimetype, encoding, v = utility.serializeLiteral(
                                self.itsView, v, attrType)

                            if mimetype:
                                attrs['mimetype'] = mimetype
                            if encoding:
                                attrs['encoding'] = encoding
                                v = unicode(v, encoding)
                            else:
                                v = unicode(v, 'utf-8')

                            dom.openElement(value, 'value', content=v, **attrs)
                            dom.closeElement(value, 'value')
                        dom.closeElement(item, 'value')

        dom.closeElement(element, elementName)
Beispiel #20
0
    def exportProcess(self, dom, key, element, changes, keys):

        view = self.itsView
        kind = view.kindForKey(key)

        attributes = changes.get(key, ())
        if attributes:
            attributes = tuple(attributes[0])

        if keys is None:
            keys = set()

        if key in keys:
            dom.openElement(element, kind.itsName, uuid=key.str64())
            dom.closeElement(element, kind.itsName)
            return None

        keys.add(key)

        pairs = [(name, Nil) for name in attributes]
        pairs.append((pim.Stamp.stamp_types.name, ()))
        values = list(view.findValues(key, *pairs))

        stampClasses = values.pop()
        elementName, classes = self._getElementName(kind, stampClasses)

        attrs = { 'class': classes, 'uuid': key.str64() }
        item = dom.openElement(element, elementName, **attrs)

        for attrName, attrValue in izip(attributes, values):
            if attrValue is Nil:
                dom.openElement(item, 'value', name=attrName, status='nil')
                dom.closeElement(item, 'value')

            else:
                attribute = kind.getAttribute(attrName) 
                attrType = attribute.getAspect('type')
                cardinality = attribute.getAspect('cardinality')
                otherName = attribute.getAspect('otherName', None)

                if otherName:
                    value = dom.openElement(item, 'value', name=attrName)

                    if isuuid(attrValue):
                        self.exportProcess(dom, attrValue, value,
                                           changes, keys)
                    elif cardinality == 'list':
                        for attrKey in attrValue.iterkeys():
                            self.exportProcess(dom, attrKey, value,
                                               changes, keys)

                    dom.closeElement(item, 'value')
                else:
                    if cardinality == 'single':
                        if isitemref(attrValue):
                            value = dom.openElement(item, 'value', name=attrName)
                            attrValue = attrValue.itsUUID
                            self.exportProcess(dom, attrValue, value,
                                               changes, keys)
                            dom.closeElement(item, 'value')
                        else:
                            mimetype, encoding, attrValue = utility.serializeLiteral(self.itsView, attrValue, attrType)

                            attrs = { 'name': attrName }
                            if mimetype:
                                attrs['mimetype'] = mimetype
                            if encoding:
                                attrs['encoding'] = encoding
                                attrValue = unicode(attrValue, encoding)
                            else:
                                attrValue = unicode(attrValue, 'utf-8')

                            dom.openElement(item, 'value',
                                            content=attrValue, **attrs)
                            dom.closeElement(item, 'value')

                    elif cardinality == 'list':
                        value = dom.openElement(item, 'value', name=attrName)
                        for v in attrValue:
                            attrs = {}
                            mimetype, encoding, v = utility.serializeLiteral(self.itsView, v, attrType)

                            if mimetype:
                                attrs['mimetype'] = mimetype
                            if encoding:
                                attrs['encoding'] = encoding
                                v = unicode(v, encoding)
                            else:
                                v = unicode(v, 'utf-8')

                            dom.openElement(value, 'value', content=v, **attrs)
                            dom.closeElement(value, 'value')
                        dom.closeElement(item, 'value')

        dom.closeElement(element, elementName)
Beispiel #21
0
    def _ref(self, item, name, value, version, flags, withSchema, attribute):

        self.indexes = []
        uValue = UUID()
        self.values.append((name, uValue))
        size = 0

        record = Record(Record.UUID, attribute.itsUUID, Record.BYTE, flags)

        refRecord = Record()
        if withSchema:
            refRecord += (Record.SYMBOL, name)

        if value is None:
            refRecord += (Record.BYTE, (DBItemWriter.NONE | DBItemWriter.REF
                                        | DBItemWriter.SINGLE))

        elif value is Empty:
            refRecord += (Record.BYTE, (DBItemWriter.NONE | DBItemWriter.REF
                                        | DBItemWriter.LIST))

        elif isuuid(value):
            if withSchema:
                raise AssertionError, 'withSchema is True'
            refRecord += (Record.BYTE, DBItemWriter.SINGLE | DBItemWriter.REF,
                          Record.UUID, value)

        elif isitemref(value):
            refRecord += (Record.BYTE, DBItemWriter.SINGLE | DBItemWriter.REF,
                          Record.UUID, value.itsUUID)

        elif value._isRefs():
            attrCard = attribute.c.cardinality
            if attrCard == 'list':
                flags = DBItemWriter.LIST | DBItemWriter.REF
                if withSchema:
                    flags |= DBItemWriter.TYPED
                refRecord += (Record.BYTE, flags, Record.UUID, value.uuid)
                if withSchema:
                    refRecord += (Record.SYMBOL,
                                  item.itsKind.getOtherName(name, item))
                size += value._saveValues(version)

            elif attrCard == 'set':
                refRecord += (Record.BYTE, DBItemWriter.SET | DBItemWriter.REF,
                              Record.STRING, value.makeString(value))

            elif attrCard == 'dict':
                flags = DBItemWriter.DICT | DBItemWriter.REF
                if withSchema:
                    flags |= DBItemWriter.TYPED
                refRecord += (Record.BYTE, flags)
                if withSchema:
                    refRecord += (Record.SYMBOL,
                                  item.itsKind.getOtherName(name, item))
                refRecord += (Record.SHORT, len(value._dict))
                for key, refList in value._dict.iteritems():
                    refRecord += (Record.UUID_OR_SYMBOL, key, Record.UUID,
                                  refList.uuid)
                    if refList._isDirty():
                        size += refList._saveValues(version)

            else:
                raise NotImplementedError, attrCard

            if attrCard != 'dict':
                size += self.writeIndexes(refRecord, item, version, value)

        else:
            raise TypeError, value

        record += (Record.RECORD, refRecord, Record.RECORD, Record())

        indexRecord = Record()
        for uuid in self.indexes:
            indexRecord += (Record.UUID, uuid)
        record += (Record.RECORD, indexRecord)

        size += self.store._values.c.saveValue(item.itsUUID, uValue, record)

        return size
Beispiel #22
0
    def iterKeys(self, key, firstValue=Default):

        view = self.itsView

        def append(values, value):
            if value is not None:
                if isuuid(value) or isinstance(value, RefList):
                    values.append(value)
                elif isitem(value) or isitemref(value):
                    values.append(value.itsUUID)
                elif isinstance(value, PersistentCollection):
                    values.extend(value._iterKeys())
                elif isinstance(value, AbstractSet):
                    values.append(value)
                else:
                    raise TypeError, type(value)

        if firstValue is not Default:
            names = self.attribute[1:]
            value = firstValue
        else:
            names = self.attribute
            value = key

        for name in names:
            if isinstance(value, PersistentCollection):
                values = []
                for v in value._iterKeys():
                    append(values, view.findValue(v, name, None))
                value = values
            elif isinstance(value, RefList):
                values = []
                for v in value.iterkeys():
                    append(values, view.findValue(v, name, None))
                value = values
            elif isinstance(value, AbstractSet):
                values = []
                for v in value.iterkeys():
                    append(values, view.findValue(v, name, None))
                value = values
            elif isinstance(value, list):
                values = []
                for v in value:
                    if isuuid(v):
                        append(values, view.findValue(v, name, None))
                    else:
                        for k in v.iterkeys():
                            append(values, view.findValue(k, name, None))
                value = values
            else:
                value = view.findValue(value, name, None)
                if value is None:
                    break
                if isitemref(value) or isitem(value):
                    value = value.itsUUID
                elif not (isuuid(value) or isinstance(
                        value, (PersistentCollection, RefList, AbstractSet))):
                    value = None
                    break

        if value is None:
            return []

        if isuuid(value):
            return [value]

        if isitemref(value) or isitem(value):
            return [value.itsUUID]

        if isinstance(value, PersistentCollection):
            return value._iterKeys()

        if isinstance(value, RefList):
            return value.iterkeys()

        return value