r5 - 23 Aug 2007 - 10:48:44 - RandyLetnessYou are here: OSAF >  Journal Web  >  ContributorNotes > RandyLetnessNotes > CosmoZeroPointSevenModelDocs

Cosmo 0.7 Architecture Notes

Changes from 0.6.1

  • ContentItem is now abstract
  • Files represented as FileItem instead of ContentItem
  • time-range indexes refactored and now stored on EventStamp
  • icalendar property indexes removed (this plus time-range index refactoring results in smaller db size)
  • new query api that uses new ItemFilter model

Source Structure

The cosmo source code is organized into java packages. The major packages are:
package name description
org.osaf.cosmo.model model objects
org.osaf.cosmo.service service api
org.osaf.cosmo.service.impl service api implementation
org.osaf.cosmo.dao dao api
org.osaf.cosmo.dao.hibernate hibernate dao implementation
org.osaf.cosmo.hibernate cosmo hibernate extensions
org.osaf.cosmo.acegisecurity.* cosmo acegi security extensions
org.osaf.cosmo.security security api used in cosmo
org.osaf.cosmo.security.impl security api implementation
org.osaf.cosmo.dav.* WebDAV/CalDAV protocol
org.osaf.cosmo.atom.* Atom protocol
org.osaf.cosmo.mc Morse Code protocol
org.osaf.cosmo.cmp CMP protocol
org.osaf.cosmo.ui.* Application code for Account Browser ui

The rest of this document is going to focus mainly on the model,service, and dao layers.


A User represents a Cosmo user. In addition to standard attributes such as username , email , firstName , and lastName , User contains a Set of Preference s which allow arbitrary attributes to be associated to a User . These preferences are mainly used by the ui. A Set of CollectionSubscription s provides a way to associate "subscription" collections to a user.


All content in Cosmo inherits from the abstract Item class. Item defines common attributes such as uid (unique identifier), name (used in DAV URI), displayName (item description), and common associations such as owner (user that created item), parents (collections that item belong to), attributes , tickets , and stamps .

A group of items is called a collection. Collections are modeled as items ( CollectionItem ) with an additional association children . Cosmo 0.7 supports items belonging to a multiple collections. HomeCollectionItem is a special CollectionItem that represents the root collection for a user. When a user is created a HomeCollectionItem is automatically created. It is possible to have collections within collections.

The abstract class ContentItem represents a piece of content. There are two implementations. FileItem represents a file with binary content. All files created through DAV are stored as FilteItem. NoteItem is the base for all pim (personal information manager) items. A personal information item includes notes, tasks, events, messages and any combination of these.

Implementation Notes
Items are mapped to the item table using a table per class hierarchy in Hibernate. This means all Item subclasses are mapped to the same table, and use a discriminator column ( itemtype ) to denote the item type for the row.


Item has a Map of Attribute objects, indexed by a QName . An Attribute can be associated to a single Item . QName is a composite key that represents a qualified name (namespace and local name). There are several Attribute implementations (String, Binary, Integer, etc) that are used to store different types of values. The polymorphic mapping allows any number of any mix of Attribute implementations to be associated to an item.

Implementation Notes
Attributes are mapped to the attribute table using a table per class hierarchy in Hibernate. All Attribute implementations are stored in the same table, and use a discriminator column ( attributetype ) to denote the attribute type for the row. There is a bi-directional association between Item and Attribute , with Item containing the inverse mapping. This means that Attribute is responsible for managing the association. Save, update and delete operations are cascaded to Attriubte from Item .


Item has a Set of Stamp objects. A stamp can be associated to a single Item . A stamp associates a related set of properties/attributes/methods to an Item . This is different from Attribute , which generally represents a single value. For example EventStamp , contains properties and apis relating to an event and MessageStamp contains properties related to an email message. The stamp model allows items to be stamped and unstamped with these related sets of properties throughout its life-cycle.

CalendarCollectionStamp is another stamp implementation that is usedto indicate that a CollectionItem is a calendar collection.

Like Attribute , the polymorphic mapping allows any number and mix of stamps to be associated to an Item .

Implementation Notes
Stamps are mapped to the stamp table using a table per class hierarchy in Hibernate. This means all item implementations are stored in the same table, and use a discriminator column ( stamptype ) to denote the stamp type for the row. EventStamp and CalendarCollectionStamp are mapped to secondary tables ( event_stamp and calendar_stamp ) that is joined to the primary stamp table. Note that not all Stamp implementations require a new table. MessageStamp is implemented by storing its data as item attributes. One benefit (or drawback depending on how you look at it) of this is that when a stamp is removed, the underlying attributes remain associated to the item, allowing the item to be "stamped" and "unstamped" without losing the stamp data. There is a bi-directional association between Item and Stamp with Item containing the inverse mapping. Like Attribute , stamp creation, modification and deletion is cascaded by Item .


Item has a set of associated Ticket objects. A ticket can be associated to a single Item . A ticket is an authorization object that grants some level of access to an item and its descendents based on a unique ticket key. If a client has this key, then the client can gain access to the item and its descendants with the ticket key.

Implementation Notes
Tickets are mapped to the tickets table. Ticket privileges are mapped to the ticket_privilege table. There is a bi-directional association between Item and Ticket , with Item containing the inverse mapping.

Colleciton Subscription

A User contains a set of CollectionSubscription s. A CollectionSubscription contains a ticket key and a collection uid. It is a way to associate a collection that is not owned by the user to the user. The ticket key provides the necessary authentication to access the collection.


Item has a set of associated Tombstone objects. A tombstone can be associated to a single Item . A tombstone is a way to represent that something existed and was removed from the item. The implementations are ItemTombstone , StampTombstone , and AttributeTombstone . ItemTombstone are added to CollectionItem and represent that an item was removed from the collection. StampTombstone and AttributeTombstone are used to represent that a stamp and attribute have been removed from the collection. Tombstones are used for synchronization purposes (think the morse code protocol) where a client only wants the changes from the last time it synchronized.

PIM Items

As stated before, NoteItem provides the basis for a pim item in Cosmo. Cosmo 0.7 supports the full range of pim items that Chandler supports. All pim items start out as a NoteItem . The NoteItem can be stamped as a task, event and message. A calendar event is represented by NoteItem stamped with EventStamp .

The EventStamp contains an ical4j Calendar object, which is an iCalendar component as defined in RFC 2445. The iCalendar component must contain a single VEVENT component (master event).

Note that this allows Cosmo to support events submitted using an external protocol such as CalDAV because the internal representation of an event is iCalendar. Cosmo preserves all valid iCalendar data.

Indexing Calendar Items

In order for Cosmo to provide useful queries such as a time-range query, it must be smart about indexing events. Cosmo 0.7 indexes events by calculating and storing extra data on the EventStamp during creation/modification of the event. This data includes a start and end date for the event and whether that event is recurring or floating (no timezone associated with the event).

Previous versions of Cosmo indexed every occurrence of a recurring event, which didn’t prove well for recurring events with no end (Cosmo only indexed a year or so). Cosmo 0.7 handles these events by expanding them during the query, allowing time-range queries well into the future.


Cosmo 0.7 uses Hibernate annotations (http://www.hibernate.org/397.html) on all the model classes ( org.osaf.cosmo.model ) to map Cosmo objects to database tables. This frees us from the use of separate XML config files (as used in Cosmo 0.5).

All package level Hibernate configuration annotations are defined in org.osaf.cosmo.model.package-info.java . This includes named queries and custom types.

Cosmo utlizes Hiberate's second level and query caches. The cache implementation used is Ehcache, which can be configured using echache.xml .

Cosmo 0.7 has been developed and tested on Derby, MySQL? 5 (InnoDB?), and PostgreSQL? 8.2 databases. Cosmo relies on Hibernate's auto schema generation to create the database schema at startup (see DbInitializer.java ). Hibernate uses the annotations defined on all the model objects to automatically generate and execute the ddl statements that define the Cosmo schema. Because one of the goals for Cosmo is to support multiple databases, the database schema is not as optimized as is could be. We have to support the least common denominator, which means no custom triggers, stored procedures, or anything that is database specific that isn't handled by Hibernate's dialect abstraction.

Cosmo makes extensive use of Hibernate's lazy-loading feature. This means associations such as children , parents, attributes, stamps, etc aren't loaded until they are needed. This allows additional data to be loaded from the db without requiring additional service calls. Cosmo uses the "Open Session in View" pattern to allow lazing loading outside of the service layer. This means a new Hibernate session is created for each request and kept open for the duration (implemented as a servlet filter).

DAO Layer

The DAO layer in Cosmo provides the basic CRUD operations for the model objects. The main DAOs in Cosmo are UserDao and ContentDao . UserDao handles all User CRUD operations and ContentDao handles the ContentItem CRUD operations. There is also a CalendarDao that provides special calendar object query apis. The only consumer of the DAO layer is the Service layer. That is, the only code that uses DAO objects is the Service layer.

Implementation Notes
Cosmo provides a Hibernate based implementations for the DAOs. These implementations extend from Spring's HibernateDaoSupport class.

more notes: CosmoZeroPointSevenDaoLayer

Service Layer

The service layer consists of UserService and ContentService and is what is exposed to the application. The transaction boundary in Cosmo is at the service layer, meaning each service call is a transaction. A service can utilize several DAOs. One example is UserService .createUser(), which needs to create a new User and create a new HomeCollection for that User .

more notes: CosmoZeroPointSevenServiceLayer

Implementation Notes
Cosmo uses Spring's declarative transaction management TransactionProxyFactoryBean for the service layer. There is no transaction code in any of the Cosmo service/dao implementation classes. Instead, transactional behavior is defined in Spring's applicationContext.xml . For Cosmo, this means each method called on a service requires a transaction to be present, and will create a new transaction if one doesn't exist. Cosmo relies on transactions for atomicity. If a service method is called that updates multiple database tables and fails halfway through, the transaction is rolled back instead of leaving Cosmo in an invalid state. This requires the use of a database that supports transactions. For MySQL? this means using InnoDB? tables.



Application Framework

Cosmo utilizes the Spring framework extensively to instantiate and configure the majority of the service/dao layer objects. An example is the Hibernate SessionFactory (no hibernate.cfg.xml file as everything is configured in Spring's applicationContext.xml).

-- RandyLetness - 20 Aug 2007

toggleopenShow attachmentstogglecloseHide attachments
Topic attachments
I Attachment Action Size Date Who Comment
gifgif cosmo7db.gif manage 97.6 K 20 Aug 2007 - 10:10 RandyLetness cosmo 7 db schema
Edit | WYSIWYG | Attach | Printable | Raw View | Backlinks: Web, All Webs | History: r5 < r4 < r3 < r2 < r1 | More topic actions
Open Source Applications Foundation
Except where otherwise noted, this site and its content are licensed by OSAF under an Creative Commons License, Attribution Only 3.0.
See list of page contributors for attributions.