My comments inline
On Jun 30, 2005, at 6:40 PM, Alec Flett wrote:
A bunch of us met thursday afternoon to discuss ItemCollection further.
I was asked to capture the (hopefully) shared understanding of the decisions that were made. Before these are rolled into the spec, please read the attached document.. hopefully we're all on the same page.
Thanks for capturing this, Alec.
Alec
ItemCollection decisions
Date: 6/30/2005
Attending: Katie, John, Ted, Morgen, Grant, Philippe, Alec
This meeting was to discuss open issues regarding ItemCollection. The following diagram gives a visual representation for how the Sidebar intersects facets to show the user a resulting collection.
| All | Tasks | Mail | Calendar |
| All | | | | | |
| In | | | | | |
| Out | | | | V |
| Home | ---- | ---- | ---> | Calendar & Home |
| Work |
Issues and Questions
The following specific questions were brought to the table.
- How does a view know what "collection" to use for additions or removals, when views typically deal with "filtered" versions of existing item collections?
- How to store metainformation in an item collection? Examples include color, sharing data, ZaoBao URL, etc
1. Adding/removing from collections
The Problem: When a view (i.e. the calendar view) needs to create or remove an item, how does it know what collection to add or remove it from? Views typically deal with ephemeral collections of items which are filtered versions of real collections.
For example, if a user has clicked the "Home" collection in the sidebar and the "Calendar" filter button in the toolbar, then it is dealing with a collection that is an intersection of all items in the Home collection that are also CalendarEvents. If a new item is created, how does it know to add that item to the "Home" collection, and not this ephemeral "Home and Calendar" collection?
The question of "how" has two facets:
1.1. How does the Calendar view get back to the "Home" collection from the "Home and Calendar" collection?
i.e. how does it find the "context" of the add?
Decision
The sidebar will notify the view about what collection should be used for add/delete, as a part of the SetContents event. Currently, the SetContents event passes along just the ephemeral collection in the "items" parameter to the event. Now, the real collection will also be passed along as another parameter.
Reasoning
It was decided that the "add" is really a user-level event that the user sees as add or removal from whatever is displayed in the sidebar. The user doesn't think about the add/delete only within the context of the ephemeral collection. So really, the add or delete is an action at the level of the view, not the collection. This means it is the responsibility of the UI that is managing the view's contents (i.e. its the Sidebar's responsibility because it tells the calendar view what data to deal with)
I completely agree with this
1.2. Given the context (i.e. the "real collection") of the add/delete, What does the calendar actually do with this context to indicate that the add should happen?
Decision
The view will call the add() or remove() method on the "real" collection. For example, realcollection.add(newItem).
Reasoning
There was some discussion about what makes an item a member of a collection, and that membership is really just a facet of the item. That facet could be represented by an attribute that matches a rule. In fact, that facet could be any arbitrary facet that matches a query.
I don't think that membership is a facet of an item. An item has facets which determine whether that item is a member of a particular collection. Two possible implementations of facets are:
1. one collection per facet
2. setting the value of an attribute. There are multiple ways to implement this one. One is to add adhoc attributes to the item, the other is to have a refcollection (call it facets) of the collections that the item is a member of. So adding the item to a collection means placing a ref to the collection in facets.
Also, any attribute of an item potentially determines a facet, regardless of which of 1 or 2 we pick.
For instance the "label" attribute might be set to "Home" and if there was a rule on the "Home" collection saying that all items with the label "Home"
So that brings us back to the question, do we explicitly add an item to an itemcollection, or do we do something like set an attribute?
The choices end up being:
collection.add(item) item.label=collectionName (or any other variation where you're setting an attribute on "item")
The problem is, that there may be any one of a number of properties of an item that make it a member of a collection. The sidebar, which "manages" these collections seemed like one candidate because it kind of "owns" its ItemCollection. But ultimately, this isn't a function of the view, this is really a function of the original collection.
Furthermore, even if we were to use item.label=... or some other convention, if that convention changed we'd have to update all the users of that convention.
Since it seems to be the responsibility of a collection to know what makes an item a member, then it should also have responsibility for the add/remove operations, by performing the respective modification to that item. The obvious way to do this is with an add and remove method on the collection, and let the collection handle the messy details of the actual add or delete.
I don't think we want a convention that can get out of sync. That's why I prefer a refcollection.
3. When using attributes to denote collection membership, how should that attribute be used?
If some collections do determine membership by some simply query, like "All items whose label is pink" what convention should we use? What is the name and type of that attribute?
Decision
Ted and John and Alec will hash this one out. It looks like the choices right now are:
- A string:
item.label = collection.name? John prefers this for readability of the label, but it leaves open issues like: - What happens if an item is a member of multiple collections?
- What happens when the target collection goes away?
- What happens when the name of the collection changes
- A bidirectional attribute pointing directly to the collection:
item.collections.append(collection)? (like itemCollectionInclusions) Alec likes this because it leaves much of the lifetime management to the repository. - A list of uuids of itemcollections - maybe this is the same as bidirectional refs? Ted talked about this but I wasn't sure if it was the same
See #2
4. User level collections vs. other collections
What exactly is an "ItemCollection" in the context of the user's view of his/her data? There was some discussion of logically separating a user's collections (e.g. "Home") and the ephemeral collections (e.g. "CalendarEvents in Home")
Decision
Much of this comes down to implementation details. Alec and Katie saw a need for this, whereas John thought that when it comes to implementation, there won't be any need to make the distinction.
Katie and Alec imagined cases where a user might be presented with a list of his/her collections, and that you wouldn't want that list to include the ephemeral collections
Discussion
Perhaps the notion of UserCollection as a subclass of something called Collection would make sense? Kind queries could find them, and perhaps that is one place we could store color data, especially if UserCollection is more or less a special case of the just-subclass-collection to get meta information? Sort of Collection is to Item as UserCollection is to ContentItem?
I think that it make sense to have UserCollection as a subclass (subKind, really) of Collection. In the platform group we've been talking about various kinds of extensibility mechanisms based on querying items by Kind. We should have a uniform metaphor for this sort of thing throughout the whole system. If we query by Kind to discover extension points, it makes sense to query by Kind to discover all the UserCollections. We don't need a separate registry, the repository serves that function in a large number of cases.
Once we have a UserCollection Kind, that becomes the place to hang adhoc data that is associated with a Collection.
Alec's proposal
class Collection: the unit by which most items are collected together in an Item-based list. The most basic unit that can be treated like a set, queried against, and so forth. When seen in the wild, these collections are likely a subclass such as FilteredCollection()
This is what my wrappers implement today.
class UserCollection(Collection): a collection, as presented to the user. This may be the place for add/remove? These collections would be the ones that exist in the sidebar, and perhaps could contain some user-facing data like color. In many ways, UserCollection is just one case of the meta-data argument for subclassing item collections.
I agree that you want to distinguish UserCollections as a Kind from any old Collection, while continuing to support the same interface. I don't see how this turns into an argument for subclassing UserCollections all over the place.
class SpecialCollection(UserCollection): the base class for "All" "In" "Out" and so forth. Has dummy implementations of add()/remove() that either throw exceptions or do nothing. Has a string with an internal name of the specialness of the collection, such as "all", "in", "out" and so forth.
What is the use case for distinguishing a SpecialCollection from a UserCollection?
5. How and where will itemcollection metadata be stored?
Information about the item collection such as its color, label, etc, needs a home.
Decision
No real firm decision on this yet. But most were in favor of a system that hung the data off the collection somewhere, rather than in some global place. When the ZaoBao case of needing to store a URL with a collection was mentioned, everyone immediately said "Subclass ItemCollection!" So it seems like that might be the way to go.
That said, I wonder if we'll just want to subclass item collection for items that live in the sidebar for things like color. See Alec's proposal in section on User Collections vs. other collections.
I think that subclassing to add metadata is a bad idea. One of the things that we wanted to do in Chandler was to allow individual items to have ad-hoc attributes added to them. From what I understand, this was one of the motivating factors for the choice of Python. If that's the case, then it seems to me that requiring people to subclass in order to add meta-data is a step in the opposite direction. Suppose two parcels want to add some of he same metadata to a Collection? Now we have that nasty multiple inheritance stuff to deal with. These collections are just items. We should use whatever mechanism we are going to use for ad-hoc item attributes to solve this problem.
6. Special Collections - how to handle their special behavior, like All, In, Out, etc?
They may have special rules about how items are added, and so forth.
Decision
No real decision just yet, the issues haven't been flushed out.
I don't understand the use cases for Special Collections well enough to know whether this is really necessary.
Discussion
This is when Alec floated his idea of subclassing - see the section on User-level collections vs. other collections.
7. How will queries work on collections?
For instance, if the calendar wants to query all items in a collection, within a given date range?
Decision
Collections will be first class citizens with respect to queries - you'll be able to pass them in as parameters to queries, such as:
query = MakeQuery("for i in '%s' where i.startDate <= '3/3/2005 03:15", collection)
(Ted, did I get this right?
A Query is a predicate applied to a Set/Collection of items. In the new world, you will be able to apply predicates to any collection of item. At the moment this happens via a FilteredCollection kind which accepts the predicate as an argument. Right now my intention is to support the predicate language from the existing Query implemenatation. I have a feeling the Phillip may be interested in something more Pythonic, which may also be a possiblity. Concretely:
c = UserCollection(.....)
fc = FilteredCollection(c, "i.startDate < '3/3/2005 03:15'")
fc is itself a collection and can be used anywhere a collection would be used.
The existing query classes will go away, to be replaced by FilteredCollections of other types of Collections.
8. How will the autogeneration of recurring items happen?
We need a mechanism so that if you query a collection on a given date range, the appropriate recurring items are created.
Decision
Ted is trying to make a pluggable system so that when a given attribute (or is it Kind?) is searched, a callback mechanism can be triggered to allow the creation of the items before the query actually runs, so the query finds them.
I believe that this is feasible but have not worked out the precise details.
Ted