org.jutil.java.collections
Class Visitor

java.lang.Object
  |
  +--org.jutil.java.collections.Visitor
All Implemented Interfaces:
CollectionOperator

public abstract class Visitor
extends java.lang.Object
implements CollectionOperator

A class of collection operators that can perform a certain action on all element of a collection.

Visitor

The Visitor class is a replacement for the java.util.Iterator class that allows a programmer to perform a certain action on all elements of a collection. An iterator already provides a convenient way to iterate over all elements of a collection without having to know anything about its inner structure, but the programmer still needs to write the control statements for the iteration.

Traditional use of an iterator.


 Iterator iter = collection.iterator();
 while(iter.hasNext()) {
   MyClass element = (MyClass) iter.next();
   // action code
 }
 

The Visitor class provides a more declarative way of performing an action on all elements of a collection. Instead of writing an iteration loop, a class is created, most often as an anonymous inner class, which overwrites the visit method of the Visitor class. The visit method will perform the action on the given element of the collection. To perform the visit, the applyTo method is invoked with the collection which has to be visited as an argument. The typical use of such an inner class is shown below.

Typical use of a Visitor.


 new Visitor() {
   public void visit(Object element) {
     MyClass object = (MyClass) element;
     // action code
   }
 }.applyTo(collection);
 

Notice that all control statements have disappeared. Only the code that actually performs the action is present, along with the invokation of the applyTo method. The code in Visitor takes care of the iteration. Using a visitor does not make the code shorter, but it is easier to read and write than the code with the iterator.

When the action to be performed needs information from elements that were visited before, that information can be stored in instance variables of the inner class instead of a local variable of the current method.

In addition to collections, a Visitor class can also visit iterators, enumerations and multi-dimensional arrays of objects. Being able to visit iterators and enumerations is usefull in case you can't get a reference to a collection but only a reference to an Iterator or an Enumeration for that collection. The applyTo method has been overloaded in order to provide a single notation for all visits.

When you need to save information between the visit of two elements, you can create instance variables for the inner class instead of using local variables.

Version:
$Revision: 1.16 $
Author:
Jan Dockx, Marko van Dooren

Field Summary
static java.lang.String CVS_REVISION
           
 
Constructor Summary
Visitor()
           
 
Method Summary
 java.util.Collection applyTo(java.util.Collection collection)
          public behavior

pre (\forall Object o, collection.contains(o); isValidElement(o));

// The changes are applied to the given collection,
// which is returned afterwards
post \result == collection;

// public void visit(Object) is called for all elements.
post (* for all e in collection: visit(e) *);

signals (ConcurrentModificationException)
(* The collection was modified while calculating the tranitive closure.
 void applyTo(java.util.Enumeration enumeration)
          pre (* The enumeration must be at the beginning of its enumeration.
 void applyTo(java.util.Iterator iterator)
          pre (* The iterator must be at the beginning of its iteration.
 java.lang.Object[] applyTo(java.lang.Object[] array)
          // The changes are applied to the given object array,
// which is returned afterwards
post \result == array;
abstract  void visit(java.lang.Object element)
          public behavior

pre isValidElement(element);
The code to be applied to all elements of a collection.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

CVS_REVISION

public static final java.lang.String CVS_REVISION
Constructor Detail

Visitor

public Visitor()
Method Detail

visit

public abstract void visit(java.lang.Object element)
public behavior

pre isValidElement(element);
The code to be applied to all elements of a collection.
Parameters:
element - The object the code should be applied to.

applyTo

public final java.util.Collection applyTo(java.util.Collection collection)
                                   throws java.util.ConcurrentModificationException
public behavior

pre (\forall Object o, collection.contains(o); isValidElement(o));

// The changes are applied to the given collection,
// which is returned afterwards
post \result == collection;

// public void visit(Object) is called for all elements.
post (* for all e in collection: visit(e) *);

signals (ConcurrentModificationException)
(* The collection was modified while calculating the tranitive closure. *);

Perform the visit defined in public void visit(Object) on . The contents of is not changed.

The collection is returned, so that further operations can be applied to it inline.

Parameters:
collection - The collection to perform this visit on. This can be null.

applyTo

public final java.lang.Object[] applyTo(java.lang.Object[] array)
// The changes are applied to the given object array,
// which is returned afterwards
post \result == array;

Perform the visit defined in public void visit(Object) on the multi-dimensional object array . The contents of is not changed.

The array is returned, so that further operations can be applied to it inline.

The elements are visited in depth-first order.

NOTE: For now it doesn't work when subarrays at the same level have different sizes. for example:


 [
  [o1, o2],
  [o3, o4, o5]
 ]
 
Parameters:
array - The array to perform this visit on. This can be null.

applyTo

public final void applyTo(java.util.Iterator iterator)
                   throws java.util.ConcurrentModificationException
pre (* The iterator must be at the beginning of its iteration. *);

// The iterator will be at the end
post ! iterator.hasNext();

signals (ConcurrentModificationException)
(* The collection was modified while calculating the tranitive closure. *);

Perform the visit defined in public void visit(Object) on . The contents of collection of the iterator is not changed.

Parameters:
iterator - The iterator used to perform this visit. This can be null.

applyTo

public final void applyTo(java.util.Enumeration enumeration)
                   throws java.util.ConcurrentModificationException
pre (* The enumeration must be at the beginning of its enumeration. *);

// The enumeration will be at the end
post ! enumeration.hasMoreElements();

signals (ConcurrentModificationException)
(* The collection was modified while calculating the tranitive closure. *);

Perform the visit defined in public void visit(Object) on . The contents of collection of the enumeration is not changed.

Parameters:
enumeration - The enumeration used to perform this visit. This can be null.