Customizing Bright Content

The Bright Content Store

Bright Content uses a simple pattern for storing XML, and more specifically Atom entries, using an AtomPub based store library. This library is based on Amplee, a generic AtomPub library that uses Atom as a model. The most important pieces we take from Amplee are:

  1. The Object Model
  2. The Indexes

The Amplee object model is simply a wrapper around Atom and AtomPub. There are Workspaces, Collections, and Entries that correlate directly with AtomPub semantics. This is in fact largely defined by an AtomPub Service Document that describes the workspaces and collections available. The second portion of the object model that is important is the storage mechanism. Amplee creates a generic storage API that is wrapped for slightly simpler interface. We keep Amplee's abstraction available so you can use its flexible storage features.

The use of indexes in Amplee is very simple. Essentilly, an index is simply a dict like object that has some query methods as needed in order to find an ID to dereference to a n actual Atom Entry. The value that is indexed is defined by a function in the indexer called "update".The function takes in the entry it is potentially going to index. This means you can index any detail within the Atom entry as well as potentially index content.

With this in place customizing the store involves a few general steps. The first step is to find any sort of indexes that might be queried through the "get_entries" function of the store. The indexes will need to be added to a StoreManager object. The StoreManager object is a business logic layer on top of the general store. The specific class should be named according to the application it is used for. A few examples are:

The StoreManager class should contain an internal Store object that is an instance of the Bright Content Store. This way a request to "get_entries" for example could process the arguments according to some rules before passing them along to the actual store. Likewise, extra query methods can be created as needed. The biggest aspect that is required of the StoreManager class is to provide any validation and composition of entry values for the actual application. The canonical example of this is the URLs found in the entry. Bright Content has traditionally chosen to have full URLs whenever possible. Yet, in the store, we prefer the URLs to be relative. This allows the StoreManager to make the connection between a potential development/production xml:base that needs to be used for resolving URLs without removing portability. This is exactly what occurs in the BlogStoreManager. It enforces the URL pattern of:

{year}/{month}/{day}/{slug}/

This allows decomposing/normalization of the values in the URL down to a unique ID that can be consistently queried in the Store. The result, is through this abstraction, the following works correctly:

/2007/2/3/My_Slug/
/2007/02/3/My_Slug/
/2007/2/03/My_Slug/

# all resolve to

year => 2007
month => 2
day => 3
slug => My_Slug

From the above, this allows us to use a simple stftime function to consistently translate back and forth between the URL and the ID of the entry. Also, in this case, we use the generated URL in the atom:link[@rel='alternate'] instead of the actual atom:id. Again, this is a conscience decision based on the fact the alternate links most likely refer to URLs "owned" by the Bright Content application. If this was not the case, then a slightly different StoreManager class could make the required changes as necessary.

This pattern is referred to as the Store and StoreManager pattern. By using this pattern we are able to remove the necessity to entirely understand the Amplee file dereferencing scheme. This pattern also allows you to layer the logic necessary for the store and customize the store interface as needed. Good examples of this pattern can be seen in all the core applications (brightcontent/core/application/*).

Bright_Content/Customization (last edited 2008-11-24 18:46:30 by localhost)