After many more lines of code, much thought, and too many cigarettes, I believe I've got the final design of "Inklog" (damn, I need a better name for this) complete. Below is a written account of how I believe it will work at this point. Any comments or suggestions you might have will be appreciated.
Every transaction starts with a Transport. The server handling the transaction can either be implemented in the Transport itself (i.e. in a Jabber bot) or it can be external and eventually results in a call to a Transport (i.e. an Apache request, or an incoming Sendmail message).
Once the transaction makes it to the Transport it will use data supplied to it to determine the next step. In many cases, this will result in a call to a Directory.
The Directory will be given a lookup string and will respond with either a Redirect, a Request or an Error.
In the event of a Redirect, the Transport will either respond to the transaction and terminate, or it will contact the Directory again with the new lookup string.
In the event of an Error, the Transport will respond to the transaction and terminate.
In the event of a Request, the Transport will, most likely, call the Request's execute() method. This will result in the instantiation of an Action. Using various methods on that Action (at this point undetermined) it will verify the requestors permission to execute() this Action. If verified, a call to that Action's execute() method will be made. The Request will be passed to the Action as part of that call. In the event that access is denied the Transport will respond to the transaction and terminate.
At the end of the Actions execute() method, it will respond with a Forward, an Error or a View. Through the course of the Action calls to various models can be made. Addtionally, the Request can be altered and other Actions can be called upon.
In the event that an Error is returned, the Request will merely return this to the Transport.
In the event that a Forward is returned, the Request will analyze itself, and determine the new Action to be instantiated which will then be execute()d after verifying permissions.
In the event that a View is returned, the Request will use various methods of the View to determine if the requestor is authorized to see this View (perhaps this is not needed, as it may be enough to allow the Action to check this permission before returning the View). The View will then have its execute() method called.
The View's execute() method will select a Template for display. That template will be activated and the results returned to the View. If this is successful, the View will return a Response to the Request. If not, an Error will be returned which will be passed on to the Transport.
When a Response is returned, it will be handed off to the Transport. The Transport will analyze the Response and respond to the transaction accordingly and in whatever method is required for that partcular Transport (i.e. an Apache based transaction will simply have the data sent to STDOUT after sending various headers, a Sendmail based transaction will execute an SMTP connection in order to respond, and a Jabber transaction will, most likely, be reponded to via a return Jabber message). After sending a response, the Transport will terminate.
In most cases, it is the Transport's responsibility to insert requested Content Type information into the Request before calling its execute() method. This Content Type information will be used by the View to determine the proper output type. Additionally, smart Transports can use this information to respond appropriately in the event of an Error.