[Commits] (vajda) - moved alias functionality from RefDict to LinkedMap

commits at osafoundation.org commits at osafoundation.org
Thu Sep 2 10:34:30 PDT 2004


Commit by: vajda
Modified files:
chandler/repository/item/Item.py 1.156 1.157
chandler/repository/item/ItemHandler.py 1.45 1.46
chandler/repository/item/ItemRef.py 1.88 1.89
chandler/repository/item/Values.py 1.16 1.17
chandler/repository/persistence/FileRepository.py 1.29 1.30
chandler/repository/persistence/PackHandler.py 1.16 1.17
chandler/repository/persistence/Repository.py 1.81 1.82
chandler/repository/persistence/RepositoryError.py 1.2 1.3
chandler/repository/persistence/RepositoryView.py 1.6 1.7
chandler/repository/persistence/XMLRefDict.py 1.3 1.4
chandler/repository/persistence/XMLRepository.py 1.79 1.80
chandler/repository/persistence/XMLRepositoryView.py 1.52 1.53
chandler/repository/remote/RemoteRepository.py 1.3 1.4
chandler/repository/tests/RepositoryTestCase.py 1.13 1.14
chandler/repository/tests/TestItems.py 1.11 1.12
chandler/repository/tests/TestMove.py 1.1 1.2
chandler/repository/tests/TestRepository.py 1.8 1.9
chandler/repository/util/LinkedMap.py 1.13 1.14
chandler/repository/util/SAX.py 1.4 1.5

Log message:
   - moved alias functionality from RefDict to LinkedMap
   - roots, children and ref collections now use same storage
   - eliminated SDIRTY bit, introduced NDIRTY bit


ViewCVS links:
http://cvs.osafoundation.org/index.cgi/chandler/repository/item/Item.py.diff?r1=text&tr1=1.156&r2=text&tr2=1.157
http://cvs.osafoundation.org/index.cgi/chandler/repository/item/ItemHandler.py.diff?r1=text&tr1=1.45&r2=text&tr2=1.46
http://cvs.osafoundation.org/index.cgi/chandler/repository/item/ItemRef.py.diff?r1=text&tr1=1.88&r2=text&tr2=1.89
http://cvs.osafoundation.org/index.cgi/chandler/repository/item/Values.py.diff?r1=text&tr1=1.16&r2=text&tr2=1.17
http://cvs.osafoundation.org/index.cgi/chandler/repository/persistence/FileRepository.py.diff?r1=text&tr1=1.29&r2=text&tr2=1.30
http://cvs.osafoundation.org/index.cgi/chandler/repository/persistence/PackHandler.py.diff?r1=text&tr1=1.16&r2=text&tr2=1.17
http://cvs.osafoundation.org/index.cgi/chandler/repository/persistence/Repository.py.diff?r1=text&tr1=1.81&r2=text&tr2=1.82
http://cvs.osafoundation.org/index.cgi/chandler/repository/persistence/RepositoryError.py.diff?r1=text&tr1=1.2&r2=text&tr2=1.3
http://cvs.osafoundation.org/index.cgi/chandler/repository/persistence/RepositoryView.py.diff?r1=text&tr1=1.6&r2=text&tr2=1.7
http://cvs.osafoundation.org/index.cgi/chandler/repository/persistence/XMLRefDict.py.diff?r1=text&tr1=1.3&r2=text&tr2=1.4
http://cvs.osafoundation.org/index.cgi/chandler/repository/persistence/XMLRepository.py.diff?r1=text&tr1=1.79&r2=text&tr2=1.80
http://cvs.osafoundation.org/index.cgi/chandler/repository/persistence/XMLRepositoryView.py.diff?r1=text&tr1=1.52&r2=text&tr2=1.53
http://cvs.osafoundation.org/index.cgi/chandler/repository/remote/RemoteRepository.py.diff?r1=text&tr1=1.3&r2=text&tr2=1.4
http://cvs.osafoundation.org/index.cgi/chandler/repository/tests/RepositoryTestCase.py.diff?r1=text&tr1=1.13&r2=text&tr2=1.14
http://cvs.osafoundation.org/index.cgi/chandler/repository/tests/TestItems.py.diff?r1=text&tr1=1.11&r2=text&tr2=1.12
http://cvs.osafoundation.org/index.cgi/chandler/repository/tests/TestMove.py.diff?r1=text&tr1=1.1&r2=text&tr2=1.2
http://cvs.osafoundation.org/index.cgi/chandler/repository/tests/TestRepository.py.diff?r1=text&tr1=1.8&r2=text&tr2=1.9
http://cvs.osafoundation.org/index.cgi/chandler/repository/util/LinkedMap.py.diff?r1=text&tr1=1.13&r2=text&tr2=1.14
http://cvs.osafoundation.org/index.cgi/chandler/repository/util/SAX.py.diff?r1=text&tr1=1.4&r2=text&tr2=1.5

Index: chandler/repository/tests/RepositoryTestCase.py
diff -u chandler/repository/tests/RepositoryTestCase.py:1.13 chandler/repository/tests/RepositoryTestCase.py:1.14
--- chandler/repository/tests/RepositoryTestCase.py:1.13	Wed Sep  1 15:35:32 2004
+++ chandler/repository/tests/RepositoryTestCase.py	Thu Sep  2 10:34:26 2004
@@ -1,8 +1,8 @@
 """
 A base class for repository testing
 """
-__revision__  = "$Revision: 1.13 $"
-__date__      = "$Date: 2004/09/01 22:35:32 $"
+__revision__  = "$Revision: 1.14 $"
+__date__      = "$Date: 2004/09/02 17:34:26 $"
 __copyright__ = "Copyright (c) 2003 Open Source Applications Foundation"
 __license__   = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
 
@@ -99,7 +99,7 @@
 
     # Repository specific assertions
     def assertIsRoot(self, item):
-        self.assert_(item in self.rep.getRoots())
+        self.assert_(item in list(self.rep.iterRoots()))
 
     def assertItemPathEqual(self, item, string):
         self.assertEqual(str(item.itsPath), string)

Index: chandler/repository/item/Values.py
diff -u chandler/repository/item/Values.py:1.16 chandler/repository/item/Values.py:1.17
--- chandler/repository/item/Values.py:1.16	Mon Aug 30 14:27:15 2004
+++ chandler/repository/item/Values.py	Thu Sep  2 10:34:25 2004
@@ -1,6 +1,6 @@
 
-__revision__  = "$Revision: 1.16 $"
-__date__      = "$Date: 2004/08/30 21:27:15 $"
+__revision__  = "$Revision: 1.17 $"
+__date__      = "$Date: 2004/09/02 17:34:25 $"
 __copyright__ = "Copyright (c) 2002 Open Source Applications Foundation"
 __license__   = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
 
@@ -252,6 +252,20 @@
                 value._xmlValue(key, item, generator, withSchema, version,
                                 attrs, mode)
 
+    def _clearDirties(self):
+
+        try:
+            for key, flags in self._flags.iteritems():
+                if flags & Values.DIRTY:
+                    self._flags[key] &= ~Values.DIRTY
+
+                    value = self.get(key)
+                    if value is not None:
+                        value._clearDirties()
+                        
+        except AttributeError:
+            pass
+
     def _isRefDict(self):
 
         return False

Index: chandler/repository/persistence/RepositoryError.py
diff -u chandler/repository/persistence/RepositoryError.py:1.2 chandler/repository/persistence/RepositoryError.py:1.3
--- chandler/repository/persistence/RepositoryError.py:1.2	Mon Aug 30 14:27:16 2004
+++ chandler/repository/persistence/RepositoryError.py	Thu Sep  2 10:34:26 2004
@@ -1,6 +1,6 @@
 
-__revision__  = "$Revision: 1.2 $"
-__date__      = "$Date: 2004/08/30 21:27:16 $"
+__revision__  = "$Revision: 1.3 $"
+__date__      = "$Date: 2004/09/02 17:34:26 $"
 __copyright__ = "Copyright (c) 2002 Open Source Applications Foundation"
 __license__   = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
 
@@ -26,3 +26,10 @@
 
     def __str__(self):
         return self.__doc__ % self.args
+
+
+class MergeError(VersionConflictError):
+    "(%s) merging %s failed because %s"
+
+    def __str__(self):
+        return self.__doc__ % self.args

Index: chandler/repository/persistence/Repository.py
diff -u chandler/repository/persistence/Repository.py:1.81 chandler/repository/persistence/Repository.py:1.82
--- chandler/repository/persistence/Repository.py:1.81	Wed Aug 25 18:00:52 2004
+++ chandler/repository/persistence/Repository.py	Thu Sep  2 10:34:25 2004
@@ -1,6 +1,6 @@
 
-__revision__  = "$Revision: 1.81 $"
-__date__      = "$Date: 2004/08/26 01:00:52 $"
+__revision__  = "$Revision: 1.82 $"
+__date__      = "$Date: 2004/09/02 17:34:25 $"
 __copyright__ = "Copyright (c) 2002 Open Source Applications Foundation"
 __license__   = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
 
@@ -224,14 +224,14 @@
         Iterate over the roots of this repository using the current view.
         """
 
-        return self.iterChildren()
-    
-    def iterChildren(self, load=True):
+        return self.view.__iter__()
+
+    def iterRoots(self, load=True):
         """
         Iterate over the roots of this repository using the current view.
         """
 
-        return self.view.iterChildren(load)
+        return self.view.iterRoots(load)
 
     def isOpen(self):
         """
@@ -251,7 +251,7 @@
         for more details.
         """
 
-        return self.getRoot(name, load) is not None
+        return self.view.hasRoot(name, load)
 
     def getRoot(self, name, load=True):
         """
@@ -268,17 +268,6 @@
 
         return self.view.__getitem__(key)
 
-    def getRoots(self, load=True):
-        """
-        Get all roots in the repository.
-
-        See L{RepositoryView.getRoots
-        <repository.persistence.RepositoryView.RepositoryView.getRoots>}
-        for more details.
-        """
-
-        return self.view.getRoots(load)
-
     def walk(self, path, callable, _index=0, **kwds):
         """
         Walk a path in the current view and invoke a callable along the way.
@@ -468,9 +457,6 @@
     def serveItem(self, version, uuid):
         raise NotImplementedError, "%s.serveItem" %(type(self))
     
-    def loadChild(self, version, uuid, name):
-        raise NotImplementedError, "%s.loadChild" %(type(self))
-
     def serveChild(self, version, uuid, name):
         raise NotImplementedError, "%s.serveChild" %(type(self))
 

Index: chandler/repository/tests/TestItems.py
diff -u chandler/repository/tests/TestItems.py:1.11 chandler/repository/tests/TestItems.py:1.12
--- chandler/repository/tests/TestItems.py:1.11	Mon Jun  7 23:59:09 2004
+++ chandler/repository/tests/TestItems.py	Thu Sep  2 10:34:26 2004
@@ -2,8 +2,8 @@
 Basic Unit tests for Chandler repository
 """
 
-__revision__  = "$Revision: 1.11 $"
-__date__      = "$Date: 2004/06/08 06:59:09 $"
+__revision__  = "$Revision: 1.12 $"
+__date__      = "$Date: 2004/09/02 17:34:26 $"
 __copyright__ = "Copyright (c) 2003 Open Source Applications Foundation"
 __license__   = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
 
@@ -49,7 +49,7 @@
 
         # Test to see that item became a respository root
         self.rep.commit()
-        roots = self.rep.getRoots()
+        roots = list(self.rep.iterRoots())
         self.assert_(item in roots)
         self.failIf(item.isDirty())
 
@@ -152,7 +152,7 @@
         child2 = item['child2']
         child3 = self.rep['child3']
 
-        self.assert_(child3 in self.rep.getRoots())
+        self.assert_(child3 in list(self.rep.iterRoots()))
         self.assertItemPathEqual(child3, '//child3')
         self.assertIsRoot(child3.itsRoot)
 

Index: chandler/repository/persistence/FileRepository.py
diff -u chandler/repository/persistence/FileRepository.py:1.29 chandler/repository/persistence/FileRepository.py:1.30
--- chandler/repository/persistence/FileRepository.py:1.29	Thu Aug 19 11:06:29 2004
+++ chandler/repository/persistence/FileRepository.py	Thu Sep  2 10:34:25 2004
@@ -1,6 +1,6 @@
 
-__revision__  = "$Revision: 1.29 $"
-__date__      = "$Date: 2004/08/19 18:06:29 $"
+__revision__  = "$Revision: 1.30 $"
+__date__      = "$Date: 2004/09/02 17:34:25 $"
 __copyright__ = "Copyright (c) 2002 Open Source Applications Foundation"
 __license__   = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
 
@@ -94,9 +94,6 @@
     def _loadItem(self, uuid):
         return None
 
-    def _loadChild(self, parent, name):
-        return None
-
     def purge(self):
         'Purge the repository directory tree of all item files that do not correspond to currently existing items in the repository.'
         

Index: chandler/repository/persistence/PackHandler.py
diff -u chandler/repository/persistence/PackHandler.py:1.16 chandler/repository/persistence/PackHandler.py:1.17
--- chandler/repository/persistence/PackHandler.py:1.16	Sun May 30 12:28:57 2004
+++ chandler/repository/persistence/PackHandler.py	Thu Sep  2 10:34:25 2004
@@ -1,6 +1,6 @@
 
-__revision__  = "$Revision: 1.16 $"
-__date__      = "$Date: 2004/05/30 19:28:57 $"
+__revision__  = "$Revision: 1.17 $"
+__date__      = "$Date: 2004/09/02 17:34:25 $"
 __copyright__ = "Copyright (c) 2002 Open Source Applications Foundation"
 __license__   = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
 
@@ -148,6 +148,7 @@
 
             for item in items:
                 item._status |= item.NEW
+                item.setDirty(item.NDIRTY, None)
 
             return items[0]
 

Index: chandler/repository/persistence/XMLRepository.py
diff -u chandler/repository/persistence/XMLRepository.py:1.79 chandler/repository/persistence/XMLRepository.py:1.80
--- chandler/repository/persistence/XMLRepository.py:1.79	Mon Aug 30 14:27:16 2004
+++ chandler/repository/persistence/XMLRepository.py	Thu Sep  2 10:34:26 2004
@@ -1,6 +1,6 @@
 
-__revision__  = "$Revision: 1.79 $"
-__date__      = "$Date: 2004/08/30 21:27:16 $"
+__revision__  = "$Revision: 1.80 $"
+__date__      = "$Date: 2004/09/02 17:34:26 $"
 __copyright__ = "Copyright (c) 2002 Open Source Applications Foundation"
 __license__   = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
 
@@ -205,14 +205,6 @@
 
         return None
             
-    def loadChild(self, version, uuid, name):
-
-        uuid = self.store.readName(version, uuid, name)
-        if uuid is None:
-            return None
-
-        return self.loadItem(version, uuid)
-
     def queryItems(self, version, query):
 
         store = self.store
@@ -245,10 +237,6 @@
 
         return results
 
-    def deleteDocument(self, doc):
-
-        self._xml.deleteDocument(self.store.txn, doc, self.store.updateCtx)
-
     def getDocument(self, docId):
 
         return self._xml.getDocument(self.store.txn, docId, DB_DIRTY_READ)
@@ -364,10 +352,6 @@
 
         return self._data.loadItem(version, uuid)
     
-    def loadChild(self, version, uuid, name):
-
-        return self._data.loadChild(version, uuid, name)
-
     def loadRef(self, version, uItem, uuid, key):
 
         buffer = self._refs.prepareKey(uItem, uuid)
@@ -550,7 +534,7 @@
             self.repository._env.lock_put(lock)
         return None
 
-    def saveItem(self, xml, uuid, version, currPN, origPN, status,
+    def saveItem(self, xml, uuid, version, parent, status,
                  dirtyValues, dirtyRefs):
         
         doc = XmlDocument()
@@ -566,24 +550,15 @@
             raise
 
         if status & Item.DELETED:
-            parent, name = origPN
             self._versions.setDocVersion(uuid, version, 0)
             self._history.writeVersion(uuid, version, 0, status,
                                        parent, [], [])
-            self.writeName(version, parent, name, None)
 
         else:
             self._versions.setDocVersion(uuid, version, docId)
             self._history.writeVersion(uuid, version, docId, status,
                                        None, dirtyValues, dirtyRefs)
 
-            if origPN is not None:
-                parent, name = origPN
-                self.writeName(version, parent, name, None)
-
-            parent, name = currPN
-            self.writeName(version, parent, name, uuid)
-
     def serveItem(self, version, uuid):
 
         if version == 0:

Index: chandler/repository/item/ItemHandler.py
diff -u chandler/repository/item/ItemHandler.py:1.45 chandler/repository/item/ItemHandler.py:1.46
--- chandler/repository/item/ItemHandler.py:1.45	Sun Aug 29 19:50:28 2004
+++ chandler/repository/item/ItemHandler.py	Thu Sep  2 10:34:25 2004
@@ -1,11 +1,9 @@
 
-__revision__  = "$Revision: 1.45 $"
-__date__      = "$Date: 2004/08/30 02:50:28 $"
+__revision__  = "$Revision: 1.46 $"
+__date__      = "$Date: 2004/09/02 17:34:25 $"
 __copyright__ = "Copyright (c) 2002 Open Source Applications Foundation"
 __license__   = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
 
-import repository.item as ItemPackage
-
 from repository.item.PersistentCollections import PersistentCollection
 from repository.item.PersistentCollections import PersistentList
 from repository.item.PersistentCollections import PersistentDict
@@ -146,18 +144,19 @@
         self.cls = None
         self.kindRef = None
         self.parentRef = None
-        self.previous = self.next = None
-        self.first = self.last = None
+        self.isContainer = False
         self.withSchema = attrs.get('withSchema', 'False') == 'True'
         self.uuid = UUID(attrs.get('uuid'))
         self.version = long(attrs.get('version', '0L'))
         
     def itemEnd(self, itemHandler, attrs):
 
+        from repository.item.Item import Item
+        
         cls = self.cls
         if cls is None:
             if self.kind is None:
-                cls = ItemPackage.Item.Item
+                cls = Item
             else:
                 cls = self.kind.getItemClass()
 
@@ -174,17 +173,14 @@
             
         item._fillItem(self.name, self.parent, self.kind, uuid = self.uuid,
                        values = self.values, references = self.references,
-                       previous = self.previous, next = self.next,
                        afterLoadHooks = self.afterLoadHooks,
                        version = self.version)
+        if self.isContainer:
+            item._children = self.repository._createChildren(item)
+            
         if pinned:
             item._status |= item.PINNED
 
-        if self.first or self.last:
-            item._children = ItemPackage.Item.Children(item)
-            item._children._firstKey = self.first
-            item._children._lastKey = self.last
-
         self.repository._registerItem(item)
 
         for attribute, value in self.values.iteritems():
@@ -239,22 +235,9 @@
         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:
-            if self.afterLoadHooks is not None:
-                self.afterLoadHooks.append(self._move)
-            else:
-                raise ValueError, "Parent %s not found" %(self.parentRef)
-
-    def containerEnd(self, itemHandler, attrs):
-
-        self.parentRef = UUID(self.data)
-        self.previous = attrs.get('previous')
-        self.next = attrs.get('next')
-        self.first = attrs.get('first')
-        self.last = attrs.get('last')
 
-        self.parent = self.repository.find(self.parentRef)
         if self.parent is None:
             if self.afterLoadHooks is not None:
                 self.afterLoadHooks.append(self._move)
@@ -268,7 +251,7 @@
             if self.parent is None:
                 raise ValueError, 'Parent %s not found' %(self.parentRef)
             else:
-                self.item.move(self.parent, self.previous, self.next)
+                self.item.move(self.parent)
 
     def classEnd(self, itemHandler, attrs):
 
@@ -598,10 +581,13 @@
         generator.startElement(tag, attrs)
 
         if attrCard == 'single':
-            if isinstance(value, ItemPackage.Item.Item):
+
+            from repository.item.Item import Item
+            
+            if isinstance(value, Item):
                 raise TypeError, "item %s cannot be stored as a literal value" %(value.itsPath)
 
-            if value is ItemPackage.Item.Item.Nil:
+            if value is Item.Nil:
                 raise ValueError, 'Cannot persist Item.Nil'
 
             if attrType is not None:

Index: chandler/repository/item/ItemRef.py
diff -u chandler/repository/item/ItemRef.py:1.88 chandler/repository/item/ItemRef.py:1.89
--- chandler/repository/item/ItemRef.py:1.88	Thu Aug 26 12:25:03 2004
+++ chandler/repository/item/ItemRef.py	Thu Sep  2 10:34:25 2004
@@ -1,6 +1,6 @@
 
-__revision__  = "$Revision: 1.88 $"
-__date__      = "$Date: 2004/08/26 19:25:03 $"
+__revision__  = "$Revision: 1.89 $"
+__date__      = "$Date: 2004/09/02 17:34:25 $"
 __copyright__ = "Copyright (c) 2002 Open Source Applications Foundation"
 __license__   = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
 
@@ -34,6 +34,9 @@
 
         return '<ItemRef: %s - %s>' %(self._item, self._other)
 
+    def _clearDirties(self):
+        pass
+
     def _setItem(self, item):
         pass
 
@@ -481,13 +484,6 @@
     items.
     """
     
-    class link(LinkedMap.link):
-
-        def __init__(self, value):
-
-            super(RefDict.link, self).__init__(value)
-            self._alias = None
-
     def __init__(self, item, name, otherName, readOnly=False):
         """
         The constructor for this class. A RefDict should not be instantiated
@@ -499,7 +495,6 @@
         self._otherName = otherName
         self._setItem(item)
         self._count = 0
-        self._aliases = None
         self._readOnly = readOnly
         self._indexes = None
         self._flags = RefDict.SETDIRTY
@@ -797,21 +792,15 @@
             value = ItemRef(self._getItem(), self._name,
                             value, self._otherName)
 
-        link = super(RefDict, self).__setitem__(key, value,
-                                                previousKey, nextKey)
+        super(RefDict, self).__setitem__(key, value,
+                                         previousKey, nextKey, alias)
+
         if not loading:
             self._count += 1
             if self._indexes:
                 for index in self._indexes.itervalues():
                     index.insertKey(key, previousKey)
 
-        if alias:
-            link._alias = alias
-            if self._aliases is None:
-                self._aliases = { alias: key }
-            else:
-                self._aliases[alias] = key
-
         return value
 
     def placeItem(self, item, after, indexName=None):
@@ -879,13 +868,9 @@
             value.detach(self._item, self._name,
                          value.other(self._item), self._otherName)
 
-        link = super(RefDict, self).__delitem__(key)
-        if link._alias is not None:
-            del self._aliases[link._alias]
-            
         self._count -= 1
 
-        return link
+        return super(RefDict, self).__delitem__(key)
 
     def _load(self, key):
 
@@ -954,52 +939,6 @@
 
         return default
 
-    def getByAlias(self, alias, default=None, load=True):
-        """
-        Get the item referenced through its alias.
-        
-        @param alias: the alias of the item referenced.
-        @type key: a string
-        @param default: the default value to return if there is no reference
-        for C{key} in this ref collection, C{None} by default.
-        @type default: anything
-        @param load: if the reference exists but hasn't been loaded yet,
-        this method will return C{default} if this parameter is C{False}.
-        @type load: boolean
-        @return: an C{Item} instance or C{default}
-        """
-        
-        key = None
-
-        if self._aliases is not None:
-            key = self._aliases.get(alias)
-            
-        if key is None and load:
-            key = self.resolveAlias(alias, load)
-
-        if key is None:
-            return default
-            
-        return self.get(key, default, load)
-
-    def resolveAlias(self, alias, load=True):
-        """
-        Resolve the alias to its corresponding reference key.
-
-        @param alias: the alias to resolve.
-        @type alias: a string
-        @param load: if the reference exists but hasn't been loaded yet,
-        this method will return C{None} if this parameter is C{False}.
-        @type load: boolean
-        @return: a L{UUID<repository.util.UUID.UUID>} or C{None} if the
-        alias does not exist.
-        """
-        
-        if self._aliases:
-            return self._aliases.get(alias)
-
-        return None
-
     def getAlias(self, item):
         """
         Get the alias this item is keyed on in this collection.
@@ -1276,6 +1215,9 @@
 
         return True
 
+    def _clearDirties(self):
+        pass
+
     SETDIRTY = 0x0001
 
 

Index: chandler/repository/persistence/XMLRepositoryView.py
diff -u chandler/repository/persistence/XMLRepositoryView.py:1.52 chandler/repository/persistence/XMLRepositoryView.py:1.53
--- chandler/repository/persistence/XMLRepositoryView.py:1.52	Mon Aug 30 17:19:56 2004
+++ chandler/repository/persistence/XMLRepositoryView.py	Thu Sep  2 10:34:26 2004
@@ -1,6 +1,6 @@
 
-__revision__  = "$Revision: 1.52 $"
-__date__      = "$Date: 2004/08/31 00:19:56 $"
+__revision__  = "$Revision: 1.53 $"
+__date__      = "$Date: 2004/09/02 17:34:26 $"
 __copyright__ = "Copyright (c) 2002 Open Source Applications Foundation"
 __license__   = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
 
@@ -18,7 +18,7 @@
 from repository.persistence.Repository import Repository
 from repository.persistence.Repository import RepositoryNotifications
 from repository.persistence.XMLLob import XMLText, XMLBinary
-from repository.persistence.XMLRefDict import XMLRefDict
+from repository.persistence.XMLRefDict import XMLRefDict, XMLChildren
 from repository.util.SAX import XMLGenerator
 
 timing = False
@@ -66,11 +66,13 @@
         for item in self._log:
             if not item.isNew():
                 self.logger.debug('reloading version %d of %s',
-                                  self.version, item)
+                                  self._version, item)
                 self._loadItem(item._uuid, instance=item)
 
         del self._log[:]
-        self._notRoots.clear()
+        if self._dirty:
+            self._roots._clearDirties()
+            self._dirty = 0
 
         self.prune(10000)
 
@@ -79,7 +81,7 @@
         store = self.repository.store
         items = []
         
-        for doc in store.queryItems(self.version, query):
+        for doc in store.queryItems(self._version, query):
             uuid = store.getDocUUID(doc)
             if not uuid in self._deletedRegistry:
                 # load and doc, trick to pass doc directly to find
@@ -93,7 +95,7 @@
 
         store = self.repository.store
         results = []
-        docs = store.searchItems(self.version, query)
+        docs = store.searchItems(self._version, query)
         for (uuid, (ver, attribute)) in docs.iteritems():
             if not uuid in self._deletedRegistry:
                 item = self.find(uuid, load=load)
@@ -109,6 +111,10 @@
         else:
             return TransientRefDict(item, name, otherName, readOnly)
 
+    def _createChildren(self, parent):
+
+        return XMLChildren(self, parent)
+
     def _getLobType(self, mode):
 
         if mode == 'text':
@@ -188,13 +194,15 @@
                                 ood[uuid] = item
 
                     if ood:
-                        self._mergeItems(ood, self.version, newVersion,
+                        self._mergeItems(ood, self._version, newVersion,
                                          history)
                 
                     for item in self._log:
                         size += self._saveItem(item, newVersion, store, ood)
+                    if self._dirty:
+                        self._roots._saveValues(newVersion)
 
-                if newVersion > self.version:
+                if newVersion > self._version:
                     histNotifications = RepositoryNotifications()
                     
                     def unload(uuid, version, docId, status, parent, dirties):
@@ -215,7 +223,7 @@
                             item._version < newVersion):
                             unloads[item._uuid] = item
 
-                    history.apply(unload, self.version, newVersion)
+                    history.apply(unload, self._version, newVersion)
                     
                 if txnStarted:
                     self._commitTransaction()
@@ -244,6 +252,7 @@
                 raise
 
         if self._log:
+
             for item in self._log:
                 if not item._status & Item.MERGED:
                     item._version = newVersion
@@ -251,10 +260,14 @@
                 item._status &= ~(Item.NEW | Item.MERGED | Item.SAVED)
             del self._log[:]
 
-        if newVersion > self.version:
+            if self._dirty:
+                self._roots._clearDirties()
+                self._dirty = 0
+
+        if newVersion > self._version:
             self.logger.debug('refreshing view from version %d to %d',
-                              self.version, newVersion)
-            self.version = newVersion
+                              self._version, newVersion)
+            self._version = newVersion
             for item in unloads.itervalues():
                 self.logger.debug('unloading version %d of %s',
                                   item._version, item)
@@ -265,8 +278,6 @@
                                       newVersion, item)
                     self._loadItem(item._uuid, instance=item)
                     
-        self._notRoots.clear()
-
         after = datetime.now()
         if count > 0:
             self.logger.info('%s committed %d items (%ld bytes) in %s',
@@ -318,14 +329,8 @@
         xml = out.getvalue()
         out.close()
 
-        if '_origName' in item.__dict__:
-            origPN = item.__dict__['_origName']
-            del item.__dict__['_origName']
-        else:
-            origPN = None
-
-        store.saveItem(xml, uuid, newVersion,
-                       (item.itsParent.itsUUID, item._name), origPN,
+        parent = item.itsParent.itsUUID
+        store.saveItem(xml, uuid, newVersion, parent,
                        item._status & Item.SAVEMASK,
                        item._values._getDirties(),
                        item._references._getDirties())
@@ -335,7 +340,7 @@
                 store.saveACL(newVersion, uuid, name, acl)
 
         if isDeleted:
-            self._notifications.changed(uuid, 'deleted', parent=origPN[0])
+            self._notifications.changed(uuid, 'deleted', parent=parent)
         elif isNew:
             self._notifications.changed(uuid, 'added')
         else:
@@ -353,11 +358,9 @@
                 if newDirty & oldDirty:
                     raise VersionConflictError, (item, newDirty, oldDirty)
                 else:
-                    if (newDirty == item.VDIRTY or oldDirty == item.VDIRTY or
-                        newDirty == item.RDIRTY or oldDirty == item.RDIRTY or
-                        newDirty == item.VRDIRTY or oldDirty == item.VRDIRTY):
+                    if newDirty == item.VDIRTY or oldDirty == item.VDIRTY:
                         items[uuid] = (docId, oldDirty, newDirty)
                     else:
-                        raise NotImplementedError, 'Item %s may be mergeable but this particular merge (0x%x:0x%x) is not implemented yet' %(item.itsPath, newDirty, oldDirty)    
+                        raise NotImplementedError, 'Item %s may be mergeable but this particular merge (0x%x:0x%x) is not implemented yet' %(item.itsPath, newDirty, oldDirty)
 
         history.apply(check, oldVersion, newVersion)

Index: chandler/repository/persistence/XMLRefDict.py
diff -u chandler/repository/persistence/XMLRefDict.py:1.3 chandler/repository/persistence/XMLRefDict.py:1.4
--- chandler/repository/persistence/XMLRefDict.py:1.3	Thu Aug 19 11:06:29 2004
+++ chandler/repository/persistence/XMLRefDict.py	Thu Sep  2 10:34:26 2004
@@ -1,11 +1,12 @@
 
-__revision__  = "$Revision: 1.3 $"
-__date__      = "$Date: 2004/08/19 18:06:29 $"
+__revision__  = "$Revision: 1.4 $"
+__date__      = "$Date: 2004/09/02 17:34:26 $"
 __copyright__ = "Copyright (c) 2002 Open Source Applications Foundation"
 __license__   = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
 
 from cStringIO import StringIO
 
+from repository.item.Item import Children
 from repository.item.ItemRef import RefDict
 from repository.item.Indexes import NumericIndex
 from repository.util.UUID import UUID
@@ -50,14 +51,18 @@
         super(XMLRefDict, self)._changeRef(key, alias, noMonitors)
 
         if not self.view.isLoading():
-            self._changedRefs[key] = (0, alias)
+            op, alias = self._changedRefs.get(key, (1, alias))
+            if op != 0:
+                self._changedRefs[key] = (0, alias)
         
     def _removeRef(self, key, _detach=False):
 
         link = super(XMLRefDict, self)._removeRef(key, _detach)
 
         if not self.view.isLoading():
-            self._changedRefs[key] = (1, link._alias)
+            op, alias = self._changedRefs.get(key, (0, link._alias))
+            if op != 1:
+                self._changedRefs[key] = (1, alias)
         else:
             raise ValueError, 'detach during load'
 
@@ -84,8 +89,12 @@
 
         if load and key is None:
             view = self.view
-            key = view.repository.store.readName(view.version, self._uuid,
+            key = view.repository.store.readName(view._version, self._uuid,
                                                  alias)
+            if key is not None:
+                op, oldAlias = self._changedRefs.get(key, (0, None))
+                if oldAlias == alias:
+                    key = None
 
         return key
 
@@ -122,7 +131,7 @@
                         alias = value._alias
     
                         self._writeRef(key, version, previous, next, alias)
-                        if oldAlias is not None:
+                        if oldAlias is not None and oldAlias != alias:
                             store.writeName(version, self._uuid, oldAlias,
                                             None)
                         if alias is not None:
@@ -132,7 +141,8 @@
                 elif op == 1:             # remove
                     self._deleteRef(key, version)
                     if oldAlias is not None:
-                        store.writeName(version, key, oldAlias, None)
+                        store.writeName(version, self._uuid, oldAlias,
+                                        None)
 
                 else:                     # error
                     raise ValueError, op
@@ -140,8 +150,6 @@
             if self._changedRefs:
                 self.view._notifications.changed(self._item._uuid, self._name)
 
-            self._changedRefs.clear()
-            
             if len(self) > 0:
                 generator.startElement('db', {})
                 generator.characters(self._uuid.str64())
@@ -158,6 +166,13 @@
         else:
             raise ValueError, mode
 
+    def _clearDirties(self):
+
+        self._changedRefs.clear()
+        if self._indexes:
+            for name, index in self._indexes.iteritems():
+                index._clearDirties()
+
     def _createIndex(self, indexType, **kwds):
 
         if indexType == 'numeric':
@@ -284,7 +299,6 @@
                 indexes.saveKey(self._key, self._value,
                                 version, key, node)
 
-            self._changedKeys.clear()
             self._version = version
             
         elif mode == 'serialize':
@@ -292,4 +306,132 @@
 
         else:
             raise ValueError, mode
+
+    def _clearDirties(self):
+
+        self._changedKeys.clear()
+        
+
+class XMLChildren(Children):
+
+    def __init__(self, view, item):
+
+        super(XMLChildren, self).__init__(item)
+
+        self.view = view
+        
+        self._uuid = item.itsUUID
+        self._changedRefs = {}
+        self._key = self._getRefs().prepareKey(self._uuid, self._uuid)
+        self._value = StringIO()
+
+        ref = self._getRefs().loadRef(self._key, self._item._version,
+                                      self._uuid)
+        if ref is not None:
+            self._firstKey, self._lastKey, alias = ref
+
+    def resolveAlias(self, alias, load=True):
+
+        load = load and not self._item.isNew()
+        key = None
+        
+        if self._aliases:
+            key = self._aliases.get(alias)
+
+        if load and key is None:
+            view = self.view
+            key = view.repository.store.readName(view._version,
+                                                 self._uuid, alias)
+            if key is not None:
+                op, oldAlias = self._changedRefs.get(key, (0, None))
+                if oldAlias == alias:
+                    key = None
+
+        return key
+
+    def _load(self, key):
+
+        if self.view._loadItem(key) is not None:
+            return True
+
+        return False
+
+    def linkChanged(self, link, key):
+
+        super(XMLChildren, self).linkChanged(link, key)
         
+        if not self.view.isLoading():
+            op, alias = self._changedRefs.get(key, (1, link._alias))
+            if op != 0:
+                # changed element: key, maybe old alias: alias
+                self._changedRefs[key] = (0, alias)
+
+    def __delitem__(self, key):
+
+        link = super(XMLChildren, self).__delitem__(key)
+        op, alias = self._changedRefs.get(key, (0, link._alias))
+        if op != 1:
+            # deleted element: key, maybe old alias: alias
+            self._changedRefs[key] = (1, alias)
+
+    def __setitem__(self, key, value,
+                    previousKey=None, nextKey=None, alias=None):
+
+        if previousKey is None and nextKey is None and self.view.isLoading():
+            ref = self._getRefs().loadRef(self._key, self._item._version, key)
+            if ref is not None:
+                previousKey, nextKey, refAlias = ref
+                assert alias == refAlias
+
+        super(XMLChildren, self).__setitem__(key, value,
+                                             previousKey, nextKey, alias)
+
+    def _getRefs(self):
+
+        return self.view.repository.store._refs
+
+    def _writeRef(self, key, version, previous, next, alias):
+
+        self._getRefs().saveRef(self._key, self._value, version, key,
+                                previous, next, alias)
+
+    def _deleteRef(self, key, version):
+
+        self._getRefs().deleteRef(self._key, self._value, version, key)
+
+    def _saveValues(self, version):
+
+        store = self.view.repository.store
+
+        for key, (op, oldAlias) in self._changedRefs.iteritems():
+            try:
+                link = self._get(key, load=False)
+            except KeyError:
+                link = None
+    
+            if op == 0:               # change
+                if link is not None:
+                    ref = link._value
+                    previous = link._previousKey
+                    next = link._nextKey
+                    alias = link._alias
+                    
+                    self._writeRef(key, version, previous, next, alias)
+                    if oldAlias != alias:
+                        store.writeName(version, self._uuid, oldAlias, None)
+                    store.writeName(version, self._uuid, alias, key)
+
+                elif key is None:
+                    self._writeRef(self._uuid, version,
+                                   self._firstKey, self._lastKey, None)
+                        
+            elif op == 1:             # remove
+                self._deleteRef(key, version)
+                store.writeName(version, self._uuid, oldAlias, None)
+
+            else:                     # error
+                raise ValueError, op
+
+    def _clearDirties(self):
+
+        self._changedRefs.clear()

Index: chandler/repository/persistence/RepositoryView.py
diff -u chandler/repository/persistence/RepositoryView.py:1.6 chandler/repository/persistence/RepositoryView.py:1.7
--- chandler/repository/persistence/RepositoryView.py:1.6	Thu Jul  8 17:00:01 2004
+++ chandler/repository/persistence/RepositoryView.py	Thu Sep  2 10:34:26 2004
@@ -1,6 +1,6 @@
 
-__revision__  = "$Revision: 1.6 $"
-__date__      = "$Date: 2004/07/09 00:00:01 $"
+__revision__  = "$Revision: 1.7 $"
+__date__      = "$Date: 2004/09/02 17:34:26 $"
 __copyright__ = "Copyright (c) 2002 Open Source Applications Foundation"
 __license__   = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
 
@@ -74,6 +74,10 @@
 
         raise NotImplementedError, "%s._createRefDict" %(type(self))
     
+    def _createChildren(self, parent):
+
+        raise NotImplementedError, "%s._createChildren" %(type(self))
+    
     def _getLobType(self):
 
         raise NotImplementedError, "%s._getLobType" %(type(self))
@@ -86,7 +90,8 @@
         re-opening a closed view.
         """
 
-        self._roots = {}
+        self._roots = self._createChildren(self)
+        self._dirty = 0
         self._registry = {}
         self._deletedRegistry = {}
         self._childrenRegistry = {}
@@ -95,6 +100,10 @@
         
         self.repository.store.attachView(self)
 
+    def setDirty(self, dirty, attribute):
+
+        self._dirty = dirty
+
     def closeView(self):
         """
         Close this repository view.
@@ -113,7 +122,8 @@
             item._setStale()
 
         self._registry.clear()
-        self._roots.clear()
+        self._roots = None
+        self._dirty = 0
         self._deletedRegistry.clear()
         self._childrenRegistry.clear()
         del self._stubs[:]
@@ -150,6 +160,10 @@
         return ((self._status & RepositoryView.OPEN) != 0 and
                 self.repository.isOpen())
 
+    def isNew(self):
+
+        return False
+
     def isStale(self):
 
         return False
@@ -328,7 +342,7 @@
         @return: an L{ACL<repository.item.Access.ACL>} instance or C{None}
         """
 
-        return self.repository.store.loadACL(self.version, uuid, name)
+        return self.repository.store.loadACL(self._version, uuid, name)
 
     def loadPack(self, path, parent=None):
         """
@@ -369,7 +383,7 @@
         
         if item is None:
             path = Path('//')
-            for root in self.getRoots():
+            for root in self.iterRoots():
                 self.dir(root, path)
         else:
             if path is None:
@@ -451,7 +465,7 @@
         """
 
         result = True
-        for root in self.getRoots():
+        for root in self.iterRoots():
             check = root.check(True)
             result = result and check
 
@@ -470,7 +484,7 @@
         @return: C{True} or C{False}
         """
 
-        return self.getRoot(name, load) is not None
+        return self._roots.resolveAlias(name, load) is not None
 
     def getRoot(self, name, load=True):
         """
@@ -485,10 +499,7 @@
         @return: a root item or C{None} if not found.
         """
 
-        try:
-            return self._roots[name]
-        except KeyError:
-            return self._loadRoot(name)
+        return self._roots.getByAlias(name, None, load)
 
     def __getitem__(self, key):
 
@@ -514,29 +525,30 @@
 
     def __iter__(self):
         """
-        Iterate over the roots of this repository in this view.
+        See L{iterRoots}
         """
 
-        return self.iterChildren()
+        return self.iterRoots()
     
-    def iterChildren(self, load=True):
+    def iterChildren(self):
         """
-        Iterate over the roots of this repository in this view.
+        See L{iterRoots}
         """
 
-        return self.getRoots(load).__iter__()
-
-    def getRoots(self, load=True):
+        return self.iterRoots()
+    
+    def iterRoots(self, load=True):
+        """
+        Iterate over the roots of this repository in this view.
         """
-        Get all roots in the repository from this view.
 
-        A repository root is defined as an item whose parent is this view.
+        if not load:
+            for child in self._roots._itervalues():
+                yield child._value
 
-        @param load: if load is C{False}, only return the loaded roots.
-        @type load: boolean
-        """
-        
-        return self._roots.values()
+        else:
+            for child in self._roots:
+                yield child
 
     def _getPath(self, path=None):
 
@@ -564,20 +576,20 @@
 
         name = item.itsName
 
-        if name in self._roots:
+        if self._roots.resolveAlias(name, not self.isLoading()):
             raise ValueError, "A root named '%s' exists already" %(name)
 
-        self._roots[name] = item
+        self._roots.__setitem__(item._uuid, item, alias=name)
 
         return item
 
     def _removeItem(self, item):
 
-        del self._roots[item.itsName]
+        del self._roots[item.itsUUID]
 
-    def _unloadChild(self, name):
+    def _unloadChild(self, child):
 
-        del self._roots[name]
+        self._roots._unload(child)
 
     def _registerItem(self, item):
 
@@ -674,9 +686,6 @@
     def _loadRoot(self, name):
         raise NotImplementedError, "%s._loadRoot" %(type(self))
 
-    def _loadChild(self, parent, name):
-        raise NotImplementedError, "%s._loadChild" %(type(self))
-
     def _newItems(self):
         raise NotImplementedError, "%s._newItems" %(type(self))
 
@@ -701,6 +710,10 @@
 
         return self.repository.logger.getEffectiveLevel() <= logging.DEBUG
 
+    def getRepositoryView(self):
+
+        return self
+
     itsUUID = property(__getUUID)
     itsName = property(__getName)
     itsPath = property(_getPath)
@@ -717,13 +730,16 @@
 class OnDemandRepositoryView(RepositoryView):
 
     def __init__(self, repository, name):
-        
-        super(OnDemandRepositoryView, self).__init__(repository, name)
 
-        self.version = repository.store.getVersion()
+        self._version = repository.store.getVersion()
         self._hooks = None
-        self._notRoots = {}
         
+        super(OnDemandRepositoryView, self).__init__(repository, name)
+
+    def isNew(self):
+
+        return self._version == 0
+
     def _loadDoc(self, doc, instance=None):
 
         try:
@@ -781,7 +797,7 @@
     def _loadItem(self, uuid, instance=None):
 
         if not uuid in self._deletedRegistry:
-            doc = self.repository.store.loadItem(self.version, uuid)
+            doc = self.repository.store.loadItem(self._version, uuid)
 
             if doc is not None:
                 self.logger.debug("loading item %s", uuid)
@@ -789,46 +805,6 @@
 
         return None
 
-    def _loadRoot(self, name):
-
-        return self._loadChild(None, name)
-
-    def getRoots(self, load=True):
-        'Return a list of the roots in the repository.'
-
-        if load:
-            for uuid in self.repository.store.readNames(self.version,
-                                                        self.itsUUID):
-                self.find(uuid)
-            
-        return super(OnDemandRepositoryView, self).getRoots(load)
-
-    def _loadChild(self, parent, name):
-
-        if parent is not None and parent is not self:
-            uuid = parent.itsUUID
-        else:
-            uuid = self.itsUUID
-
-        store = self.repository.store
-        doc = store.loadChild(self.version, uuid, name)
-                
-        if doc is not None:
-            uuid = store.getDocUUID(doc)
-
-            if (not self._deletedRegistry or
-                not uuid in self._deletedRegistry):
-                if self.isDebug():
-                    if parent is not None and parent is not self:
-                        self.logger.debug("loading child %s of %s",
-                                          name, parent.itsPath)
-                    else:
-                        self.logger.debug("loading root %s", name)
-                    
-                return self._loadDoc(doc)
-
-        return None
-
     def _findKind(self, spec, withSchema):
 
         if withSchema:
@@ -852,10 +828,6 @@
 
         super(OnDemandRepositoryView, self)._addItem(item, previous, next)
 
-        name = item.itsName
-        if name in self._notRoots:
-            del self._notRoots[name]
-
         item.setPinned(True)
 
         return item
@@ -864,18 +836,8 @@
 
         super(OnDemandRepositoryView, self)._removeItem(item)
 
-        name = item.itsName
-        self._notRoots[name] = name
-
         item.setPinned(False)
         
-    def getRoot(self, name, load=True):
-
-        if not name in self._notRoots:
-            return super(OnDemandRepositoryView, self).getRoot(name, load)
-
-        return None
-
     def prune(self, size):
 
         registry = self._registry

Index: chandler/repository/remote/RemoteRepository.py
diff -u chandler/repository/remote/RemoteRepository.py:1.3 chandler/repository/remote/RemoteRepository.py:1.4
--- chandler/repository/remote/RemoteRepository.py:1.3	Tue May 18 20:19:21 2004
+++ chandler/repository/remote/RemoteRepository.py	Thu Sep  2 10:34:26 2004
@@ -1,6 +1,6 @@
 
-__revision__  = "$Revision: 1.3 $"
-__date__      = "$Date: 2004/05/19 03:19:21 $"
+__revision__  = "$Revision: 1.4 $"
+__date__      = "$Date: 2004/09/02 17:34:26 $"
 __copyright__ = "Copyright (c) 2002 Open Source Applications Foundation"
 __license__   = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
 
@@ -62,20 +62,6 @@
 
         return doc
 
-    def loadChild(self, version, uuid, name):
-
-        doc = super(RemoteStore, self).loadChild(version, uuid, name)
-        if doc is None:
-            versionId = self._versions.getVersionId(self.itsUUID)
-            remoteVersion = self._versions.getVersion(versionId)
-            xml = self.transport.serveChild(remoteVersion, uuid, name)
-            if xml is not None:
-                filter = RemoteFilter(self, versionId)
-                self.transport.parseDoc(xml, filter)
-                doc = filter.getDocument()
-
-        return doc
-
     def getVersion(self):
 
         version = super(RemoteStore, self).getVersion()

Index: chandler/repository/tests/TestRepository.py
diff -u chandler/repository/tests/TestRepository.py:1.8 chandler/repository/tests/TestRepository.py:1.9
--- chandler/repository/tests/TestRepository.py:1.8	Mon Jun 21 17:54:08 2004
+++ chandler/repository/tests/TestRepository.py	Thu Sep  2 10:34:26 2004
@@ -2,8 +2,8 @@
 Basic Unit tests for Chandler repository
 """
 
-__revision__  = "$Revision: 1.8 $"
-__date__      = "$Date: 2004/06/22 00:54:08 $"
+__revision__  = "$Revision: 1.9 $"
+__date__      = "$Date: 2004/09/02 17:34:26 $"
 __copyright__ = "Copyright (c) 2003 Open Source Applications Foundation"
 __license__   = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
 
@@ -39,11 +39,11 @@
         root = self.rep['Packs']
         self.assert_(root.itsName == 'Packs')
     
-    def testGetRoots(self):
+    def testIterRoots(self):
         """ Make sure the roots of the repository are correct"""
 
         # (The parcel manager sticks the //parcels root in there)
-        for root in self.rep.getRoots():
+        for root in self.rep.iterRoots():
             self.assert_(root.itsName in ['Schema', 'Packs', 'parcels'])
 
     def testWalk(self):

Index: chandler/repository/item/Item.py
diff -u chandler/repository/item/Item.py:1.156 chandler/repository/item/Item.py:1.157
--- chandler/repository/item/Item.py:1.156	Mon Aug 30 17:19:56 2004
+++ chandler/repository/item/Item.py	Thu Sep  2 10:34:25 2004
@@ -1,6 +1,6 @@
 
-__revision__  = "$Revision: 1.156 $"
-__date__      = "$Date: 2004/08/31 00:19:56 $"
+__revision__  = "$Revision: 1.157 $"
+__date__      = "$Date: 2004/09/02 17:34:25 $"
 __copyright__ = "Copyright (c) 2002 Open Source Applications Foundation"
 __license__   = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
 
@@ -66,6 +66,8 @@
         if kind is not None:
             kind.getInitialValues(self, self._values, self._references)
 
+        self.setDirty(Item.NDIRTY, None)
+
     def _fillItem(self, name, parent, kind, **kwds):
 
         self._uuid = kwds['uuid']
@@ -86,7 +88,7 @@
             references._setItem(self)
             self._references = references
 
-        self._setParent(parent, kwds.get('previous'), kwds.get('next'))
+        self._setParent(parent)
 
     def __iter__(self):
         """
@@ -644,9 +646,7 @@
         """
 
         return ('_children' in self.__dict__ and
-                not ('_notChildren' in self.__dict__ and
-                     name in self._notChildren) and
-                self._children.has_key(name, load))
+                self._children.resolveAlias(name, load) is not None)
 
     def hasChildren(self):
         """
@@ -677,11 +677,11 @@
         if not (after is None or after.itsParent is self):
             raise ValueError, '%s not a child of %s' %(after, self)
         
-        key = child._name
+        key = child._uuid
         if after is None:
             afterKey = None
         else:
-            afterKey = after._name
+            afterKey = after._uuid
 
         self._children.place(key, afterKey)
 
@@ -1312,9 +1312,8 @@
         C{False}.
 
         @param dirty: one of L{Item.VDIRTY <VDIRTY>},
-        L{Item.RDIRTY <RDIRTY>}, L{Item.CDIRTY <CDIRTY>},
-        L{Item.SDIRTY, <SDIRTY>} or a bitwise or'ed combination, defaults to
-        C{Item.VDIRTY}.
+        L{Item.RDIRTY <RDIRTY>}, L{Item.CDIRTY <CDIRTY>}, or a bitwise or'ed
+        combination, defaults to C{Item.VDIRTY}.
         @type dirty: an integer
         @param attribute: the name of the attribute that was changed,
         optional, defaults to C{None} which means that no attribute was
@@ -1338,6 +1337,7 @@
             if self._status & Item.DIRTY == 0:
                 repository = self.getRepositoryView()
                 if repository is not None and not repository.isLoading():
+
                     if attribute is not None:
                         if self.getAttributeAspect(attribute, 'persist',
                                                    default=True) == False:
@@ -1354,6 +1354,8 @@
             self._status &= ~(Item.DIRTY | Item.ADIRTY)
             self._values._clearDirties()
             self._references._clearDirties()
+            if '_children' in self.__dict__:
+                self._children._clearDirties()
 
         return False
 
@@ -1491,12 +1493,10 @@
                 self.removeAttributeValue(name, _attrDict=self._references)
 
             parent = self.itsParent
-
+            view = self.getRepositoryView()
+            
             parent._removeItem(self)
-            self._setRoot(None)
-
-            if not '_origName' in self.__dict__:
-                self.__dict__['_origName'] = (parent.itsUUID, self._name)
+            self._setRoot(None, view)
 
             self._status |= Item.DELETED | Item.STALE
             self._status &= ~Item.DELETING
@@ -1575,29 +1575,26 @@
             
         return self._root
 
-    def _setRoot(self, root):
+    def _setRoot(self, root, oldView):
 
         if root is not self._root:
 
-            oldRepository = self.getRepositoryView()
             self._root = root
-            newRepository = self.getRepositoryView()
+            newView = self.getRepositoryView()
 
-            if oldRepository is not newRepository:
+            if oldView is not newView:
 
-                if oldRepository is not None and newRepository is not None:
+                if oldView is not None and newView is not None:
                     raise NotImplementedError, 'changing repositories'
 
-                if oldRepository is not None:
-                    oldRepository._unregisterItem(self)
+                if oldView is not None:
+                    oldView._unregisterItem(self)
 
-                if newRepository is not None:
-                    newRepository._registerItem(self)
-
-                    self.setDirty(Item.CDIRTY, None)
+                if newView is not None:
+                    newView._registerItem(self)
 
             for child in self.iterChildren(load=False):
-                child._setRoot(root)
+                child._setRoot(root, oldView)
 
     def __getParent(self):
 
@@ -1806,24 +1803,19 @@
         """
 
         if name != self._name:
-            origName = self._name
             parent = self.itsParent
 
             if parent._isItem():
-                link = parent._children._get(self._name)
-                parent._removeItem(self)
-                self._name = name or self._uuid.str64()
-                parent._addItem(self, link._previousKey, link._nextKey)
-            else:
-                parent._removeItem(self)
-                self._name = name or self._uuid.str64()
-                parent._addItem(self)
-                self.setDirty(Item.SDIRTY, None)
-                
-            if not '_origName' in self.__dict__:
-                self.__dict__['_origName'] = (parent.itsUUID, origName)
+                link = parent._children._get(self._uuid)
+            else:
+                link = parent._roots._get(self._uuid)
 
+            parent._removeItem(self)
+            self._name = name or self._uuid.str64()
+            parent._addItem(self, link._previousKey, link._nextKey)
 
+            self.setDirty(Item.NDIRTY, None)
+                
     def move(self, newParent, previous=None, next=None):
         """
         Move this item under another container.
@@ -1850,10 +1842,10 @@
             
         parent = self.itsParent
         if parent is not newParent:
+            oldView = parent.getRepositoryView()
             parent._removeItem(self)
-            self._setParent(newParent, previous, next)
-            if not '_origName' in self.__dict__:
-                self.__dict__['_origName'] = (parent.itsUUID, self._name)
+            self._setParent(newParent, previous, next, oldView)
+            self.setDirty(Item.NDIRTY, None)
 
     def _isRepository(self):
         return False
@@ -1861,14 +1853,13 @@
     def _isItem(self):
         return True
 
-    def _setParent(self, parent, previous=None, next=None):
+    def _setParent(self, parent, previous=None, next=None, oldView=None):
 
         if parent is not None:
             if parent._isRepository():
                 parent = parent.view
             self._parent = parent
-            self._root = None
-            self._setRoot(parent._addItem(self, previous, next))
+            self._setRoot(parent._addItem(self, previous, next), oldView)
         else:
             self._parent = None
 
@@ -1876,33 +1867,22 @@
 
         name = item._name
         
-        if self.__dict__.has_key('_children'):
+        if '_children' in self.__dict__:
 
             loading = self.getRepositoryView().isLoading()
-            current = self.getItemChild(name, not loading)
-                
-            if current is not None:
+            if self._children.resolveAlias(name, not loading):
                 raise ValueError, "A child '%s' exists already under %s" %(item._name, self.itsPath)
 
         else:
-            self._children = Children(self)
+            self._children = self.getRepositoryView()._createChildren(self)
 
-        self._children.__setitem__(name, item, previous, next)
+        self._children.__setitem__(item._uuid, item, previous, next, name)
 
-        if '_notChildren' in self.__dict__ and name in self._notChildren:
-            del self._notChildren[name]
-            
         return self.itsRoot
 
     def _removeItem(self, item):
 
-        name = item._name
-        del self._children[name]
-
-        if '_notChildren' in self.__dict__:
-            self._notChildren[name] = name
-        else:
-            self._notChildren = { name: name }
+        del self._children[item._uuid]
 
     def getItemChild(self, name, load=True):
         """
@@ -1924,17 +1904,7 @@
 
         child = None
         if '_children' in self.__dict__:
-            child = self._children.get(name, None, False)
-
-        if load and child is None:
-            hasNot = '_notChildren' in self.__dict__
-            if not (hasNot and name in self._notChildren):
-                child = self.getRepositoryView()._loadChild(self, name)
-                if child is None:
-                    if not hasNot:
-                        self._notChildren = { name: name }
-                    else:
-                        self._notChildren[name] = name
+            child = self._children.getByAlias(name, None, load)
 
         return child
 
@@ -2216,16 +2186,8 @@
                 self._status |= Item.MERGED
                 
             if newDirty == Item.VDIRTY:
-                mergeNewOld('attribute')
-            elif newDirty == Item.RDIRTY:
-                mergeNewOld('ref')
-            elif newDirty == Item.VRDIRTY:
                 mergeNewOld('attribute', 'ref')
             elif oldDirty == Item.VDIRTY:
-                mergeOldNew(Item.VDIRTY, 'attribute')
-            elif oldDirty == Item.RDIRTY:
-                mergeOldNew(Item.RDIRTY, 'ref')
-            elif oldDirty == Item.VRDIRTY:
                 mergeOldNew(Item.VRDIRTY, 'attribute', 'ref')
             else:
                 raise NotImplementedError, "merge %0.4x:%0.4x" %(oldDirty,
@@ -2264,33 +2226,17 @@
                 xmlTag('class', { 'module': self.__module__ },
                        type(self).__name__, generator)
 
-        attrs = {}
-        parent = self.itsParent
-        parentID = parent.itsUUID.str64()
-
-        if not isDeleted:
-            if parent._isItem():
-                link = parent._children._get(self._name)
-                if link._previousKey is not None:
-                    attrs['previous'] = link._previousKey
-                if link._nextKey is not None:
-                    attrs['next'] = link._nextKey
-
-            if '_children' in self.__dict__:
-                children = self._children
-                if children._firstKey is not None:
-                    attrs['first'] = children._firstKey
-                if children._lastKey is not None:
-                    attrs['last'] = children._lastKey
-
-        xmlTag('container', attrs, parentID, generator)
+        attrs = { 'type': 'uuid' }
+        if '_children' in self.__dict__:
+            attrs['container'] = 'True'
+            if mode == 'save':
+                self._children._saveValues(version)
 
-        if not isDeleted:
-            if save & Item.VDIRTY:
-                self._values._xmlValues(generator, withSchema, version, mode)
-            if save & Item.RDIRTY:
-                self._references._xmlValues(generator, withSchema, version,
-                                            mode)
+        xmlTag('parent', attrs, self.itsParent.itsUUID.str64(), generator)
+            
+        if not isDeleted and save & Item.VRDIRTY:
+            self._values._xmlValues(generator, withSchema, version, mode)
+            self._references._xmlValues(generator, withSchema, version, mode)
 
         generator.endElement('item')
 
@@ -2317,15 +2263,15 @@
                 self._references._unload()
             repository._unregisterItem(self)
 
-            self._parent._unloadChild(self._name)
+            self._parent._unloadChild(self)
             if '_children' in self.__dict__ and len(self._children) > 0:
                 repository._registerChildren(self._uuid, self._children)
 
             self._status |= Item.STALE
 
-    def _unloadChild(self, name):
+    def _unloadChild(self, child):
 
-        self._children._unload(name)
+        self._children._unload(child)
 
     def _refDict(self, name, otherName=None, persist=None):
 
@@ -2366,8 +2312,8 @@
     SCHEMA     = 0x0020
     NEW        = 0x0040
     STALE      = 0x0080
-    SDIRTY     = 0x0100           # name of sibling(s) changed
-    CDIRTY     = 0x0200           # parent or first/last child changed
+    NDIRTY     = 0x0100           # parent or name changed
+    CDIRTY     = 0x0200           # children list changed
     RDIRTY     = 0x0400           # ref collection changed
     MERGED     = 0x0800
     SAVED      = 0x1000
@@ -2376,7 +2322,7 @@
     NODIRTY    = 0x8000           # turn off dirtying
     
     VRDIRTY    = VDIRTY | RDIRTY
-    DIRTY      = VDIRTY | RDIRTY | SDIRTY | CDIRTY
+    DIRTY      = VDIRTY | RDIRTY | NDIRTY | CDIRTY
     SAVEMASK   = DIRTY | ADIRTY | NEW | DELETED | SCHEMA
 
     __access__ = 0L
@@ -2465,23 +2411,27 @@
 
 class Children(LinkedMap):
 
-    def __init__(self, item, dictionary=None):
+    def __init__(self, item):
 
-        super(Children, self).__init__(dictionary)
+        super(Children, self).__init__()
         self._item = item
 
     def _setItem(self, item):
 
+        assert item._uuid == self._item._uuid
         self._item = item
+
         for link in self._itervalues():
             link._value._parent = item
         
     def linkChanged(self, link, key):
 
-        if key is None:
-            self._item.setDirty(Item.CDIRTY, None)
-        else:
-            link._value.setDirty(Item.SDIRTY, None)
+        self._item.setDirty(Item.CDIRTY, None)
+
+    def _unload(self, child):
+
+        link = super(Children, self)._unload(child._uuid)
+        del self._aliases[child._name]
     
     def __repr__(self):
 
@@ -2509,8 +2459,11 @@
 
     def _load(self, key):
 
-        if self._item.getRepositoryView()._loadChild(self._item,
-                                                     key) is not None:
+        if self._item.getRepositoryView()._loadItem(key) is not None:
             return True
 
         return False
+
+    def _saveValues(self, version):
+
+        pass

Index: chandler/repository/tests/TestMove.py
diff -u chandler/repository/tests/TestMove.py:1.1 chandler/repository/tests/TestMove.py:1.2
--- chandler/repository/tests/TestMove.py:1.1	Tue Feb  3 19:37:52 2004
+++ chandler/repository/tests/TestMove.py	Thu Sep  2 10:34:26 2004
@@ -2,8 +2,8 @@
 Text blocked read of appended storage compression unit tests
 """
 
-__revision__  = "$Revision: 1.1 $"
-__date__      = "$Date: 2004/02/04 03:37:52 $"
+__revision__  = "$Revision: 1.2 $"
+__date__      = "$Date: 2004/09/02 17:34:26 $"
 __copyright__ = "Copyright (c) 2003 Open Source Applications Foundation"
 __license__   = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
 
@@ -25,10 +25,12 @@
         cineguidePack = os.path.join(self.testdir, 'data', 'packs',
                                      'cineguide.pack')
         self.rep.loadPack(cineguidePack)
-        self.rep.commit()
-
+        
     def move(self, withCommit):
 
+        if withCommit:
+            self.rep.commit()
+            
         c = self.rep['CineGuide']
         k = c['KHepburn']
         m = k.movies.first()
@@ -55,6 +57,14 @@
     def testMove(self):
         self.move(False)
 
+    def testReopenCommit(self):
+        self._reopenRepository()
+        self.move(True)
+
+    def testReopen(self):
+        self._reopenRepository()
+        self.move(False)
+
 
 if __name__ == "__main__":
 #    import hotshot

Index: chandler/repository/util/LinkedMap.py
diff -u chandler/repository/util/LinkedMap.py:1.13 chandler/repository/util/LinkedMap.py:1.14
--- chandler/repository/util/LinkedMap.py:1.13	Wed Jul 21 14:34:29 2004
+++ chandler/repository/util/LinkedMap.py	Thu Sep  2 10:34:27 2004
@@ -1,6 +1,6 @@
 
-__revision__  = "$Revision: 1.13 $"
-__date__      = "$Date: 2004/07/21 21:34:29 $"
+__revision__  = "$Revision: 1.14 $"
+__date__      = "$Date: 2004/09/02 17:34:27 $"
 __copyright__ = "Copyright (c) 2002 Open Source Applications Foundation"
 __license__   = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
 
@@ -17,6 +17,7 @@
 
             self._previousKey = self._nextKey = None
             self._value = value
+            self._alias = None
 
         def __repr__(self):
 
@@ -41,13 +42,12 @@
             linkedMap.linkChanged(self, key)
 
 
-    def __init__(self, dictionary=None):
+    def __init__(self):
 
         super(LinkedMap, self).__init__()
-        self._firstKey = self._lastKey = None
 
-        if dictionary is not None:
-            self.update(dictionary)
+        self._firstKey = self._lastKey = None
+        self._aliases = None
 
     def __repr__(self):
 
@@ -102,7 +102,8 @@
 
         return self._get(key, load)._value
 
-    def __setitem__(self, key, value, previousKey=None, nextKey=None):
+    def __setitem__(self, key, value,
+                    previousKey=None, nextKey=None, alias=None):
 
         link = super(LinkedMap, self).get(key)
 
@@ -125,6 +126,13 @@
 
             super(LinkedMap, self).__setitem__(key, link)
 
+        if alias:
+            link._alias = alias
+            if self._aliases is None:
+                self._aliases = { alias: key }
+            else:
+                self._aliases[alias] = key
+
         return link
 
     def place(self, key, afterKey=None):
@@ -183,6 +191,9 @@
                 
         super(LinkedMap, self).__delitem__(key)
 
+        if link._alias is not None:
+            del self._aliases[link._alias]
+
         return link
 
     def has_key(self, key, load=True):
@@ -205,6 +216,52 @@
 
         return default
 
+    def getByAlias(self, alias, default=None, load=True):
+        """
+        Get the value referenced through its alias.
+        
+        @param alias: the alias of the item referenced.
+        @type key: a string
+        @param default: the default value to return if there is no value
+        for C{key} in this collection, C{None} by default.
+        @type default: anything
+        @param load: if the value exists but hasn't been loaded yet,
+        this method will return C{default} if this parameter is C{False}.
+        @type load: boolean
+        @return: a value of the collection or C{default}
+        """
+        
+        key = None
+
+        if self._aliases is not None:
+            key = self._aliases.get(alias)
+            
+        if key is None and load:
+            key = self.resolveAlias(alias, load)
+
+        if key is None:
+            return default
+            
+        return self.get(key, default, load)
+
+    def resolveAlias(self, alias, load=True):
+        """
+        Resolve the alias to its corresponding reference key.
+
+        @param alias: the alias to resolve.
+        @type alias: a string
+        @param load: if the value exists but hasn't been loaded yet,
+        this method will return C{None} if this parameter is C{False}.
+        @type load: boolean
+        @return: a key into the collection or C{None} if the alias does not
+        exist.
+        """
+        
+        if self._aliases:
+            return self._aliases.get(alias)
+
+        return None
+
     def firstKey(self):
         "Return the first key of this mapping."
 

Index: chandler/repository/util/SAX.py
diff -u chandler/repository/util/SAX.py:1.4 chandler/repository/util/SAX.py:1.5
--- chandler/repository/util/SAX.py:1.4	Thu May 13 23:34:27 2004
+++ chandler/repository/util/SAX.py	Thu Sep  2 10:34:27 2004
@@ -1,6 +1,6 @@
 
-__revision__  = "$Revision: 1.4 $"
-__date__      = "$Date: 2004/05/14 06:34:27 $"
+__revision__  = "$Revision: 1.5 $"
+__date__      = "$Date: 2004/09/02 17:34:27 $"
 __copyright__ = "Copyright (c) 2002 Open Source Applications Foundation"
 __license__   = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
 
@@ -34,6 +34,12 @@
 
         return self.exception is not None
 
+    def parse(self, xml):
+
+        createPushParser(self, xml, len(xml), 'filter').parseChunk('', 0, 1)
+        if self.errorOccurred():
+            raise self.saxError()
+        
     def saxError(self):
 
         try:
@@ -190,12 +196,6 @@
 
         raise NotImplementedError, 'XMLFilter.output'
 
-    def parse(self, xml):
-
-        createPushParser(self, xml, len(xml), 'filter').parseChunk('', 0, 1)
-        if self.errorOccurred():
-            raise self.saxError()
-        
     def endDocument(self):
 
         if self.cdata:



More information about the Commits mailing list