r3 - 14 Jul 2008 - 10:25:11 - RandyLetnessYou are here: OSAF >  Journal Web  >  ContributorNotes > RandyLetnessNotes > CosmoOneDotZeroModelDocs

Cosmo 1.0 Model Notes

Changes from 0.7

  • interfaces now used for model objects
  • acegi becomes spring security (same code/different name)
  • item authorization moved to security aspect (aop)
  • move from spring's TransactionProxyFactoryBean to spring's transactional advice (aop)

Source Structure

The cosmo source code is organized into java packages. The major packages are:

package name description
org.osaf.cosmo.model model object interfaces
org.osaf.cosmo.model.hibernate hibernate persistent implementation of model
org.osaf.cosmo.model.filter filter api
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 spring 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.webcal Webcal servlet
org.osaf.cosmo.ui.* Application code for Account Browser ui
org.osaf.cosmo.db Database initialization code
org.osaf.cosmo.calendar.* calendar utiltity classes/ ical4j extensions
org.osaf.cosmo.xml xml utilities

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


The model, service, and dao layers are made up of a bunch of interfaces, which are implemented using Hibernate as a database-backed persistence layer.


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.

Implementation Notes
Users are mapped to the users table using Hibernate.


All content in Cosmo inherits from Item. 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 , tombstones, and stamps .

A group of items is called a collection. Collections are modeled as items (CollectionItem) with an additional association children . Cosmo 1.0 supports items belonging to a multiple collections. The relationship is modeled by CollectionItemDetails, which allows additional properties to be associated to the relationship. HomeCollectionItem is a special CollectionItem that represents the root collection for a user. When a user is created a HomeCollectionItem is automatically created and becomes the root for all the user's resources. It is possible to have collections within collections.

ContentItem represents a piece of content. FileItem represents a file with binary content. All files created through DAV are represented 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. PIM items are treated differently by the server as these items are exposed via protocols like morse code/atom/ CalDAV. FileItem s are only exposed via DAV.

see hierarchy

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 and any mix of Attribute implementations to be associated to an item.

see hierarchy

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 used to 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 .

see hierarchy

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.

Collection 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.

see hierarchy

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

PIM Items

As stated before, NoteItem provides the basis for a pim item in Cosmo. Cosmo 1.0 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.

Cosmo uses ical4j extensively and it is essentially a core piece of the model. All complicated recursion code is either implemented in ical4j, or as extensions to ical4j.

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 1.0 indexes events by calculating and storing extra data on the BaseEventStamp 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 date (Cosmo only indexed a year or so). Cosmo 1.0 handles these events by expanding them during the query, allowing time-range queries well into the future.


EntityFactory is a bean factory used by the application layer, which is responsible for creating new instances of model classes. The implementation is of course HibEntityFactory, which creates Hibernate-persistent model objects.


Cosmo 1.0 uses Hibernate 3.2.6 as a persistence layer. To make hibernate configuration easier, cosmo uses Hibernate Annotations 3.3.1 (http://www.hibernate.org/397.html) on all the model implementation classes ( org.osaf.cosmo.mode.hibernate. ) to map Cosmo objects to database tables. Some benefits of using annotations are that no separate XML config files (as used in Cosmo 0.5) are required, and compile-time checking. Of course the drawback is that these classes are tied to the hibernate libraries, which means they can't be re-used without bringing the weight of hibernate.

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

Cosmo utilizes Hibernate's second level and query caches. The cache implementation used is Ehcache, which can be configured using echache.xml . Different caches can easily be plugged in by modifying the hibernate config in applicationContext.xml.

Cosmo 1.0 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 org.osaf.cosmo.db.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 one-to-many, many-to-many, and many-to-one associations such as children , parents, attributes, stamps, owner 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: CosmoOneDotZeroDaoLayer

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 .

Implementation Notes
Cosmo uses Spring's declarative transaction management using a transactional advice (aop) 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.

more notes: CosmoOneDotZeroServiceLayer



Application Framework

Cosmo utilizes the Spring 2.5 framework extensively to instantiate and configure the majority of the service/dao layer objects. All configuration is done in applicationContext.xml files. The spring context is loaded during startup and made available to the all servlets by using the org.springframework.web.context.ContextLoaderListener listener, which in configured in web.xml.

-- RandyLetness - 25 Jun 2008

Edit | WYSIWYG | Attach | Printable | Raw View | Backlinks: Web, All Webs | History: 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.