JTF > Rationale > The acm.util Package

Chapter 8
The acm.util Package


The acm.util package includes a set of utilities that are either simple standalone tools or that are shared resources for the other packages. The package consists of the following classes, presented here in an order that roughly reflects the likelihood that someone adopting the ACM packages would use them:

The sections that follow provide a brief overview of each mechanism without describing the class in detail. For more details, please see the javadoc documentation on the web site.

8.1 The ErrorException class

The ErrorException class is an extremely simple class whose only purpose is to provide the ACM packages with a consistent way to report errors. When errors are detected in the package, or in any other code that adopts the same convention, those errors are indicated by throwing an exception like this:

 

throw new ErrorException(message);
Any caller in the dynamic execution chain can catch this error if they want to handle it; if it is uncaught, the program will terminate with an unhandled exception error. The key advantage is that ErrorException is a subclass of RuntimeException and therefore need not be declared in throws clauses.

8.2 The CancelledException class

The CancelledException class is used to represent an exception that signals cancellation of an operation. Although the only class that throws this exception is the IODialog class in acm.io, we decided to put it in acm.util to make it more generally available. In particular, it is possible that future extensions to the Animator class might need to signal cancellation.

8.3 The RandomGenerator class

In response to our call for community input last spring, Alyce Brady of Kalamazoo College offered a pair of simple proposals that resonated with many of the Task Force members. After noting that random numbers play an important role in many introductory courses, Alyce made the following observation:

The java.util.Random class, with its nextInt, nextDouble, and nextBoolean methods is a good choice to use, but students often fall into the trap of constructing multiple Random instances in order to generate multiple random numbers. This can lead to behavior that appears far from random if the different Random objects generate equivalent or similar sequences of random numbers. Another problem with the Random class, which is not as insignificant as it sounds, is that the name is misleading. A Random instance is actually a random number generator, not a random object. [Brady04a]

For precisely the reasons that Alyce describes here, we have included a RandomGenerator class in the acm.util package. RandomGenerator is a subclass of java.util.Random and therefore provides all the methods that are available in that class. In addition, however, the RandomGenerator class offers the additional methods shown in Figure 8-1.

Figure 8-1. Additional methods in the RandomGenerator class
 Factory method
 
static RandomGenerator getInstance()
  Returns a standard random generator.

 New methods defined by RandomGenerator
 
int nextInt(int low, int high)
  Returns a random integer in the specified range (inclusive).
double nextDouble(double low, double high)
  Returns a random double in the specified range.
boolean nextBoolean(double p)
  Returns a random boolean that is true with probability p (0 = never, 1 = always).
Color nextColor()
  Returns a random opaque color.
   

8.4 The SwingTimer class

Just as the RandomGenerator class described in the preceding section provides a version of the Random class with a new name more suggestive of its function, the SwingTimer class is a simple subclass of javax.Swing.Timer. In this case, however, there is no new functionality. The only reason for the existence of this class is to avoid the ambiguity between the two versions of a Timer class in Java’s standard libraries. Since it is common to import both java.util and javax.Swing in the same source file, programmers writing such code must import the appropriate Timer version explicitly and cannot simply rely on the generic imports. While this may not be a significant problem in itself, it has the unfortunate effect in the JTF packages of defeating the strategy used to maintain compatibility with older browsers, which depend on Java’s name resolution rules to substitute new class definitions for classes that do not exist in JDK 1.1.

8.5 The Animator class

The Animator class is a simple subclass of Thread designed to support simpler animation. It is derived from the ActiveObject class included in the objectdraw package [Bruce04b]. One of the most useful aspects of Animator is that it includes a pause(time) method that suspends for the specified number of milliseconds. This method is therefore similar to Thread.sleep but is easier for novices to use because it never throws an exception. Thus, an animator can delay its own operation by writing

 

pause(time);

rather than the ungainly

 

try {
   Thread.sleep(time);
} catch (InterruptedException ex) {
   /* Empty */
}

Since the beta release, the Animator class has been upgraded to provide several additional features for animation control. The methods in the Animator class are listed in Figure 8-2. The purpose of these extensions is to support interactor control using Start, Stop, and Step buttons and variable speed execution. An example using this facility appears in Chapter 4 of the JTF Tutorial, which includes an implementation of the Marine Biology Simulation used as a case study for the Computer Science Advanced Placement course [CollegeBoard00].

Figure 8-2. Methods defined in the Animator class
Constructor
 
Animator()
  Creates a new Animator object.
 
Method to specify the code for the animation thread
 
void run()
  The code to animate the object goes in a run method specific to each subclass.
 
Methods to control the speed and flow of the animation
 
void pause(double milliseconds)
  Pauses the animation thread for the specified number of milliseconds.
void setSpeed(double speed)
  Sets the speed of the animator to speed, which must be between 0.0 (slow) and 1.1 (fast).
double getSpeed()
  Returns the speed of the animator set by the last call to setSpeed.
void delay()
  Delays the animation by a time interval determined by the current speed setting.
void trace()
  Checks for tracing operations from buttons such as Start, Stop, and Step.
 
Methods to support GUI controls
 
void buttonAction(String actionCommand)
  Invokes the action associated with the action command (Start, Stop, or Step)
void registerSpeedBar(JSlider slider)
  Registers the specified slider as the speed bar for this animator.

8.6 The Platform class

The Platform class implements a variety of convenience methods for the ACM packages that allow the implementations to determine properties about the environment. The intent of these facilities is not to produce programs that behave differently on different platforms, but instead to overcome any known platform incompatibilities to ensure that code works in as portable a way as possible. The package also includes several methods that look at the runtime environment to determine what capabilities are supported by the virtual machine. These facilities are used to take advantage of modern Java facilities while remaining compatible with earlier versions of the JDK.

8.7 The MediaTools class

The MediaTools class provides several static methods that support the creation and loading of images and audio clips in a convenient and portable way. Please see the package documentation for details.

8.8 The JTFTools class

The JTFTools class implements a collection of static methods that are used throughout the ACM packages. Several of these methods are potentially useful to clients outside of those packages, but the motivation behind the package is simply to centralize common methods used in the packages to avoid duplication of code.

8.9 The OptionTable class

The OptionTable class was added to the acm.util package as part of the implementation of the TableLayout class introduced in section 7.3. It has the responsibility of parsing the string version of the constraint specification, which consists of a set of key/value pairs. The OptionTable package checks to make sure that a key is valid and makes it easy to specify default options. Although TableLayout is currently the only client, other developers may want to use the same mechanism.

8.10 Oh Scanner, where art thou?

The February 2005 release of the acm.util package included a Scanner class that provided most of the features of the Java 2 Standard Edition 5.0 class while remaining compatible with JDK 1.1. Putting that class in the acm.util package, however, did not turn out to be a workable strategybecause of name conflicts caused when users upgraded their systems to J2SE 5.0. Given the common practice of importing everything in a package using the import * feature, having two classes named Scanner made it impossible to import both the java.util and the acm.util packages without creating an ambiguity. At the same time, calling our simulated Scanner class something else would eliminate much of the reason for its inclusion.

Fortunately, the simulated Scanner class has not entirely disappeared. Although it no longer exists in the acm.util package, the same functionality is now available in the supplemental package that allows the ACM libraries to run even in JDK 1.1 environments. The strategy that makes this level of compatibility possible is described in section 9.3.



Final Report—July 31, 2006