3.3 Driving the Plug-in
To use our model statistics collection class we need to do several things:
    • Make the models statistics functionality available as an Eclipse action.
    • Perform the model traversal.
    • Record/report the results.
To make an Eclipse action we need to create a new class and to extend the plugin.xml file. The model traversal will be invoked and the model results reported from a method in the new action class. Of particular importance is reporting the results of the analysis performed by the plug-in. We have several options for making the results available:
    • Associate the results persistently with the model by using Eclipse markers. Markers are kept with the resource (file) and are shown by Eclipse in the Problem view. Clicking on a marker in this view causes the appropriate model object to be highlighted in an editor.
    • Store the result persistently as an AADL property in the model itself.
    • Record the results temporarily with the model through an adapter.
    • Store the results in a resource, i.e., file, in the Eclipse project workspace.
    • Display the results in a dialog box.
In this example we will illustrate the first and last options. Section 7 discusses these methods in more detail.
3.3.1 Eclipse Actions
We must implement an Eclipse action to make our model statistics functionality available to the user. We do this in two parts:
    • Implementing the Eclipse interface IWorkbenchWindowActionDelegate. This class will execute our model statistics code.
    • Describing our action in the plug-in’s plugin.xml file.
The interface IWorkbenchWindowActionDelegate declares methods that allow Eclipse to manage the lifecycle of the action. In particular, the method run(IAction) is invoked to actually execute the action. OSATE provides an abstract class AaxlReadOnlyAction, in package edu.cmu.sei.osate.ui.actions, that provides default implementations for all the action methods. The run implementation performs various sanity checks on the currently selected object and ensures that the necessary Eclipse resources are initialized before delegating to the abstract method doAaxlAction(AObject), which is passed the selected model object. The intent is that to implement an action, the programmer needs only to extend AaxlReadOnlyAction and override the doAaxlAction method. See the Javadoc for more information.
Class AaxlReadOnlyAction gets its name from the fact that any changes made to any models as a side effect of the action will not be saved. This allows actions to make temporary changes to the model to facilitate analyses. OSATE also provides the abstract class AaxlModifyAction that is the same as AaxlReadOnlyAction except that it saves any models modified by the action. Actions implemented as subclasses of either of these classes are triggered by first selecting a .aaxl file in the resource navigator or an AADL model element in an editor window, and then by executing the action by clicking on its icon in an Eclipse toolbar or by selecting the action’s menu item. When an .aaxl file is selected, doAaxlAction is passed the root element of the model contained in the file.
3.3.2 The Action Code
We define the DoModelStatistics class as a subclass of AaxlReadOnlyAction because it does not modify the model. Our action is applicable to all AADL model objects. If it is invoked on a declarative model object then the statistics of all the declarative model objects in the Eclipse workspace are computed. That is, all the declarative specifications, packages, and property sets in all the open projects will be analyzed. If the action is invoked on an instance model object then the statistics of the containing system instance only will be computed.
The first thing the action does is get the root object of the model containing the object obj passed to the action using the method AObject.getAObjectRoot(). This method returns an AadlSpec, SystemInstance, AadlPackage, or PropertySet object depending on whether the object is contained in an AADL specification, a system instance model, an AADL package definition, or an AADL property set definition, respectively. Our action attaches markers to this object.
The action next tries to get the SystemInstance, if any, that contains obj using AObject.getSystemInstance(). When obj comes from an instance model this is the same object as the model’s root object. When obj comes from a declarative model, package declaration, or property set declaration this method returns null. Our use of this method is redundant: we could have performed a type test using instanceof on the object referenced by root. We include it here, however, for pedagogical purposes.
The action then creates a new ModelStatistics object. If the si is non-null we have a system instance so we compute the statistics of the instance model. Otherwise, we use the method processPreOrderAllDeclarativeModels() to analyze all the AADL specifications, property set declarations, and package declarations in the workspace. The ModelStatistics object now contains the counts of the various elements in the model.
As mentioned above, we report the results using both Eclipse markers and a dialog box. To create a marker we simply invoke reportInfo(AObject, String). This creates an informative marker attached to the given model element with the given message. In this case we attach the results to the root model element. We create one marker for each category of model statistics. We can also create warning and error markers using the methods reportWarning and reportError. Creating and managing markers is further described in Section 8 Persistent Markers with AADL Models.
Finally, we report the results in a dialog box. We use the Eclipse convenience method openInformation(Shell, String, String) in class org.eclipse.jface.dialogs.MessageDialog to create and display the modal dialog box. The first parameter is the shell to use as the parent of the dialog box; we get this using the method AaxlReadOnlyAction.getShell(). The second parameter is the title of the dialog box. The final parameter is the message to display. In our case, the message is our accumulated list of model statistics results, so we use msg.toString() to convert the string buffer into a string. In general, you are free to use SWT to build any kind of window or dialog box you would like to display the results. A description of how to do so is beyond the scope of this document. The MessageDialog class provides many additional convenience methods, e.g., openError, that are suitable for reporting various kinds of analysis results.
package edu.cmu.sei.osate.statistics;

import org.eclipse.jface.dialogs.MessageDialog;

import edu.cmu.sei.aadl.model.core.AObject;
import edu.cmu.sei.aadl.model.instance.SystemInstance;
import edu.cmu.sei.osate.ui.actions.AaxlReadOnlyAction;

public class DoModelStatistics extends AaxlReadOnlyAction {
public void doAaxlAction(AObject obj) {
// Get the root object of the model
final AObject root = obj.getAObjectRoot();
// Get the system instance (if any)
final SystemInstance si = obj.getSystemInstance();

/* Create a new model statistics analysis object. Run it over the
* instance model if it exists. Otherwise, run it over all the
* declarative models in the workspace.
*/
final ModelStatistics stats = new ModelStatistics();
if (si != null) {
stats.processPreOrderAll(si);
} else {
stats.processPreOrderAllDeclarativeModels();
}
/* Accumulate the results in a StringBuffer, but also report them
* using info markers attached to the root model object.
*/
final StringBuffer msg = new StringBuffer();
if (si != null) {
final String appStats = stats.getApplicationResult();
final String epStats = stats.getExecutionPlatformResult();
reportInfo(root, appStats);
reportInfo(root, epStats);
msg.append(appStats);
msg.append(epStats);
} else {
final String modelStats = stats.getModelResult();
final String flowStats = stats.getFlowResult();
reportInfo(root, modelStats);
reportInfo(root, flowStats);
msg.append(modelStats);
msg.append(flowStats);
}

// Also report the results using a message dialog
MessageDialog.openInformation(
getShell(), "Model Statistics", msg.toString());
}
}