Let’s make a Plug-in to count classes in Astah

Let’s make another plug-in, this time one that counts the classes in Astah. This sample is for Astah Professional and Astah UML, but you can adapt it to count blocks in Astah SysML.

The sample model below contains three classes.
Sample model with three classes in a package

Now let’s make a Plug-in to count the classes and show the number like this:

"There are 3 classes"
section divider

Get model information

In order to get model information, you need to use Astah API. The Astah API is a set of Java interfaces for reading and writing Astah models; here we use it to count classes. For details, see the Astah API User Guide for your product:

We are going to write a code to get the root model of Astah by using ProjectAccessor and get all the classes under the root model recursively. Now let’s modify the “Hello World” Plug-in to make it show the number of classes from the menu instead.

First, create CountClassAction class.

/*
 * Please change this class's package to your generated Plug-in's package.
 * Plug-in's package namespace => com.example
 *   com.change_vision.astah.extension.plugin => X
 *   com.example                              => O
 *   com.example.internal                     => O
 *   learning                                 => X
 */
package com.example.actions;
 
import java.util.ArrayList;
import java.util.List;
import javax.swing.JOptionPane;
import com.change_vision.jude.api.inf.AstahAPI;
import com.change_vision.jude.api.inf.exception.ProjectNotFoundException;
import com.change_vision.jude.api.inf.model.IClass;
import com.change_vision.jude.api.inf.model.IModel;
import com.change_vision.jude.api.inf.model.INamedElement;
import com.change_vision.jude.api.inf.model.IPackage;
import com.change_vision.jude.api.inf.project.ProjectAccessor;
import com.change_vision.jude.api.inf.ui.IPluginActionDelegate;
import com.change_vision.jude.api.inf.ui.IWindow;
 
public class CountClassAction implements IPluginActionDelegate {
  public Object run(IWindow window) throws UnExpectedException {
    try {
      AstahAPI api = AstahAPI.getAstahAPI();
      ProjectAccessor projectAccessor = api.getProjectAccessor();
      IModel iCurrentProject = projectAccessor.getProject();
      List<IClass> classeList = new ArrayList<IClass>();
      getAllClasses(iCurrentProject, classeList);
      JOptionPane.showMessageDialog(window.getParent(),
          "There are " + classeList.size() + " classes.");
    } catch (ProjectNotFoundException e) {
      String message = "Please open a project";
      JOptionPane.showMessageDialog(window.getParent(), message,
          "Warning", JOptionPane.WARNING_MESSAGE);
      throw new CalculateUnExpectedException();
    } catch (Exception e) {
      JOptionPane.showMessageDialog(window.getParent(),
          "Exception occured", "Alert", JOptionPane.ERROR_MESSAGE);
      throw new UnExpectedException();
    }
    return null;
  }
 
  public class CalculateUnExpectedException
	extends UnExpectedException {
  }
 
  private void getAllClasses(INamedElement element, List<IClass> classList)
      throws ClassNotFoundException, ProjectNotFoundException {
    if (element instanceof IPackage) {
      for(INamedElement ownedNamedElement :
			((IPackage)element).getOwnedElements()) {
        getAllClasses(ownedNamedElement, classList);
      }
    } else if (element instanceof IClass) {
      classList.add((IClass)element);
      for(IClass nestedClasses : ((IClass)element).getNestedClasses()) {
        getAllClasses(nestedClasses, classList);
      }
    }
  }
}

Now, modify the plugin.xml with this CountClassAction class.

<?xml version="1.0" encoding="UTF-8"?>
<plugin>
  <extension point="com.change_vision.astah.ui.actionSets">
    <actionSet
        label="%action_set_label "
        visible="true"
        id="com.example.actions.actionSet1">
      <menu
        label="%sample_menu"
        id="sampleMenu"
        path="tool/sampleMenu">
      </menu>
      <action
        label="%count_classes"
        icon="icons/sample.gif"
        class="com.example.actions.CountClassAction"
        tooltip="Count classes"
        menubarPath="tool/sampleMenu/"
        id="com.example.actions.CountClassdAction">
      </action>
    </actionSet>
  </extension>
</plugin>

At last, add the label for this menu in plugin.properties:

count_classes=Count classes(C)

And now this new Plug-in should show the number of classes in Astah from the menu.

section divider

Debug the Plug-in

Now let’s debug and also check that it finds the nested class1 and class2 under package0 recursively. Run this command:

> astah-debug

This command launches Astah with port 44000 open for remote debugging, so you can connect to it from your IDE.

section divider

Example of remote debugging using Eclipse

If you are using Eclipse, please make the configuration as below.

Remote Debugging using Eclipse

Click [Debug] to start remote debugging. Set breakpoints in your code as needed.

section divider

Let’s add an extended view to Astah

Astah Plug-in can add an extra view in Astah. For example, you can make a view to show a list of class summaries or whatever you would like to show on Astah. So on this page, let’s create a Plug-in to add an extended view to Astah. And let’s make it show just a “hello world” text on there as an easy example.

Adding extended View
section divider

Creating an extended view

To add an extended view, use IPluginExtraTabView interface. Below is a sample HelloWorldView class that implements IPluginExtraTabView.

/*
 * Please change this class's package to your genearated Plug-in's package.
 * Plug-in's package namespace => com.example
 *   com.change_vision.astah.extension.plugin => X
 *   com.example                              => O
 *   com.example.internal                     => O
 *   learning                                 => X
 */
package com.example.internal;
 
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
 
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
 
import com.change_vision.jude.api.inf.AstahAPI;
import com.change_vision.jude.api.inf.project.ProjectAccessor;
import com.change_vision.jude.api.inf.project.ProjectEvent;
import com.change_vision.jude.api.inf.project.ProjectEventListener;
import com.change_vision.jude.api.inf.ui.IPluginExtraTabView;
import com.change_vision.jude.api.inf.ui.ISelectionListener;
 
public class HelloWorldView extends JPanel
      implements IPluginExtraTabView, ProjectEventListener {
  public HelloWorldView() {
    initComponents();
  }
 
  private void initComponents() {
    setLayout(new BorderLayout());
    add(createLabelPane(), BorderLayout.CENTER);
    addProjectEventListener();
  }
 
  private void addProjectEventListener() {
  try {
    AstahAPI api = AstahAPI.getAstahAPI();
    ProjectAccessor projectAccessor = api.getProjectAccessor();
    projectAccessor.addProjectEventListener(this);
  } catch (ClassNotFoundException e) {
    e.getMessage();
  }
  }
 
  private Container createLabelPane() {
    JLabel label = new JLabel("hello world");
    JScrollPane pane = new JScrollPane(label);
    return pane;
  }
 
  @Override
  public void projectChanged(ProjectEvent e) {
  }
 
  @Override
  public void projectClosed(ProjectEvent e) {
  }
 
   @Override
  public void projectOpened(ProjectEvent e) {
  }
 
  @Override
  public void addSelectionListener(ISelectionListener listener) {
  }
 
  @Override
  public Component getComponent() {
    return this;
  }
 
  @Override
  public String getDescription() {
    return "Show Hello World here";
  }
 
  @Override
  public String getTitle() {
    return "Hello World View";
  }
 
  public void activated() {
  }
 
  public void deactivated() {
  }
}

The getComponent() tells Astah what to show in the extended tab view , such as information in a table. In our sample, the instance of a JPanel with a JLabel is returned to Astah by the getComponent(). And the label on the extended tab should be defined in the getTitle().

A class implementing ProjectEventListener interface is an observer which keeps watching the models on current Astah. And the projectChanged() method will be called when there was a change in models such as adding/deleting of classes.

section divider

Adding an extended view to Astah

Next, let’s write the plugin.xml to add the extended view to Astah.

<?xml version="1.0" encoding="UTF-8"?>
<plugin>
   <extension point="com.change_vision.astah.ui.view">
        <view
            id="com.example.internal.HelloWorldView"
            type="extraTab"
            class="com.example.internal.HelloWorldView" />
   </extension>
</plugin>
Tag nameAttributeRequiredDescription
extensionRequiredSpecify extension point
pointRequiredSpecify com.change_vision.astah.ui.view
viewRequiredSpecify view configuration
idRequiredView’s ID
typeRequiredSpecify the location of the view
extraTab if you put the view on ExtraView
classRequiredSpecify implementation of the class

Now an extended view is added to Astah.