Title: [commits] (vajda) [11108] - fixed bug 6210 (http://bugzilla.osafoundation.org/show_bug.cgi?id=6210)
Revision
11108
Author
vajda
Date
2006-07-10 13:58:07 -0700 (Mon, 10 Jul 2006)

Log Message

- fixed bug 6210 (http://bugzilla.osafoundation.org/show_bug.cgi?id=6210)

Modified Paths

Diff

Modified: branches/0.7alpha3/chandler/application/Utility.py (11107 => 11108)

--- branches/0.7alpha3/chandler/application/Utility.py	2006-07-10 20:46:24 UTC (rev 11107)
+++ branches/0.7alpha3/chandler/application/Utility.py	2006-07-10 20:58:07 UTC (rev 11108)
@@ -33,7 +33,7 @@
 # with your name (and some helpful text). The comment's really there just to
 # cause Subversion to warn you of a conflict when you update, in case someone 
 # else changes it at the same time you do (that's why it's on the same line).
-SCHEMA_VERSION = "215" # John: added bufferedDraw to BoxContainer
+SCHEMA_VERSION = "216" #vajda: refactored collections for dynamic source changes
 
 logger = None # initialized in initLogging()
 

Modified: branches/0.7alpha3/chandler/parcels/osaf/pim/collections.py (11107 => 11108)

--- branches/0.7alpha3/chandler/parcels/osaf/pim/collections.py	2006-07-10 20:46:24 UTC (rev 11107)
+++ branches/0.7alpha3/chandler/parcels/osaf/pim/collections.py	2006-07-10 20:58:07 UTC (rev 11108)
@@ -22,7 +22,7 @@
 from chandlerdb.item.c import Default
 from repository.item.Sets import \
     Set, MultiUnion, Union, MultiIntersection, Intersection, Difference, \
-    KindSet, ExpressionFilteredSet, MethodFilteredSet
+    KindSet, ExpressionFilteredSet, MethodFilteredSet, EmptySet
 from repository.item.Collection import Collection
 
 from osaf.pim.items import ContentItem
@@ -31,7 +31,6 @@
 DEBUG = logger.getEffectiveLevel() <= logging.DEBUG
 
 
-
 class ContentCollection(ContentItem, Collection):
     """
     The base class for Chandler Collection types.
@@ -107,7 +106,7 @@
             invitees,
             byRef=['contentsOwner', 'subscribers']
         ),
-        sharing = schema.Cloud( none = ["displayName"] ),
+        sharing = schema.Cloud(none=["displayName"]),
     )
 
     def __str__(self):
@@ -163,9 +162,7 @@
 
     set = schema.One(schema.TypeReference('//Schema/Core/AbstractSet'))
 
-    schema.kindInfo(
-        displayName=u"KindCollection"
-    )
+    schema.kindInfo(displayName=u"KindCollection")
 
     kind = schema.One(schema.TypeReference('//Schema/Core/Kind'))
     recursive = schema.One(schema.Boolean, defaultValue=False)
@@ -199,13 +196,9 @@
             item.delete(True)
 
 
-class DifferenceCollection(ContentCollection):
+class WrapperCollection(ContentCollection):
     """
-    A ContentCollection containing the set theoretic difference of two
-    ContentCollections.
-
-    The C{sources} attribute (a list) contains the ContentCollection
-    instances to be differenced.
+    A class for collections wrapping other collections
     """
 
     __metaclass__ = schema.CollectionClass
@@ -213,48 +206,15 @@
 
     set = schema.One(schema.TypeReference('//Schema/Core/AbstractSet'))
 
-    schema.kindInfo(
-        displayName=u"DifferenceCollection"
-    )
+    sources = schema.Sequence(ContentCollection, otherName='sourceFor',
+                              doc="the collections being wrapped",
+                              initialValue=[])
+    schema.addClouds(copying=schema.Cloud(byCloud=[sources]))
 
-    sources = schema.Sequence(ContentCollection, otherName='sourceFor')
-
-    schema.addClouds(
-        copying = schema.Cloud(byCloud=[sources]),
-    )
-
     def __init__(self, *args, **kwds):
 
-        super(DifferenceCollection, self).__init__(*args, **kwds)
+        super(WrapperCollection, self).__init__(*args, **kwds)
 
-        a, b = self.sources
-        setattr(self, self.__collection__, Difference(a, b))
-
-
-class MultiCollection(ContentCollection):
-    """
-    A ContentCollection containing the set theoretic union or intersection
-    of at least two ContentCollections.
-
-    The C{sources} attribute (a ref collection) contains the ContentCollection
-    instances to be combined and can be changed.
-    """
-
-    __metaclass__ = schema.CollectionClass
-    __collection__ = 'set'
-
-    set = schema.One(schema.TypeReference('//Schema/Core/AbstractSet'))
-
-    sources = schema.Sequence(ContentCollection,
-                              otherName='sourceFor', initialValue=[])
-
-    schema.kindInfo(displayName=u"UnionCollection")
-    schema.addClouds(copying = schema.Cloud(byCloud=[sources]))
-
-    def __init__(self, *args, **kwds):
-
-        super(MultiCollection, self).__init__(*args, **kwds)
-
         self._sourcesChanged_()
         self.watchCollection(self, 'sources', '_sourcesChanged')
 
@@ -267,7 +227,7 @@
             if op == 'add':
                 set = self._sourcesChanged_()
                 sourceChanged = set.sourceChanged
-                actualSource = set.findSource(source.itsUUID)
+                actualSource = set.findSource(sourceId)
                 assert actualSource is not None
                 for uuid in source.iterkeys():
                     view._notifyChange(sourceChanged, 'add', 'collection',
@@ -276,7 +236,7 @@
             elif op == 'remove':
                 set = getattr(self, self.__collection__)
                 sourceChanged = set.sourceChanged
-                actualSource = set.findSource(source.itsUUID)
+                actualSource = set.findSource(sourceId)
                 assert actualSource is not None
                 for uuid in source.iterkeys():
                     view._notifyChange(sourceChanged, 'remove', 'collection',
@@ -295,12 +255,83 @@
             self.sources.remove(source)
 
 
-class UnionCollection(MultiCollection):
+class SingleSourceWrapperCollection(WrapperCollection):
     """
+    A class for collections wrapping another collection
+    """
+
+    def _getSource(self):
+        sources = self.sources
+        if sources:
+            return sources.first()
+        return None
+    def _setSource(self, source):
+        sources = self.sources
+        if sources:
+            if sources.first() is source:
+                return
+            sources.clear()
+        if source is not None:
+            sources.append(source)
+    def _delSource(self):
+        self.sources.clear()
+    source = property(_getSource, _setSource, _delSource)
+
+    def __init__(self, *args, **kwds):
+
+        source = kwds.pop('source', None)
+        if source is not None:
+            kwds['sources'] = [source]
+
+        super(SingleSourceWrapperCollection, self).__init__(*args, **kwds)
+
+
+class DifferenceCollection(WrapperCollection):
+    """
+    A ContentCollection containing the set theoretic difference of two
+    ContentCollections.
+
+    The C{sources} attribute (a list) contains the ContentCollection
+    instances to be differenced.
+    """
+
+    schema.kindInfo(displayName=u"DifferenceCollection")
+
+    def _sourcesChanged_(self):
+
+        sources = self.sources
+        sourceCount = len(sources)
+
+        if sourceCount == 0:
+            set = EmptySet()
+        elif sourceCount == 1:
+            set = getattr(self, self.__collection__)
+            source = sources.first()
+            if instance(set, Difference):
+                if set._left[0] == source.itsUUID:
+                    set = Set(source)
+                else:
+                    set = EmptySet()
+            else:
+                set = Set(source)
+        elif sourceCount == 2:
+            a, b = self.sources
+            set = Difference(a, b)
+        else:
+            raise ValueError, 'too many sources'
+
+        setattr(self, self.__collection__, set)
+        return set
+
+
+class UnionCollection(WrapperCollection):
+    """
     A ContentCollection containing the set theoretic union of at least two
     ContentCollections.
     """
 
+    schema.kindInfo(displayName=u"UnionCollection")
+
     def _sourcesChanged_(self):
 
         sources = self.sources
@@ -308,11 +339,12 @@
 
         # For now, when we join collections with Union, we pull trash
         # out of the equation with withoutTrash()
-        if sourceCount == 1:
+        if sourceCount == 0:
+            set = EmptySet()
+        elif sourceCount == 1:
             set = Set(sources.first().withoutTrash())
         elif sourceCount == 2:
-            left = sources.first()
-            right = sources.next(left)
+            left, right = sources
             set = Union(left.withoutTrash(), right.withoutTrash())
         else:
             set = MultiUnion(*(source.withoutTrash()
@@ -322,12 +354,14 @@
         return set
 
 
-class IntersectionCollection(MultiCollection):
+class IntersectionCollection(WrapperCollection):
     """
     A ContentCollection containing the set theoretic intersection of at
     least two ContentCollections.
     """
 
+    schema.kindInfo(displayName=u"IntersectionCollection")
+
     def _sourcesChanged_(self):
 
         sources = self.sources
@@ -335,11 +369,10 @@
 
         # For now, when we join collections with Intersection, we pull trash
         # out of the equation with withoutTrash()
-        if sourceCount == 1:
-            set = Set(sources.first().withoutTrash())
+        if sourceCount < 2:
+            set = EmptySet()
         elif sourceCount == 2:
-            left = sources.first()
-            right = sources.next(left)
+            left, right = sources
             set = Intersection(left.withoutTrash(), right.withoutTrash())
         else:
             set = MultiIntersection(*(source.withoutTrash()
@@ -349,7 +382,7 @@
         return set
 
 
-class FilteredCollection(ContentCollection):
+class FilteredCollection(SingleSourceWrapperCollection):
     """
     A ContentCollection which is the result of applying a boolean predicate
     to every item of another ContentCollection.
@@ -366,49 +399,33 @@
     Failure to provide this list will result in missing notifications.
     """
 
-    __metaclass__ = schema.CollectionClass
-    __collection__ = 'set'
+    schema.kindInfo(displayName=u"FilteredCollection")
 
-    set = schema.One(schema.TypeReference('//Schema/Core/AbstractSet'))
-
-    schema.kindInfo(
-        displayName=u"FilteredCollection"
-    )
-
-    sources = schema.Sequence(ContentCollection, otherName='sourceFor')
-
     filterExpression = schema.One(schema.Text)
     filterMethod = schema.One(schema.Tuple)
     filterAttributes = schema.Sequence(schema.Symbol, initialValue=[])
 
-    schema.addClouds(
-        copying = schema.Cloud(byCloud=[sources]),
-    )
+    def _sourcesChanged_(self):
 
-    def __init__(self, *args, **kwds):
+        source = self.source
+        if source is None:
+            s = EmptySet()
+        else:
+            attrTuples = set()
+            for name in self.filterAttributes:
+                attrTuples.add((name, "set"))
+                attrTuples.add((name, "remove"))
+            attrs = tuple(attrTuples)
 
-        source = kwds.pop('source', None)
-        if source is not None:
-            kwds['sources'] = [source]
+            if hasattr(self, 'filterExpression'):
+                s = ExpressionFilteredSet(source, self.filterExpression, attrs)
+            else:
+                s = MethodFilteredSet(source, self.filterMethod, attrs)
 
-        super(FilteredCollection, self).__init__(*args, **kwds)
+        setattr(self, self.__collection__, s)
+        return s
 
-        attrTuples = set()
-        for i in self.filterAttributes:
-            attrTuples.add((i, "set"))
-            attrTuples.add((i, "remove"))
 
-        source = self.sources.first()
-        attrs = tuple(attrTuples)
-
-        if 'filterExpression' in kwds:
-            setattr(self, self.__collection__,
-                    ExpressionFilteredSet(source, self.filterExpression, attrs))
-        else:
-            setattr(self, self.__collection__,
-                    MethodFilteredSet(source, self.filterMethod, attrs))
-
-
 class AppCollection(ContentCollection):
     """
     AppCollections implement inclusions, exclusions, source,
@@ -626,35 +643,33 @@
     pass
 
 
-class IndexedSelectionCollection(ContentCollection):
+class IndexedSelectionCollection(SingleSourceWrapperCollection):
     """
     A collection that adds an index, e.g. for sorting items, a
     selection and visibility attribute to another source collection.
     """
 
-    __metaclass__ = schema.CollectionClass
-    __collection__ = 'set'
+    indexName = schema.One(schema.Symbol, initialValue="__adhoc__")
 
-    set = schema.One(schema.TypeReference('//Schema/Core/AbstractSet'))
+    def _sourcesChanged_(self):
+        
+        source = self.source
+        trash = schema.ns('osaf.pim', self.itsView).trashCollection
 
-    indexName   = schema.One(schema.Text, initialValue="__adhoc__")
-    source      = schema.One(ContentCollection, defaultValue=None)
-
-    def __init__(self, *args, **kwds):
-
-        super(IndexedSelectionCollection, self).__init__(*args, **kwds)
-
-        trash = schema.ns('osaf.pim', self.itsView).trashCollection
-        if (isinstance(self.source, MultiCollection) and
-            trash not in self.source.sources):
+        if source is None:
+            set = EmptySet()
+        elif (isinstance(source, WrapperCollection) and
+              trash not in source.sources):
             # bug 5899 - alpha2 workaround: When SmartCollections are
             # wrapped with IntersectionCollection/UnionCollection,
             # they drop the trash. So we artificially insert it back
-            sourceMinusTrash = Difference(self.source, trash)
-            setattr(self, self.__collection__, sourceMinusTrash)
+            set = Difference(source, trash)
         else:
-            setattr(self, self.__collection__, Set(self.source))
+            set = Set(self.source)
 
+        setattr(self, self.__collection__, set)
+        return set
+
     def getCollectionIndex(self, indexName=None):
         """
         Get the index. If it doesn't exist, create. Also create a RangeSet
@@ -716,7 +731,6 @@
             self.setDescending (currentIndexName, not self.isDescending(currentIndexName))
             self.setSelectionRanges(newRanges)
 
-
     def __len__(self):
 
         return len(self.getCollectionIndex())
@@ -748,7 +762,7 @@
     # Range-based selection methods
     # 
 
-    def getSelectionRanges (self):
+    def getSelectionRanges(self):
         """
         Return the ranges associated with the current index as an
         array of tuples, where each tuple represents a start and
@@ -756,7 +770,7 @@
         """
         return self.getCollectionIndex().getRanges()
         
-    def setSelectionRanges (self, ranges):
+    def setSelectionRanges(self, ranges):
         """
         Sets the ranges associated with the current index with
         C{ranges} which should be an array of tuples, where each
@@ -765,7 +779,7 @@
         """
         self.setRanges(self.indexName, ranges)
 
-    def isSelected (self, range):
+    def isSelected(self, range):
         """
         Returns C{True} if the C{range} is completely inside the selected
         ranges of the index.  C{range} may be a tuple: (start, end) or
@@ -774,7 +788,7 @@
         """
         return self.getCollectionIndex().isInRanges(range)
 
-    def addSelectionRange (self, range):
+    def addSelectionRange(self, range):
         """
         Selects a C{range} of indexes. C{range} may be a tuple:
         (start, end) or an integer index, where negative indexing
@@ -782,7 +796,7 @@
         """
         self.addRange(self.indexName, range)
 
-    def removeSelectionRange (self, range):
+    def removeSelectionRange(self, range):
         """
         Unselects a C{range} of indexes. C{range} may be a tuple:
         (start, end) or an integer index, where negative indexing
@@ -793,14 +807,14 @@
     # Item-based selection methods
     #
     
-    def setSelectionToItem (self, item):
+    def setSelectionToItem(self, item):
         """
         Sets the entire selection to include only the C{item}.
         """
         index = self.index (item)
         self.setRanges(self.indexName, [(index, index)])
 
-    def getFirstSelectedItem (self):
+    def getFirstSelectedItem(self):
         """
         Returns the first selected item in the index or C{None} if
         there is no selection.
@@ -827,13 +841,13 @@
                 for idx in range(start,end+1):
                     yield self[idx]
 
-    def selectItem (self, item):
+    def selectItem(self, item):
         """
         Selects an C{item} in the index.
         """
         self.addSelectionRange (self.index (item))
 
-    def unselectItem (self, item):
+    def unselectItem(self, item):
         """
         Unselects an C{item} in the index.
         """
@@ -843,7 +857,7 @@
     # index-based methods
     #
 
-    def __getitem__ (self, index):
+    def __getitem__(self, index):
         """
         Support indexing using [].
         """
@@ -852,7 +866,7 @@
         self.getCollectionIndex()
         return self.getByIndex(self.indexName, index)
 
-    def index (self, item):
+    def index(self, item):
         """
         Return the position of item in the index.
         """
@@ -863,7 +877,6 @@
         self.getCollectionIndex()
         return self.positionInIndex(self.indexName, item)
 
-
     def add(self, item):
         self.source.add(item)
 




_______________________________________________
Commits mailing list
[email protected]
http://lists.osafoundation.org/mailman/listinfo/commits

Reply via email to