def readItem(self, view, afterLoadHooks): status = self.status withSchema = (status & Item.CORESCHEMA) != 0 isContainer = (status & Item.CONTAINER) != 0 status &= Item.CORESCHEMA kind = self._kind(self.uKind, withSchema, view, afterLoadHooks) parent = self._parent(self.uParent, withSchema, view, afterLoadHooks) cls = self._class(self.moduleName, self.className, withSchema, kind, view, afterLoadHooks) values = Values(None) references = References(None) self._values(values, references, self.uValues, kind, withSchema, view, afterLoadHooks) instance = view._reuseItemInstance(self.uItem) if instance is not None: if cls is not type(instance): instance.__class__ = cls item = self.item = instance status |= item._status & item.PINNED else: item = self.item = cls.__new__(cls) item._fillItem(self.name, parent, kind, uuid=self.uItem, values=values, references=references, afterLoadHooks=afterLoadHooks, version=self.version, status=status, update=False) if isContainer: item._children = view._createChildren(item, False) values._setItem(item) references._setItem(item) for name, value in values.iteritems(): if isinstance(value, ItemValue): value._setOwner(item, name) if kind is not None: afterLoadHooks.append(lambda view: kind._setupClass(cls)) if hasattr(cls, 'onItemLoad'): afterLoadHooks.append(item.onItemLoad) return item
class ItemHandler(ValueHandler): """ A SAX ContentHandler implementation responsible for loading items. """ def __init__(self, repository, parent, afterLoadHooks, new): super(ItemHandler, self).__init__(repository) self.loading = repository.isLoading() self.parent = parent self.afterLoadHooks = afterLoadHooks self.item = None self.new = new self.values = None self.references = None def refStart(self, itemHandler, attrs): if self.tags[-1] == 'item': name = attrs['name'] attribute = self.getAttribute(name) self.attributes.append(attribute) flags = attrs.get('flags', None) if flags is not None: flags = int(flags) self.references._setFlags(name, flags) readOnly = flags & Values.READONLY else: readOnly = False cardinality = self.getCardinality(attribute, attrs) if cardinality != 'single': if cardinality == 'dict': self.repository.logger.warning("Warning, 'dict' cardinality for reference attribute %s on %s is deprecated, use 'list' instead", name, self.name or self.uuid) self._setupRefList(name, attribute, readOnly, attrs) def _setupRefList(self, name, attribute, readOnly, attrs): refList = None otherName = self.getOtherName(name, attribute, attrs) if 'uuid' in attrs: uuid = UUID(attrs['uuid']) else: uuid = None if self.update and attrs.get('operation') == 'append': refList = self.item._references.get(name) if refList is None: refList = self.repository._createRefList(None, name, otherName, True, readOnly, self.new, uuid) self.collections.append(refList) def itemStart(self, itemHandler, attrs): super(ItemHandler, self).itemStart(itemHandler, attrs) if self.values is None: self.values = Values(None) if self.references is None: self.references = References(None) self.refs = [] self.name = None self.cls = None self.parentRef = None self.isContainer = False self.uuid = UUID(attrs.get('uuid')) self.version = int(attrs.get('version', '0')) self.update = update = attrs.get('update') self.delete = delete = attrs.get('delete') def _find(spec): typeAttr = attrs.get('type', 'path') if typeAttr == 'path': item = self.parent.find(Path(spec)) elif typeAttr == 'uuid': item = self.parent.find(UUID(spec)) else: raise TypeError, typeAttr if item is None: raise NoSuchItemError, (spec, self.version) return item if update is not None: item = _find(update) elif delete is not None: item = _find(delete) else: item = None if item is not None: self.item = item self.cls = type(item) self.version = item._version self.name = item.itsName self.kind = item.itsKind self.uuid = item.itsUUID self.parent = item.itsParent def itemEnd(self, itemHandler, attrs): from repository.item.Item import Item if self.withSchema: status = Item.CORESCHEMA else: status = 0 cls = self.cls if cls is None: if self.kind is None: cls = Item else: cls = self.kind.getItemClass() instance = self.repository._reuseItemInstance(self.uuid) if instance is not None: if cls is not type(instance): raise TypeError, 'Class for item has changed from %s to %s' %(type(instance), cls) item = self.item = instance status |= item._status & item.PINNED instance = None elif self.update or self.delete: item = self.item values = item._values references = item._references for name, value in self.values.iteritems(): values[name] = value item.setDirty(Item.VDIRTY, name, values, noMonitors=True) self.values = values for name, value in self.references.iteritems(): if not isinstance(value, dict): dirty = Item.VDIRTY item.setAttributeValue(name, value, references, None, False) else: dirty = Item.RDIRTY references[name] = value item.setDirty(dirty, name, references, noMonitors=True) self.references = references status = item._status | Item.NDIRTY else: item = self.item = cls.__new__(cls) item._fillItem(self.name, self.parent, self.kind, uuid = self.uuid, values = self.values, references = self.references, afterLoadHooks = self.afterLoadHooks, version = self.version, status = status, update = self.update) if self.isContainer and item._children is None: item._children = self.repository._createChildren(item, self.new) if not (self.update or self.delete): self.repository._registerItem(item) self.values._setItem(item) self.references._setItem(item) for attribute, value in self.values.iteritems(): if isinstance(value, ItemValue): value._setOwner(item, attribute) for refArgs in self.refs: other = refArgs._setItem(item) if self.loading: refArgs._setRef() elif other is None: self.afterLoadHooks.append(refArgs._setValue) else: refArgs._setValue(self.repository) self.afterLoadHooks.append(self.setupClass) if hasattr(cls, 'onItemLoad'): self.afterLoadHooks.append(item.onItemLoad) if self.delete: self.afterLoadHooks.append(item.delete) def setupClass(self, view): if self.update and isinstance(self.item, Kind): self.item.flushCaches('attributes', True) elif self.kind is not None: self.kind._setupClass(type(self.item)) def kindEnd(self, itemHandler, attrs): assert not self.item super(ItemHandler, self).kindEnd(itemHandler, attrs) if self.kind is None: if self.withSchema: self.afterLoadHooks.append(self._setKind) else: raise ValueError, "While loading %s, kind %s not found" %(self.name or self.uuid, self.kindRef) def _setKind(self, view): if self.item._kind is None: self.kind = view.find(self.kindRef) if self.kind is None: raise ValueError, 'Kind %s not found' %(self.kindRef) else: self.item._kind = self.kind def parentEnd(self, itemHandler, attrs): if attrs['type'] == 'uuid': self.parentRef = UUID(self.data) else: self.parentRef = Path(self.data) self.isContainer = attrs.get('container', 'False') == 'True' self.parent = self.repository.find(self.parentRef) if self.parent is None: self.afterLoadHooks.append(self._move) def _move(self, view): if self.item._parent is None: self.parent = view.find(self.parentRef) if self.parent is None: raise ValueError, 'Parent %s not found' %(self.parentRef) else: self.item.move(self.parent) def classEnd(self, itemHandler, attrs): self.cls = ClassLoader.loadClass(self.data, attrs['module']) def nameEnd(self, itemHandler, attrs): self.name = self.data def refEnd(self, itemHandler, attrs): if self.tags[-1] == 'item': attribute = self.attributes.pop() cardinality = self.getCardinality(attribute, attrs) otherCard = attrs.get('otherCard', None) else: cardinality = 'single' otherCard = self.tagAttrs[-1].get('otherCard', None) if cardinality == 'single': # cardinality of tag typeName = attrs.get('type', 'path') if typeName == 'path': ref = Path(self.data) elif typeName == 'none': self.references[attrs['name']] = None return else: ref = UUID(self.data) if self.collections: refList = self.collections[-1] self.refs.append(RefArgs(refList._name, None, refList._otherName, ref, otherCard=otherCard, otherAlias=attrs.get('otherAlias'), previous=self.refName(attrs, 'previous'), next=self.refName(attrs, 'next'), alias=attrs.get('alias'))) else: name = attrs['name'] otherName = self.getOtherName(name, self.getAttribute(name), attrs) self.refs.append(RefArgs(name, None, otherName, ref, otherCard=otherCard, otherAlias=attrs.get('otherAlias'))) else: value = self.collections.pop() self.references[attrs['name']] = value if value._indexes: self.afterLoadHooks.append(value._restoreIndexes) def indexEnd(self, itemHandler, attrs): if not self.collections: raise ValueError, self.tagAttrs[-1]['name'] refList = self.collections[-1] kwds = attrs.copy() del kwds['type'] del kwds['name'] refList.addIndex(attrs['name'], attrs['type'], **kwds) def refName(self, attrs, attr): try: return self.makeValue(attrs.get(attr + 'Type', 'str'), attrs[attr]) except KeyError: return None def getOtherName(self, name, attribute, attrs): otherName = attrs.get('otherName') if otherName is None and attribute is not None: otherName = self.kind.getOtherName(name, None, None, None) if otherName is None: raise TypeError, 'Undefined other endpoint for %s.%s of kind %s' %(self.name or self.uuid, name, self.kind.itsPath) return otherName
class ItemHandler(ValueHandler): """ A SAX ContentHandler implementation responsible for loading items. """ def __init__(self, repository, parent, afterLoadHooks, new): super(ItemHandler, self).__init__(repository) self.loading = repository.isLoading() self.parent = parent self.afterLoadHooks = afterLoadHooks self.item = None self.new = new self.values = None self.references = None def refStart(self, itemHandler, attrs): if self.tags[-1] == 'item': name = attrs['name'] attribute = self.getAttribute(name) self.attributes.append(attribute) flags = attrs.get('flags', None) if flags is not None: flags = int(flags) self.references._setFlags(name, flags) readOnly = flags & Values.READONLY else: readOnly = False cardinality = self.getCardinality(attribute, attrs) if cardinality != 'single': if cardinality == 'dict': self.repository.logger.warning( "Warning, 'dict' cardinality for reference attribute %s on %s is deprecated, use 'list' instead", name, self.name or self.uuid) self._setupRefList(name, attribute, readOnly, attrs) def _setupRefList(self, name, attribute, readOnly, attrs): refList = None otherName = self.getOtherName(name, attribute, attrs) if 'uuid' in attrs: uuid = UUID(attrs['uuid']) else: uuid = None if self.update and attrs.get('operation') == 'append': refList = self.item._references.get(name) if refList is None: refList = self.repository._createRefList(None, name, otherName, True, readOnly, self.new, uuid) self.collections.append(refList) def itemStart(self, itemHandler, attrs): super(ItemHandler, self).itemStart(itemHandler, attrs) if self.values is None: self.values = Values(None) if self.references is None: self.references = References(None) self.refs = [] self.name = None self.cls = None self.parentRef = None self.isContainer = False self.uuid = UUID(attrs.get('uuid')) self.version = int(attrs.get('version', '0')) self.update = update = attrs.get('update') self.delete = delete = attrs.get('delete') def _find(spec): typeAttr = attrs.get('type', 'path') if typeAttr == 'path': item = self.parent.find(Path(spec)) elif typeAttr == 'uuid': item = self.parent.find(UUID(spec)) else: raise TypeError, typeAttr if item is None: raise NoSuchItemError, (spec, self.version) return item if update is not None: item = _find(update) elif delete is not None: item = _find(delete) else: item = None if item is not None: self.item = item self.cls = type(item) self.version = item._version self.name = item.itsName self.kind = item.itsKind self.uuid = item.itsUUID self.parent = item.itsParent def itemEnd(self, itemHandler, attrs): from repository.item.Item import Item if self.withSchema: status = Item.CORESCHEMA else: status = 0 cls = self.cls if cls is None: if self.kind is None: cls = Item else: cls = self.kind.getItemClass() instance = self.repository._reuseItemInstance(self.uuid) if instance is not None: if cls is not type(instance): raise TypeError, 'Class for item has changed from %s to %s' % ( type(instance), cls) item = self.item = instance status |= item._status & item.PINNED instance = None elif self.update or self.delete: item = self.item values = item._values references = item._references for name, value in self.values.iteritems(): values[name] = value item.setDirty(Item.VDIRTY, name, values, noMonitors=True) self.values = values for name, value in self.references.iteritems(): if not isinstance(value, dict): dirty = Item.VDIRTY item.setAttributeValue(name, value, references, None, False) else: dirty = Item.RDIRTY references[name] = value item.setDirty(dirty, name, references, noMonitors=True) self.references = references status = item._status | Item.NDIRTY else: item = self.item = cls.__new__(cls) item._fillItem(self.name, self.parent, self.kind, uuid=self.uuid, values=self.values, references=self.references, afterLoadHooks=self.afterLoadHooks, version=self.version, status=status, update=self.update) if self.isContainer and item._children is None: item._children = self.repository._createChildren(item, self.new) if not (self.update or self.delete): self.repository._registerItem(item) self.values._setItem(item) self.references._setItem(item) for attribute, value in self.values.iteritems(): if isinstance(value, ItemValue): value._setOwner(item, attribute) for refArgs in self.refs: other = refArgs._setItem(item) if self.loading: refArgs._setRef() elif other is None: self.afterLoadHooks.append(refArgs._setValue) else: refArgs._setValue(self.repository) self.afterLoadHooks.append(self.setupClass) if hasattr(cls, 'onItemLoad'): self.afterLoadHooks.append(item.onItemLoad) if self.delete: self.afterLoadHooks.append(item.delete) def setupClass(self, view): if self.update and isinstance(self.item, Kind): self.item.flushCaches('attributes', True) elif self.kind is not None: self.kind._setupClass(type(self.item)) def kindEnd(self, itemHandler, attrs): assert not self.item super(ItemHandler, self).kindEnd(itemHandler, attrs) if self.kind is None: if self.withSchema: self.afterLoadHooks.append(self._setKind) else: raise ValueError, "While loading %s, kind %s not found" % ( self.name or self.uuid, self.kindRef) def _setKind(self, view): if self.item._kind is None: self.kind = view.find(self.kindRef) if self.kind is None: raise ValueError, 'Kind %s not found' % (self.kindRef) else: self.item._kind = self.kind def parentEnd(self, itemHandler, attrs): if attrs['type'] == 'uuid': self.parentRef = UUID(self.data) else: self.parentRef = Path(self.data) self.isContainer = attrs.get('container', 'False') == 'True' self.parent = self.repository.find(self.parentRef) if self.parent is None: self.afterLoadHooks.append(self._move) def _move(self, view): if self.item._parent is None: self.parent = view.find(self.parentRef) if self.parent is None: raise ValueError, 'Parent %s not found' % (self.parentRef) else: self.item.move(self.parent) def classEnd(self, itemHandler, attrs): self.cls = ClassLoader.loadClass(self.data, attrs['module']) def nameEnd(self, itemHandler, attrs): self.name = self.data def refEnd(self, itemHandler, attrs): if self.tags[-1] == 'item': attribute = self.attributes.pop() cardinality = self.getCardinality(attribute, attrs) otherCard = attrs.get('otherCard', None) else: cardinality = 'single' otherCard = self.tagAttrs[-1].get('otherCard', None) if cardinality == 'single': # cardinality of tag typeName = attrs.get('type', 'path') if typeName == 'path': ref = Path(self.data) elif typeName == 'none': self.references[attrs['name']] = None return else: ref = UUID(self.data) if self.collections: refList = self.collections[-1] self.refs.append( RefArgs(refList._name, None, refList._otherName, ref, otherCard=otherCard, otherAlias=attrs.get('otherAlias'), previous=self.refName(attrs, 'previous'), next=self.refName(attrs, 'next'), alias=attrs.get('alias'))) else: name = attrs['name'] otherName = self.getOtherName(name, self.getAttribute(name), attrs) self.refs.append( RefArgs(name, None, otherName, ref, otherCard=otherCard, otherAlias=attrs.get('otherAlias'))) else: value = self.collections.pop() self.references[attrs['name']] = value if value._indexes: self.afterLoadHooks.append(value._restoreIndexes) def indexEnd(self, itemHandler, attrs): if not self.collections: raise ValueError, self.tagAttrs[-1]['name'] refList = self.collections[-1] kwds = attrs.copy() del kwds['type'] del kwds['name'] refList.addIndex(attrs['name'], attrs['type'], **kwds) def refName(self, attrs, attr): try: return self.makeValue(attrs.get(attr + 'Type', 'str'), attrs[attr]) except KeyError: return None def getOtherName(self, name, attribute, attrs): otherName = attrs.get('otherName') if otherName is None and attribute is not None: otherName = self.kind.getOtherName(name, None, None, None) if otherName is None: raise TypeError, 'Undefined other endpoint for %s.%s of kind %s' % ( self.name or self.uuid, name, self.kind.itsPath) return otherName