Dynamic Access Tutorial

This tutorial explains how dynamically implement the javax.swing.tree.MutableTreeNode interface for the leaf objects created by the Java source analyzer. The type of these objects is nice.LineInfo. This tutorial assumes that you have already followed the tutorial about Dynamic Implementations. The steps of this tutorial are :

  1. Get familiar with the LineInfo class.
  2. Get familiar with the MutableTreeNode interface.
  3. Create the DA_LineInfo class.
  4. Create the DI_LineInfo__MutableTreeNode class.
  5. Run the application.

 

Get familiar with the LineInfo class

LineInfo is a subclass of the StatementInfo class and it does not define any new method. It implements a trivial code for the methods handling children. For example the numberOfChildren() method always returns zero.

The leaves of the tree returned by the Java source analyzer are instances of the LineInfo class. The default label for these instances is the Java statement itself. For example: "int i=14" or "import java.io.InputStream". The objective of this tutorial is to dynamically implement the MutableTreeNode interface to allow the tree viewer to interactively modify the default labels.

You can find the source code of this class in StatementInfo.java.

 

Get familiar with the MutableTreeNode interface

This is the standard javax.swing.tree.MutableTreeNode interface used by the tree facilities of the swing library.

You can find the documentation for this interface in http://java.sun.com/products/jdk/1.2/docs/api/javax/swing/tree/MutableTreeNode.html.

There two facts about this interface particularly important for this tutorial :

  1. This interface derives from TreeNode interface.
  2. It adds some methods to insert and remove children, but the method you are going to really implement is setUserObject() because tree viewer uses this method to modify node labels.

 

Create the DA_LineInfo class

The only available way to modify the label of a LineInfo instance is to invoke the changeLabel method. The problem is that this method inherited from StatementInfo is protected. This means that the DI_LineInfo__MutableTreeNode class used to dynamically implement the MutableTreeNode interface needs to access a protected method of the LineInfo class.

DJBinder solution for this problem is to define a Dynamic Authorization class named DA_LineInfo (you can get the source file in DA_LineInfo.java).

package nice ;

abstract class DA_LineInfo
{
public abstract void changeLabel (String newLabel);
}

All the dynamic authorization classes must be abstract and the name must start by DA_ followed by the base name of the main class. In our case it means "DA_"+"LineInfo".

This class contains all the protected and private members of the main class needed by the dynamic interface implementations.

In this case the only needed member is the changeLabel method. The signature must be exactly the same one as in the main class, the only difference is the visibility modifier which must be public.

DJBinder uses this definition as a marker indicating that this member can be accessed from a dynamic interface implementation although it is a protected member. You can get more information in Accessing members of the main class.

 

Create the DI_LineInfo__MutableTreeNode class

You have already defined a dynamic interface implementation in Create the DI_StatementInfo__TreeNode class. This is going to be very similar but nevertheless there are some differences. After creating this class the LineInfo objects will behave as if they implement the MutableTreeNode interface.

The first step is to specify the same package of the LineInfo class :

package nice ;

Then you add all the imports needed. It is not a must, but very likely you may want to import the MutableTreeNode interface.

import javax.swing.tree.MutableTreeNode ;

Now you code the header of the class :

public abstract class DI_LineInfo__MutableTreeNode
extends DI_StatementInfo__TreeNode implements MutableTreeNode

All the dynamic implementation classes must be public and abstract. The name must start by DI_ followed by the base name of the main class, two underscores and finally the base name of the interface. In our case it means "DI_"+"LineInfo"+"__"+"MutableTreeNode".

And of course this class must implement the MutableTreeNode interface.

An important detail is that this class extends DI_StatementInfo__TreeNode class. This is not indispensable, but it saves you the work of redefining the TreeNode methods. Recall that MutableTreeNode interface extends TreeNode and LineInfo class extends StatementInfo. This is the most typical case when a dynamic implementation extends another one: if DI_A__B extends DI_X__Y then there are two conditions not required but strongly recommended :

This class does not have any member field, but it inherits the si_ field from the DI_StatementInfo__TreeNode class.

The si_ field refers to the LineInfo object associated to this instance. In other words the creation of this instance was triggered by the casting of that object into MutableTreeNode. This field is initialized in the StatementInfo.init() method invoked from the LineInfo.init() method :

public void init (Object params)
{
super.init (params) ;
}

Now you can implement the methods of the MutableTreeNode interface. The most important method is :

public void setUserObject(Object object)
{
((DA_LineInfo)(Object)si_).changeLabel (object.toString()) ;
}

The expression ((DA_LineInfo)(Object)si_) casts the main object referenced by si_ into DA_LineInfo. The expression ((DA_LineInfo)(Object)this) would be equivalent. It is a question of personal taste to use one or the other.

Notice that the invoked changeLabel method is the one of the DA_LineInfo class and no the one of the LineInfo class. Otherwise the program would not compile because this class does not have the right to access a protected member of LineInfo. DJBinder redirects the invocation and the actually executed method is the one of LineInfo.

All the other methods are implemented by a simple "do nothing" :

public void insert(MutableTreeNode child, int index)
{
// No supported ==> do nothing
}

public void remove(int index)
{
// No supported ==> do nothing
}

public void remove(MutableTreeNode node)
{
// No supported ==> do nothing
}

public void removeFromParent()
{
// No supported ==> do nothing
}

public void setParent(MutableTreeNode newParent)
{
// No supported ==> do nothing
}

You can find the source code in DI_LineInfo__MutableTreeNode.java.

 

Run the application

This chapter assumes that you use a standard JDK 1.2 of java.sun.com installed in the c:\jdk1.2 directory under Windows. The equivalent commands for other configurations (Unix or another Java virtual machine) are normally straight forward.

Before running this application you have to make sure that the djbinder.jar file is accessible in the runtime environment and it has all the security authorizations granted. The easiest way of doing this is to install the djbinder.jar file as an extension of the Java virtual machine. You can install the djbinder.jar file as an extension by copying it in the c:\jdk1.2\jre\lib\ext directory. You can find more information in Running applications.

You have to download the tutorialFiles.jar file and unzip it. You can use any zip tool like for example the jar tool.

C:\jdk1.2\bin\jar xvf tutorialFiles.jar

The files used by this tutorial are :

TreeAppli.java
cannes\ TreeViewer.java
nice\StatementInfo.java
nice\DI_StatementInfo__TreeNode.java
nice\DA_LineInfo.java
nice\DI_LineInfo__MutableTreeNode.java
Test.java (a sample of source file to analyze and visualize)

Compile the Java files in the same directory where you have unziped the tutorial files (no need to compile Test.java nor any other source file that you have already compiled in a previous tutorial):

C:\jdk1.2\bin\javac TreeAppli.java cannes\TreeViewer.java nice\StatementInfo.java nice\DI_StatementInfo__TreeNode.java nice\DA_LineInfo.java nice\DI_LineInfo__MutableTreeNode.java

Run the application using the following command line :

C:\jdk1.2\bin\java amslib.djbinder.Start TreeAppli Test.java

If you have followed these steps you should see a tree with the statements of the Test.java source file. You can expand and collapse the nodes by clicking on them. If you press the SHIFT key at the same time that you click on a node then a Popup-window is displayed and you can type the new text for that node.

On the contrary if you use the command line :

C:\jdk1.2\bin\java TreeAppli Test.java

You would get a ClassCastException because the root object is casted into the TreeNode interface and DJBinder is not activated.

top of this page


DJBinder downloads tutorials consulting contact us links Amslib