Tuesday, October 12, 2004

What's in a place? (peak.web)

There are several ways for a peak.web location to determine its URL:
  • By traversal: "my URL is whatever URL you used to get to me"
  • Relative to a location: "I'm here, relative to some known location"
  • By component context: "I'm a child of this other component"
  • Site root relative: "I'm this path from the top of the application"
  • Absolutely: "I know exactly where I am"
All of these serve essential purposes. By-traversal allows most components not to worry about location. By-location allows content objects to locate themselves relative to the nearest "specialist" serving objects of their kind. By-component-context allows resources in a skin layer (or locations in a site map) to refer themselves relative to a parent. Site root relative allows objects like a skin layer or a sitemap root to position themselves according to the application. True absolute positioning is useful for creating "mount points" into some other system, such as indicating that a set of static resources are actually located on a different server.

Some object types, however, need to play more than one role. For example, a Location object might be site-root relative (if it's the site root), or it might be by-component (if it's not). A ResourceDirectory might need to be absolute (if it's a "mount point"), or it might be by-component (normally), or even site-root relative (if it's the root of a skin layer).

For the by-component vs. site-root relative checks, I suppose these objects can distinguish themselves by seeing whether they have a non-empty component name. If it's empty, then they must be a site root (or something's broken). Hm. Perhaps we should have an interface, IPlace, that's something like:
class IPlace(Interface):
place_url = Attribute("""My URL relative to the site root""")
The idea is that place_url can be either a relative URL or an absolute URL, provided we use something like urlparse.urljoin() to join it with the application's base URL. Then, we can kill three formats with one stone:
  • By defining place_url as an attribute binding, it can be overridden by a constructor keyword, allowing an absolute URL to be set.
  • The binding can check whether self.getComponentName() is None, and if so, assume that the current component is the site root.
  • Otherwise, it can adapt its parent component to IPlace, and then compute its own URL relative to that. (If its parent isn't an IPlace, then something's wrong.)
This actually looks almost identical to the current web.IResource interface, but with a different name, different attribute name, and some slight tweaks to the URL computation.

Not bad. I guess I'll make it so!