Design Overview
-- - Introduction -
-The purpose of this document is to communicate the overall - structure and design patters used in Antidote, the GUI for - Ant. This document is a work in progress, as well as a living - document, and it is most likely not be in full synchronization with - the source code. Therefore, if there is any doubt, view the source - ;-) -
-- - Overview -
-The Antidote architecture design aims to provide a high level - of modularity and extensibility. Ideally the components of - Antidote will be able to be assembled in different configurations - to provide the type of application or plug-in desired. -
-To achieve this modularity, a high level of decoupling is - necessary. The standard UI design approach of providing separation - of view (presentation) from model (data) is applied, leveraging - the built-in Ant data model where possible, as well as the - predefined Swing model interfaces. Furthermore, the architecture - is highly event driven, whereby modules communicate via a shared - communications channel. -
-To a large extent, the configuration of application modules is - driven by localized configuration files, allowing new modules or - data views to be added, as well as providing multi-language - support. -
-The diagram below conveys a high altitude view of the
- application's structure. As the application grows, new components
- will be plugged in to what will be described as the EventBus
-
- - Antidote Component Architecture/Event Bus -
-- +---------------+ +----------------+ +-------------+ +-------------+ - | | | | | | | | - | ActionManager | | EventResponder | | AntModule | | AntModule | - | | | | |(ProjectNav) | |(SourceEdit) | - +---------------+ +----------------+ +-------------+ +-------------+ - | ^ ^ ^ - | | | | - ActionEvent EventObject AntEvent AntEvent - | | | | - v v v v - /---------------------------------------------------------------------\ - / \ -< EventBus > - \ / - \---------------------------------------------------------------------/ - | ^ ^ ^ - | | | | - EventObject ChangeEvent BuildEvent EventObject - | | | | - v | | v - +---------------+ +----------------+ +-------------+ +--------------+ - | | | | | | | | - | Console | | ProjectProxy | | Ant | | (Your Module)| - | | | | | | | | - +---------------+ +----------------+ +-------------+ +--------------+ --
The backbone of the application is the EventBus. Any
- component of the application can post events to the
- EventBus. Components that wish to receive events are
- called BusMembers.
-
The EventBus will dispatch any object of type
- java.util.Event, which means that Ant BuildEvent
- objects, as well as AWTEvent objects can be posted (if desired). A
- new class of events called AntEvent is defined for Antidote
- specific events, which have the additional capability of being
- canceled mid-dispatch.
-
Each BusMember must provide a BusFilter instance,
- which is the members' means of telling the bus which
- events it is interested in. This allows a BusMember to,
- say, only receive AntEvent objects.
-
When a BusMember registers itself with the
- EventBus, it must provide a (so called) interrupt
- level which is a integer value defining a relative ordering
- for dispatching EventObjects to BusMembers. The
- purpose of this is to allow certain BusMember instances
- to see an event before others, and in the case of AntEvent
- objects, keep the event from propagating onward. The
- EventBus class defines the interrupt level constants
- VETOING=1, MONITORING=5, and RESPONDING=10 to
- help define categories of members. The implied purpose being that:
-
-
-
-
VETOING: Listens for certain types of events, and - may process them in a non-default manner to determine if the - event should be canceled before being dispatched to the -RESPONDINGgroup. -
-
- MONITORING: Just listens for events, like a logger - or status monitor. -
-
- RESPONDING: Process events in a default manner, - knowing that the event has passed anyVETOINGmembers. -
-
-
Within a specific interrupt level, the order in which members will
- receive events is undefined. A BusMember may be registered
- at a level that is +/- of one of the defined levels, as long as it
- follows the constraint MONITORING <= interruptLevel <=
- MAX_INTERRUPT.
-
- - Actions and ActionManager -
-Extensive use of the javax.swing.Action interface is
- made for defining the set of menu and tool bar options that are
- available. The configuration file action.properties
- exists to define what should appear in the menu and toolbar, how
- it is displayed, and the Action command name that is
- dispatched when the user invokes that action. A class called
- ActionManager exists for not only processing the
- configuration file, but also for dispatching invoked action events
- to the EventBus, and for controlling the enabled state of
- an Action. When a new menu item or toolbar button is
- desired, first it is added to the action.properties file,
- and then the code to respond to it is added to the
- EventResponder (see below).
-
- - Commands and EventResponder -
-At some point in the stages of event processing, an event may
- require the data model to be modified, or some other task be
- performed. The Command interface is defined to classify
- code which performs some task or operation. This is distinct from
- an Action, which is a user request for an operation. A
- Command class is the encapsulation of the operation
- itself.
-
When an Action generates an ActionEvent, the
- event is posted to the EventBus which delivers the event
- to all interested BusMembers. It eventually makes it to
- the EventResponder instance (registered at the
- RESPONDING interrupt level), which is responsible for
- translating specific events into Command objects, and
- then executing the Command object. For example, when the
- user selects the "Open..." menu option, an ActionEvent is
- generated by the Swing MenuItem class, which is then
- posted to the EventBus by the ActionManager. The
- ActionEvent is delivered to the EventResponder,
- which converts the ActionEvent into a Command
- instance. The EventResponder then calls the method
- Command.execute() to invoke the command (which displays a
- dialog for selecting a file to open).
-
When adding new Actions or general tasks to the
- application, a Command object should be created to
- encapsulate the behavior. This includes most operations which
- modify the state of the data model.
-
The purpose of this encapsulation is to allow the clean - separation of making a request, and servicing a request. Due to - various conditions in the application state, the actually response - to a request may change, as well as who services it. This - design approach facilitates that. -
-- - Data Model and Views -
-NB: This part of the architecture is not fleshed out very well. There
- needs to be a discussion of the degree to which the Antidote development
- should be able to impose changes on the Ant data model, and to what level
- that model should be mirrored in the Antidote code base. The coupling
- between them should be kept low, and at the same time changes to one should
- affect the other minimally. Still, features like property change events and
- bean introspection (or BeanInfo) may be needed to be added to the Ant data
- model. Right now the data model is encapsulated in the package
- org.apache.tools.ant.gui.acs (where "acs" stands for "Ant Construction Set").
-
- - Application Context -
-In order to keep the coupling among application modules to a
- minimum, a single point of reference is needed for coordination
- and data sharing. The class AppContext is the catch-all
- class for containing the application state. Most modules and
- Command classes require an instance of the
- AppContext class. Because all state information in
- contained in an AppContext instance, multiple instances
- of Antidote can run inside the same JVM as long as each has it's
- own AppContext. (Interestingly, two instances of the
- Antidote could conceivably share an AppContext instance
- through RMI, allowing remote interaction/collaboration.)
-
- - Configuration and ResourceManager -
-Full "i18n" support should be assumed in modern applications,
- and all user viewable strings should be defined in a configuration
- file. For Antidote this configuration file is
- antidote.properties, which is located (with other UI
- resources) in the sub-package "resources".
-
To aid in the lookup of text properties, as well as other
- resources like icons, a class called ResourceManager is
- defined. There are various convenience methods attached to this
- class, which will likely grow to make looking up configuration
- values as easy as possible.
-
The organization of configuration properties is based on the
- fully qualified path of the class that requires the property. For
- example, the "about" box contains a messages, so it looks for the
- property "org.apache.tools.ant.gui.About.message" for the text
- message it should display. Therefore, the ResourceManager
- method getString() takes a Class instance as
- well as a String key. Please see the
- ResourceManager documentation for more information. Given
- this support, no user visible strings should appear in the source
- code itself.
-


-