|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: INNER | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object | +--org.jutil.java.collections.RobustVisitor
A robust visitor of collections. The code in visit is performed for each element in the visited collection.
Of course, sometimes exceptions can be thrown during a visit. The default behaviour when an exception occurs, is to undo all changes that were made and throw an exception to the caller of the method. This means that the actions that were performed on elements visited before the element that caused the exception, have to be undone. The RobustVisitor class adds support for handling exceptions to the Visitor class.
If an exception occurs while visiting the collection, the changes made to
the elements visited before the element that caused the exception, are
undone. To accomplish this, a method void
unvisit(Object element, Object undoData)
is introduced, which
takes a visited element and data to undo the changes as arguments. The method
must undo the changes made to the given element. The undoData object is the
object that is returned by the void visit(Object element)
throws Exception
method. If no undo data is necessary to undo the
changes, null
can be returned. The changes are undone in the
opposite order as the changes were done. The changes of the visit that caused
the exception should be undone by the visit method itself, the other visits
are undone using the unvisit method. After all changes are undone, the
exception is propagated to the caller of the applyTo
method.
The visit
and
applyTo
methods throw Exceptions
to keep the class as general as
possible. The Exception
of the visit
method can
be strengthened to one specific exception when overwriting the method, but
the Exception
of the applyTo method can't because that method is
made final. That means that in the code you have to catch
Exception
, which is a disadvantage of using a
RobustVisitor
. Most methods we didn't think could be overwritten
in a useful way are made final. Even if we would allow to overwrite the
applyTo
method, the only way to strengthen the exception there is to insert a
try-catch block and call the super method, or copy the code from the
RobustVisitor
doesn't inherit from Visitor
because adding an exception to the throws clausule of the visit method would
violate LSP (Liskov Substitution Principle) and because the visit methods of
both classes have different return types. The last reason also prevents us
from doing the opposite, making Visitor
inherit from
RobustVistor
(which would also introduce a useless unvisit
method in Visitor
).
Iterator iter = collection.iterator();
Vector changed = new Vector();
Vector undo = new Vector();
try{
while(iter.hasNext()) {
MyClass object = (MyClass) iter.next();
// action code
changed.add(object);
undo.add(undoData);
}
}
catch(MyException exc) {
for(int i=changed.size(); i>= 0; i--) {
// undo action code;
}
throw exc;
}
new RobustVisitor() {
public Object visit(Object element) throws MyException {
MyClass object = (MyClass) element;
// action code;
return undoData;
}
public void unvisit(Object element, Object undoData) {
// undo action code;
}
}.applyTo(collection);
Field Summary | |
static java.lang.String |
CVS_REVISION
|
Constructor Summary | |
RobustVisitor()
|
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 of post (* for all e in collection: visit(e) *); signals (ConcurrentModificationException) (* The collection was modified while visiting. |
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 array, // which is returned afterwards post \result == array; // public void visit(Object) is called for all // elements of post (* for all e in collection: visit(e) *); signals (Exception) (* Something has gone wrong during the visit *); |
abstract void |
unvisit(java.lang.Object element,
java.lang.Object unvisitData)
public behavior pre isValidElement(element); // unvisitData is the data returned by the visit method. pre unvisitData == visit(element); post (* the changes on This method will be called when the visit method has raised an exception for some element which was visited after |
abstract java.lang.Object |
visit(java.lang.Object element)
public behavior pre isValidElement(element); post (* Data which enables to undo what visit has done in unvisit is returned. |
Methods inherited from class java.lang.Object |
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Field Detail |
public static final java.lang.String CVS_REVISION
Constructor Detail |
public RobustVisitor()
Method Detail |
public abstract java.lang.Object visit(java.lang.Object element) throws java.lang.Exception
element
- The object the code should be applied to.public abstract void unvisit(java.lang.Object element, java.lang.Object unvisitData)
public final java.util.Collection applyTo(java.util.Collection collection) throws java.lang.Exception, java.util.ConcurrentModificationException
public void visit(Object)
is called for allPerform the visitation defined in public void visit(Object)
on
The collection is returned, so that further operations can be applied to it inline.
collection
- The collection to perform this visitation on. This can be null.public final java.lang.Object[] applyTo(java.lang.Object[] array) throws java.lang.Exception
Perform the visitation defined in public void visit(Object)
on
The array is returned, so that further operations can be applied to it inline.
array
- The array to perform this visitation on.
This can be null.public final void applyTo(java.util.Iterator iterator) throws java.lang.Exception, java.util.ConcurrentModificationException
Perform the visitation defined in public void visit(Object)
on all elements reachable from
iterator
- The iterator to perform this visitation on. This can be null.public final void applyTo(java.util.Enumeration enumeration) throws java.lang.Exception, java.util.ConcurrentModificationException
Perform the visitation defined in public void visit(Object)
on all elements reachable from
enumeration
- The enumeration to perform this visitation on. This can be null.
|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: INNER | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |