[1] Apparemment, Web Objects ne fait plus partie du Framework Zoe, l'information disponible ci-dessous a donc surtout un but historique.
Note de David Medinets: Informations extraites de la liste Zoe Developer.
- L'unité de base de WebObjects? est un composant. Typiquement, un composant est constitué de trois parties: un template html (.html), un fichier de définitions (.szd) décrivant les liens entre l'html et le code Java, et finalement, une classe Java (.java).
- Pour définir une page ou autre, la technique utilisée s'appelle donc "Composition" (cad: un patchwork de composants associés ensembles). Il n'y a aucun html. l'HTML est généré par le framework sous-jacent.
- Pour comprendre comment fonctionne l'Interface Utilisateur (UI) de ZOE, le concept le plus important à saisir est la notion d'"inspector". Un "inspector" est un composant qui connait la liste des objets qu'il est capable d'afficher. Il fourni de plus toutes les informations relatives l'affichage d'un objet. Qu'est-ce que cela signifie en pratique ? La signification de tout cela, c'est que les relations entre les différents composant s sont résolus lors de l'éxecution (at runtime) via un "object link" (appelé aussi SZLink). Cela signifie aussi qu'il n'existe aucune référence (<a></a>) codée en dur dans Zoe. The "links" are resolved dynamically at runtime based on the type of object.
Lets take a closer look at
SZLink as an example of how an "inspector" works:
- SZLink component has only one mandatory binding which is what "object" you want to create a link for.
- From this object value, all the other informations are derived:
- Do I link to a external "href": SZInspector .hrefForObject
( this.value(), this.context() )
- Do I go to another internal "page":
SZInspector.inspectorNameForObject( this.value() )
- What description should I display for this link:
{{SZInspector .descriptionForObject( this.value() )}}
- And so on and so forth.
Example
The end result of all that would be, for example, a link to a "date" that could look like this:
Generated html rendered as "Sat Jul 27"
<a title="Saturday July 27th 2002"
href="/S/Z/ZO.E/SZ/98097B00010010D95D00EF005375CE55/2.0.5.1.1.1.
2.5.SZEnvelopeInspectorToolbar.5.1.0"><span class = "Label">Sat
Jul 27</span></a>
HTML template
<webobject name = "Date"></webobject>
The component definition
Date: SZLink
{
value = value.creationDate;
class = "Label";
};
So how does it work?
Lets take a look at
SZLink more closely:
- To figure out where to go, SZLink will ask SZInspector for a component name given an object: SZInspector.inspectorNameForObject() .
- SZInspector will query the runtime for the existence of a relevant component Class based on a naming convention: anObject.getClass() + aSuffix. In this case it will look for SZDateInspector? , the class of the value binding "SZDate", plus the standard inspector extension "Inspector". This is what SZInspector.inspectorClassWithObject() does
- with the help of SZRuntime.classForObjectInPackageWithSuffix() as I used this pattern quiet extensively.
- The same process will take place for all the other informations. For example to know what to display for a given link, SZLink will query SZInspector.descriptionForObject(). Again, {{SZInspector }} will retrieve which concrete inspector class handles a given object and ask this class for a description. Because there is no real class method in Java all this circus is done through the reflection API... :-( In any case, SZInspector will retrieve a concrete inspector class (SZDateInspector?) and invoke its descriptionForObject() class method.
All the other
SZLink methods follow the same pattern.
This turn out to be quiet a powerful setup as it let the system deal with how exactly links should be resolve and free the developer from such trivial matters. To handle a new type of object simply add a new concrete inspector and the entire system will know how do deal with it... A great time saver... :-)
This concept is used all over the places. For example there is a pretty useful table component that takes a collection of objects and a list of keys and automatically create a table out of all this information with all the right links at the right place thanks to
SZLink. So to get a full blown table you simply define:
Envelopes: SZTable
{
list = envelopes;
keysDescription = "self|recipientNames.iterator.next|sentDate";
headersDescription = "Subject|Recipient|Date";
};
This is the definition used in the name inspector (
SZNameInspector?.szd) to display a list of all the messages for a given "name". The "list" binding point to a collection of envelopes, "keysDescription" are the different keys (aka method names) that you want to display and the optional "headersDescription" is simply the display name for those keys. For each item in the list, the table will dynamically invoke each keys (through key value coding, check
SZKeyValue?) and create an
SZLink for it. In turn,
SZLink will query
SZInspector and figure out what should be displayed exactly... Et voila.
Now, lets take a look at a typical inspector:
SZDateInspector? . This concrete inspector handles, er, date objects. In ZOE, that basically all the stuff you get when clicking on a date, the main page (which is a subclass of
SZDateInspector? ), the SZListInspector
? and so on.
The html template don't have much stuff in it:
- there is a "PageLayout?"
- a "List" (which is really a table)
- a "Month" (which handles the calendar)
- and several List components that deal with displaying all the
information on the right side of a typical ZOE page (eg threads, contributors, ...)
The definition file (
SZDateInspector?.szd) tells you exactly what those components are and where they get their data from:
PageLayout: PageLayout
{
title = title;
page = name;
pathComponents = pathComponents;
};
This component provides the overall layout of every single pages. It handles the header with all its elements, the footer and the content layout. The page itself (eg
SZDateInspector? ) only provide the content.
List: SZEnvelopeList
{
list = envelopes;
};
SZEnvelopeList? is a "custom made" table for displaying envelopes. It's like a table but specifically tailored for envelopes.
Month: Month
{
month = value;
};
This is the calendar component.
ThreadList: SZList
{
title = "Thread";
list = threads;
minimumSize = 0;
};
Finally,
SZList is a simple "list" component that only display one value in a list. It also handles the "more..." link and so on.
And that's it. Those are the only things you need to define to have a fully functional inspector page. There is one more component associated to an inspector: its toolbar. Check
SZDateInspector? Toolbar for more details. The header component will look at runtime for a toolbar component given a page name: so for "
SZDateInspector? " it will try to find a "
SZDateInspector? toolbar".