Skip to content

Simple Example Application

Matt Duquette edited this page Jun 14, 2017 · 3 revisions

An Example Application

The AMASE development kit includes examples to help AMASE developers understand the structure of AMASE and provide a starting point for custom AMASE applications. AMASE examples can be found in the examples directory of the development kit.

To setup and run the AMASE examples, create a Java project using your preferred development environment. For a feature rich free IDE, we suggest Netbeans but any development environment will work. Make sure you have a Java development kit version 7 or higher installed. If you are unfamiliar with Java development, it is highly recommended that you first familiarize yourself with Java through the many tutorials and references available online. AMASE uses advanced Java features and object-oriented principles that require thorough knowledge of Java.

Building a Simple AMASE Application

AMASE applications consist of a set of plugins designated through a configuration file. AMASE plugins are java classes that extend the base class avtas.amase.AmasePlugin. AMASE plugins can,

  • access configuration data,
  • communicate with other plugins via events,
  • provide GUI and menu items to the user
  • perform modeling, data collections, and many other AMASE functions

The simplest AMASE application is shown below. This tutorial will explain elements of an AMASE application through this example.

Sample Application Window

This application has a small set of plugins to enable loading scenarios and displaying information to the user. The application can be run using the SampleApp batch file in the examples folder of the run folder in the AMASE development kit. To run this application on the command line, one can also execute the following command (assuming the current directory is the AMASE development kit root folder):

java -cp dist/* avtas.app.Application --config config/examples/SamplePlugin

The application constructed of a small set of AMASE plugins. In the command above, note that the --config parameter points to the directory SamplePlugin. AMASE looks in the config directory for a file named Plugins.xml. The Plugins.xml file for this application contains the following:

<Plugins>
    <Plugin Class="avtas.amase.scenario.ScenarioManager"/>      
    <Plugin Class="avtas.amase.window.WindowService"/>
    <Plugin Class="avtas.amase.scenario.ScenarioEventViewer"/>
    <Plugin Class="avtas.amase.ui.IconManager"/>
    <Plugin Class="amase.examples.SamplePlugin">
        <AnyParameter>value</AnyParameter>
    </Plugin>   
</Plugins>

Plugins are loaded according to the fully qualified class name of the plugin. A compiled java class with the given name must be on the java classpath. Plugin entries can contain additional parameter information as XML children of the Plugin entry.

Several plugins interact to make the application work. For instance, the ScenarioManager enables loading scenario files through the File -> Open Scenario menu. Events read from the scenario file are published to the entire application via the Event Manager system. The Window service provides the main windows inside which plugins can place GUI elements. The IconManager enables the user to specify custom icons for entities in AMASE. Finally, the SamplePlugin entry is what we will use to explore AMASE plugins and capabilities in this example.

Life Cycle of a Plugin

When avtas.app.Application starts, it loads the plugins from the configuration ("Plugins.xml") file and calls the addedToApplication method to initialize the plugin. Note that xml data is passed to this method. In SamplePlugin, this method simply echos the contents to show the user how the data is passed. When other plugins are loaded, the applicationPeerAdded() method is called for every peer. For any plugins that were added previously, applicationPeerAdded() is also called.

If a peer is removed, applicationPeerRemoved() is called when the peer is removed from the context. The context is simply a container where plugins are stored and are notified of changes in the application.

A plugin (optionally) provides items to the application for the purposes of user interaction. The if method getGui() returns a Java component to provide a GUI display. This is typically a JPanel that contains user interface widgets, but can be any kind of Java component. The method getMenus() enables the user to add menus to the application menubar. Note that the plugin WindowService provides the functionality to manage menus and GUIs. the method getSettingsPanel can be overridden to provide a panel with settings tools. The method getIcon returns a custom icon for the plugin. Note that all of the GUI related methods are optional. Default implementations are provided in the base AmasePlugin class that return null. Simply override each method to return something meaningful.

If a plugin is removed from the application, then removedFromApplication is called.

When the application is shutdown, two plugin methods are involved. the method requestShutdown is first called on all loaded plugins. This returns true by default. If overridden, then shutdown logic can be performed here. For example, a plugin can ask the user if data should be saved. If the answer is no, then the plugin should return true (meaning it is okay to continue with shutdown). if the answer is "yes", then a dialog can be presented to allow the user to select a file. Any reply of "false" to this method will prevent the application from shutting down. Once the shutdown request is complete, the shutdown method is called, allowing plugins to perform final shutdown logic. Once this process begins, there is is no way to prevent the application from shutting down.

Application Events

The SamplePlugin provides a GUI to user that includes a button for every aircraft loaded in the scenario. Aircraft are specified in scenario files using the CMASI AirVehicleConfiguration object. When the ScenarioManager reads an AirVehicleConfiguration from the input file, it publishes it out to all other listeners that are registered with the Event Manager. The SamplePlugin listens for these and other events through its eventOccurred method.

   public void eventOccurred(Object event) {
        if (event instanceof SessionStatus) {
            SessionStatus ss = (SessionStatus) event;
            System.out.println("Time: " + ss.getScenarioTime() + ", state: " + ss.getState());
        }
        else if (event instanceof AirVehicleConfiguration) {
            AirVehicleConfiguration avc = (AirVehicleConfiguration) event;
            System.out.println("aircraft " + avc.getVehicleID() + " added to scenario.");
            addAircraftButton(avc);
        }
        else if (event instanceof ScenarioEvent) {
            ScenarioEvent scenario = (ScenarioEvent) event;
            System.out.println("scenario " + scenario.getSourceFile().getName() + " loaded.");
            buttonPanel.removeAll();
        }
    }

The event management system is a core feature of AMASE, and is the primary way in which plugins interact. Note that in this class, we handle SessionStatus, AirVehicleConfiguration, and ScenarioEvent objects. All other types of events are simply ignored. Using the java instanceof check is a convenient way to test for a particular type of message.

Timer calls

The SamplePlugin also includes two methods that are called by the timer during the simulation, step, and timerStateChanged. These methods are optional, and provide the plugin with high-resolution timing signals. The example application does not include a Timer facility, but if one were added, the plugin would print the time at every step, and print the change of the timer state when it started, paused, or rest.