Application and Frame Classes

The starting points for a YASL application (see note) are the application class and the frame class.

Application Class

The application class extends org.yasl.arch.impl.application.YASLApplicationBase and implements the main() method.

The following must occur in the main() method:

  1. Create an instance of the the frame class.
  2. Create an instance of YASLSwingApplication. This interface is implemented by YASLSwingApplicationImpl and takes the frame class instance in its constructor.
  3. Create an instance of the application class, passing the YASLSwingApplication instance to the constructor.
  4. Call the startApplication() method on the application instance. At a minimum, this method makes a call to the frame class to init the user interface and calls setVisible(true) on the associated JFrame instance. A minimal version of this method is implemented in YASLApplicationBase. Most applications will not need to override this method.

The sample code below is drawn from the YASL Test Application which is used for architecture and component testing.

public class YASLTestApplication
    extends YASLApplicationBase {

  private YASLTestApplication(YASLSwingApplication swingApp)
      throws YASLApplicationException {
    super(swingApp, 
          "/org/yasl/testapp/config/yaslTestAppConfig.xml");
  }

  public static void main(String[] args) {
    try {
      // create frame and app
      YASLTestAppFrame appFrame = 
        new YASLTestAppFrame("/org/yasl/testapp/config/yaslTestAppMenuConfig.xml");
      YASLSwingApplication swingApp = new YASLSwingApplicationImpl(appFrame);
      YASLTestApplication application = new YASLTestApplication(swingApp);
      // start application
      application.startApplication();
    }
    // exceptions should be caught before this point
    // any exception that reaches this catch is catastrophic
    catch (Exception ex) {
      ex.printStackTrace();
    }
  }
}

YASLApplicationBase

The constructor for YASLTestApplication passes an instance of YASLSwingApplication and the fully-qualified name for an xml config file to the YASLApplicationBase constructor. Applications can be configured from xml files, code, or both. The xml config file passed to YASLApplicationBase configures the singletons and actions that the application will use. (See Actions and Singletons and XML Config for Singletons and Actions for detailed information.)

All constructors for YASLApplicationBase eventually call the constructor displayed below. The constructor performs the following steps:

  1. Sets the application instance in the singleton map using the key YASLApplication.KEY_APPLICATION.
  2. Tries to initialize the application's singletons and actions from an xml config file.
  3. Calls setSingletons() and setActions(). The default implementations of these methods do nothing. To configure from code, the Application Class must override these methods.
  4. Invokes the action mapped to the YASLApplication.KEY_ACTION_APPLICATION_START key if one is available. This action handles any initialization that the application needs to perform before presenting the UI to the user. Examples include reading preferences from a properties file or loading information from xml files.

private YASLApplicationBase(YASLApplication app,
                            String configFileName,
                            File configFile)
    throws YASLApplicationException {
  if (app == null) {
    throw new YASLApplicationException("app cannot be null");
  }
  this.app = app;
  this.app.setSingleton(YASLApplication.KEY_APPLICATION,
                        app);
  if (configFileName != null) {
    ConfigUtils.initFromConfigFile(
      new YASLConfigContentHandler(app),
      ConfigUtils.getInputSource(configFileName));
  }
  else if (configFile != null) {
    ConfigUtils.initFromConfigFile(
      new YASLConfigContentHandler(app),
      ConfigUtils.getInputSource(configFile));
  }
  // Call these methods after trying to config based on an
  // xml config file.
  setSingletons();
  setActions();
  // Call application start action to perform other types
  // of initialization
  Action action = (Action)app.getActionHandler().getActionByKey(
    YASLApplication.KEY_ACTION_APPLICATION_START);
  if(action != null) {
    action.actionPerformed(null);
  }
}

The startApplication method handles initializing the the user interface and starting the JFrame instance.

public void startApplication() throws Exception {
  YASLApplicationType appType = app.getApplicationType();
  switch (appType.getId()) {
    case YASLApplicationType.APP_TYPE_ID_SWING:
      YASLSwingApplication swingApp = getSwingApplication();
      swingApp.getSwingAppFrame().initUI();
      swingApp.getJFrame().setVisible(true);
      break;
    case YASLApplicationType.APP_TYPE_ID_APPLET:
      // no op
      break;
    case YASLApplicationType.APP_TYPE_ID_CMMNDLINE:
      // no op
      break;
  }
}

Frame Class

The frame class extends org.yasl.arch.impl.application.YASLSwingAppFrameImpl and is primarily responsible for handling menu initialization. The menu details are coded in an xml config file (see XML Config for Menus for detailed information) while the work of reading the config file is handled by the parent class (YASLSwingAppFrameImpl). The frame class need only pass the xml config file to its parent's constructor. Other tasks include:

  1. Setting the title bar text.
  2. Initializing the frame's display.
  3. Setting the menu bar.

These tasks are handled in the initUI(Map menuBarMap, Map menuMap) method. This is an abstract method in YASLSwingAppFrameImpl so frame classes must override it. The method is called by YASLSwingAppFrameImpl from its initUI() method. The map arguments passed into this method are created from the menu xml config file.

If you do not handle menu configuration via an xml file, then you should create and set your menus in the initUI(Map menuBarMap, Map menuMap) method.

The sample code below is drawn from the frame class associated with the YASL Test Application.

public YASLTestAppFrame(String menuConfigFileName) {
  super(menuConfigFileName);
}

protected void initUI(Map menuBarMap, Map menuMap)
    throws Exception {
  YASLSwingApplication yaslSwingApp = getSwingApplication();
  // set resource manager
  YASLResourceManager rmanager = yaslSwingApp.getResourceManager();
  // set title bar text
  this.setTitle(rmanager.getString(AppConstants.BUNDLE_GUI_STRINGS,
                                   "app.title.bar"));
  // get and set menubar
  JMenuBar menuBar = (JMenuBar) menuBarMap.get("main_menubar");
  this.setJMenuBar(menuBar);
}

YASLSwingAppFrame

This interface defines the methods that a frame class must implement in order to work with other classes in the architecture. It is implemented by YASLSwingAppFrameImpl.

public interface YASLSwingAppFrame {
  /**
   * Initializes the application menus and other parts of the
   * application's GUI.
   *
   * @throws Exception
   */
  public void initUI()
      throws Exception;

  /**
   * Returns the swing application instance associated with
   * this frame.
   *
   * @return YASLSwingApplication
   */
  public YASLSwingApplication getSwingApplication();

  /**
   * Returns this frame as a JFrame.
   * 
   * @return JFrame
   */
  public JFrame getJFrame();
}

YASLSwingAppFrameImpl

YASLSwingAppFrameImpl is the base class for frame classes. It extends javax.swing.JFrame and implements YASLSwingAppFrame and java.awt.event.WindowListener. Its primary responsibilities are:

The first task is handled in the initUI() method. After processing the xml config file, YASLSwingAppFrameImpl calls initUI(Map menuBarMap, Map menuMap) passing the menuBar and menu maps created during the xml processing. The initUI() method is final.

The second task is handled in the windowClosing(WindowEvent e) method. This method is invoked when the user attempts to close the window from the window's system menu. If an action has been mapped to YASLApplication.KEY_ACTION_APPLICATION_EXIT, the action will be invoked.

public final void initUI()
      throws Exception {
  YASLMenuConfigContentHandler contentHandler =
        new YASLMenuConfigContentHandler(swingApp);
  if (menuConfigFileName != null) {
    ConfigUtils.initFromConfigFile(
            contentHandler,
            ConfigUtils.getInputSource(menuConfigFileName));
  }
  else if (menuConfigFile != null) {
    ConfigUtils.initFromConfigFile(
            contentHandler,
            ConfigUtils.getInputSource(menuConfigFile));
  }
  initUI(contentHandler.getMenuBarMap(),
         contentHandler.getMenuMap());
}

/**
 * Invoked when the user attempts to close the window
 * from the window's system menu.  If the program does not
 * explicitly hide or dispose the window while processing
 * this event, the window close operation will be cancelled.
 */
public void windowClosing(WindowEvent e) {
  try {
      Action exitAction = swingApp.getActionHandler().getActionByKey(
              swingApp.KEY_ACTION_APPLICATION_EXIT);
      exitAction.actionPerformed(null);
  }
  catch (YASLApplicationException ex) {
      // log this and exit??
  }
}


Note: YASL can be used to write console applications, desktop applications, and applets. Unless otherwise noted, the documentation will focus on desktop applications.