Dynamic Implementation Tutorial
This tutorial explains how dynamically implement the javax.swing.tree.TreeNode interface for the objects created by the Java source analyzer. The super type of these objects is nice.StatementInfo. The steps of the tutorial are :
Get familiar with the StatementInfo class
This is the main class of the Java source analyzer, it has a static analyze()
method which receives the name of a Java source file and returns the root object of a tree. The tree represents the structure of the program contained in the source file.
For example the following source file :
public class Y
{
{
{
else
{
int i_ ;
Generates the following tree :
The objects contained in the tree are all subclasses of StatementInfo. The StatementInfo class has methods to :
You can find the source code in StatementInfo.java and its documentation generated by javadoc in StatementInfo.html.
Get familiar with the TreeNode interface
This is the standard javax.swing.tree.TreeNode 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/TreeNode.html.
Create the DI_StatementInfo__TreeNode class
This is the main step of the tutorial. It is actually the only step required by DJBinder to dynamically implement an interface. After creating this class the StatementInfo objects will behave as if they implement the TreeNode interface.
The first step is to specify the same package of the StatementInfo class :
Then you add all the imports needed. It is not a must, but very likely you may want to import the TreeNode interface.
import java.util.Enumeration ;
import java.util.NoSuchElementException ;
Now you code the header of the class :
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_"+"StatementInfo"+"__"+"TreeNode".
And of course this class must implement the TreeNode interface.
This class has one member field :
The si_ field refers to the StatementInfo object associated to this instance. In other words the creation of this instance was triggered by the casting of that object into TreeNode. This field is initialized in the init
method. This method has to be public
and have exactly the following signature :
{
The expression (StatementInfo)(Object)this;
is the standard way used within dynamic implementations to access the associated main object. In other words the this
reference is casted into the type of the main object. Java forbids the direct cast from DI_StatementInfo__TreeNode into StatementInfo, that is why a middle cast into Object is used.
In the other methods of this class the si_ field is used as a shortcut for the expression (StatementInfo)(Object)this
.
Now you can implement the methods of the TreeNode interface :
{
public TreeNode getChildAt(int childIndex)
{
public int getChildCount()
{
public int getIndex(TreeNode node)
{
public TreeNode getParent()
{
public boolean isLeaf()
{
public Enumeration children()
{
The last method returns an object that must implement the java.util.Enumeration interface, this is done using an internal class :
{
Enumerator ()
{
public boolean hasMoreElements()
{
public Object nextElement()
{
{
catch (ArrayIndexOutOfBoundsException e)
{
The toString()
method is not directly a method of the TreeNode interface, but it is used by the tree viewer component to obtain the text of each node :
{
The String returned is the label of the associated StatementInfo object.
You can find the source code in DI_StatementInfo__TreeNode.java.
Create the application that integrates the tree viewer and the Java source analyzer
Now that the objects generated by the Java source analyzer behave as if they implement the TreeNode interface, you can send them to the tree viewer. Here is the code which integrates both components.
import javax.swing.tree.TreeNode;
import nice.StatementInfo ;
import cannes.TreeViewer ;
public class TreeAppli
{
{
TreeNode root = (TreeNode) StatementInfo.analyze (fileName) ;
if (root != null)
{
frame.setVisible(true);
This application assumes that the first argument is the name of a Java source file, this argument is sent to the Statement.analyze
method which reads the file, analyze the Java program and returns the root object of a tree containing the structure of the program.
If the root is not null then it is visualized using the tree viewer.
The type of the root object returned by the analyze()
method is StatementInfo which must be casted into TreeNode. Normally this cast should throw an exception, but this is not the case when DJBinder is activated, instead a valid TreeNode reference is returned.
You can find the source code in TreeAppli.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.
The files used by this tutorial are : You must ignore all the other files. Compile the Java files in the same directory where you have unziped the tutorial files (no need to compile Test.java):
Run the application using the following command line :
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. On the contrary if you use the command line :
You would get a ClassCastException because the root object is casted into the TreeNode interface and DJBinder is not activated.
cannes\ TreeViewer.java
nice\StatementInfo.java
nice\DI_StatementInfo__TreeNode.java
Test.java (a sample of source file to analyze and visualize)