A method lookup tool

Bruce Eckel’s Thinking in Java Contents | Prev | Next

However,
by Chapter 11 you hadn’t seen the AWT, so that tool was developed as a
command-line application. Here is the more useful GUI version, which
dynamically updates the output as you type and also allows you to cut and paste
from the output:

//: DisplayMethods.java
// Display the methods of any class inside
// a window. Dynamically narrows your search.
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.lang.reflect.*;
import java.io.*;
 
public class DisplayMethods extends Applet {
  Class cl;
  Method[] m;
  Constructor[] ctor;
  String[] n = new String[0];
  TextField
    name = new TextField(40),
    searchFor = new TextField(30);
  Checkbox strip =
    new Checkbox("Strip Qualifiers");
  TextArea results = new TextArea(40, 65);
  public void init() {
    strip.setState(true);
    name.addTextListener(new NameL());
    searchFor.addTextListener(new SearchForL());
    strip.addItemListener(new StripL());
    Panel
      top = new Panel(),
      lower = new Panel(),
      p = new Panel();
    top.add(new Label("Qualified class name:"));
    top.add(name);
    lower.add(
      new Label("String to search for:"));
    lower.add(searchFor);
    lower.add(strip);
    p.setLayout(new BorderLayout());
    p.add(top, BorderLayout.NORTH);
    p.add(lower, BorderLayout.SOUTH);
    setLayout(new BorderLayout());
    add(p, BorderLayout.NORTH);
    add(results, BorderLayout.CENTER);
  }
  class NameL implements TextListener {
    public void textValueChanged(TextEvent e) {
      String nm = name.getText().trim();
      if(nm.length() == 0) {
        results.setText("No match");
        n = new String[0];
        return;
      }
      try {
        cl = Class.forName(nm);
      } catch (ClassNotFoundException ex) {
        results.setText("No match");
        return;
      }
      m = cl.getMethods();
      ctor = cl.getConstructors();
      // Convert to an array of Strings:
      n = new String[m.length + ctor.length];
      for(int i = 0; i < m.length; i++)
        n[i] = m[i].toString();
      for(int i = 0; i < ctor.length; i++)
        n[i + m.length] = ctor[i].toString();
      reDisplay();
    }
  }
  void reDisplay() {
    // Create the result set:
    String[] rs = new String[n.length];
    String find = searchFor.getText();
    int j = 0;
    // Select from the list if find exists:
    for (int i = 0; i < n.length; i++) {
      if(find == null)
        rs[j++] = n[i];
      else if(n[i].indexOf(find) != -1)
          rs[j++] = n[i];
    }
    results.setText("");
    if(strip.getState() == true)
      for (int i = 0; i < j; i++)
        results.append(
          StripQualifiers.strip(rs[i]) + "n");
    else // Leave qualifiers on
      for (int i = 0; i < j; i++)
        results.append(rs[i] + "n");
  }
  class StripL implements ItemListener {
    public void itemStateChanged(ItemEvent e) {
      reDisplay();
    }
  }
  class SearchForL implements TextListener {
    public void textValueChanged(TextEvent e) {
      reDisplay();
    }
  }
  public static void main(String[] args) {
    DisplayMethods applet = new DisplayMethods();
    Frame aFrame = new Frame("Display Methods");
    aFrame.addWindowListener(
      new WindowAdapter() {
        public void windowClosing(WindowEvent e) {
          System.exit(0);
        }
      });
    aFrame.add(applet, BorderLayout.CENTER);
    aFrame.setSize(500,750);
    applet.init();
    applet.start();
    aFrame.setVisible(true);
  }
}
 
class StripQualifiers {
  private StreamTokenizer st;
  public StripQualifiers(String qualified) {
      st = new StreamTokenizer(
        new StringReader(qualified));
      st.ordinaryChar(' ');
  }
  public String getNext() {
    String s = null;
    try {
      if(st.nextToken() !=
            StreamTokenizer.TT_EOF) {
        switch(st.ttype) {
          case StreamTokenizer.TT_EOL:
            s = null;
            break;
          case StreamTokenizer.TT_NUMBER:
            s = Double.toString(st.nval);
            break;
          case StreamTokenizer.TT_WORD:
            s = new String(st.sval);
            break;
          default: // single character in ttype
            s = String.valueOf((char)st.ttype);
        }
      }
    } catch(IOException e) {
      System.out.println(e);
    }
    return s;
  }
  public static String strip(String qualified) {
    StripQualifiers sq =
      new StripQualifiers(qualified);
    String s = "", si;
    while((si = sq.getNext()) != null) {
      int lastDot = si.lastIndexOf('.');
      if(lastDot != -1)
        si = si.substring(lastDot + 1);
      s += si;
    }
    return s;
  }
} ///:~ 

Some
things you’ve seen before. As with many of the GUI programs in this book,
this is created to perform both as an application and as an applet. Also, the
StripQualifiers
class is exactly the same as it was in Chapter 11.

The
GUI contains a
TextField
name
in
which you can enter the fully-qualified class name you want to look up, and
another one,
searchFor,
in which you can enter the optional text to search for within the list of
methods. The
Checkbox
allows you to say whether you want to use the fully-qualified names in the
output or if you want the qualification stripped off. Finally, the results are
displayed in a
TextArea.

You’ll
notice that there are no buttons or other components by which to indicate that
you want the search to start. That’s because both of the
TextFields
and the
Checkbox
are monitored by their listener objects. Whenever you make a change, the list
is immediately updated. If you change the text within the
name
field,
the new text is captured in
class
NameL
.
If the text isn’t empty, it is used inside Class.forName( )
to try to look up the class. As you’re typing, of course, the name will
be incomplete and
Class.forName( )
will fail, which means that it throws an exception. This is trapped and the
TextArea
is set to “No match”. But as soon as you type in a correct name
(capitalization counts),
Class.forName( )
is successful and
getMethods( )
and
getConstructors( )
will return arrays of
Method
and
Constructor
objects, respectively. Each of the objects in these arrays is turned into a
String
via
toString( )
(this produces the complete method or constructor signature) and both lists are
combined into
n,
a single
String
array. The array
n
is a member of
class
DisplayMethods

and is used in updating the display whenever
reDisplay( )
is called.

If
you change the
Checkbox
or
searchFor
components, their listeners simply call
reDisplay( ).
reDisplay( )
creates a temporary array of
String
called
rs
(for “result set”). The result set is either copied directly from
n
if there is no
find
word, or conditionally copied from the
Strings
in
n
that contain the
find
word. Finally, the
strip
Checkbox
is interrogated to see if the user wants the names to be stripped (the default
is “yes”). If so,
StripQualifiers.strip( )
does the job; if not, the list is simply displayed.

In
init( ),
you might think that there’s a lot of busy work involved in setting up
the layout. In fact, it is possible to lay out the components with less work,
but the advantage of using
BorderLayouts
this way is that it allows the user to resize the window and make – in
particular – the
TextArea
larger, which means you can resize to allow you to see longer names without
scrolling.

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read