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

Let’s make another plug-in. This time make one to count Classes in Astah.
This is a sample for Astah Professional and Astah UML editions. But you could refer to this sample and apply for counting Blocks for SysML.

In this sample model as the figure below, there are three classes in this model.

Count UML Classes in a project

Now let’s make a Plug-in to count the classes and let it print the number as below.:

"There are 3 classes"
section divider

Get model information

In order to get model information, you need to use Astah API. Astah API is a group of Java interfaces for reading/writing Astah which can be used to count the number of classes in this case.
Please refer to the Astah API User Guide for detailed information.

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 Class in the menu instead.

First, create CountClassAction class.

/*
 * 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.actions;

import java.util.ArrayList;
import java.util.List;
import javax.swing.JOptionPane;
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.project.ProjectAccessorFactory;
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 {
            ProjectAccessor projectAccessor = ProjectAccessorFactory.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 see if it can get a nested class1 and class2 under a pacage0 recursively by running the command below.:

> astah-debug

This command launches Astah with the 44000 port open for remote debugging which you can connect from IDE.

section divider

Example of remote debugging using Eclipse

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

Remote Debugging using Eclipse

Clicking [Debug] button executes the remote debugging. Please set a breakpoint in the line of codes if you like. This is all we provide regarding the remote debugging on this tutorial.

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 of the HelloWoroldView which implements the 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.project.ProjectAccessor;
import com.change_vision.jude.api.inf.project.ProjectAccessorFactory;
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 {
      ProjectAccessor projectAccessor = ProjectAccessorFactory.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 like information in table format…etc. 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
extensionRequired
Specify extension point
pointRequired
Specify com.change_vision.astah.ui.view
viewRequired
Specify view configuration
idRequired
View’s ID
typeRequired
Specify the location of the view
extraTab if you put the view on ExtraView
classRequired
Specify implementation of the class

Now an extended view is added to Astah.