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 BusMember
s.
-
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 EventObject
s to BusMember
s. 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 -RESPONDING
group. -
-
- MONITORING
: Just listens for events, like a logger - or status monitor. -
-
- RESPONDING
: Process events in a default manner, - knowing that the event has passed anyVETOING
members. -
-
-
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 BusMember
s. 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 Action
s 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.
-