You are here

List Visitor Examples

6 June, 2016 - 15:14
Available under Creative Commons-ShareAlike 4.0 International License. Download for free at http://cnx.org/contents/402b20ad-c01f-45f1-9743-05eadb1f710e@37.6
/**  * Computes the length of the IList host. */ public class GetLength implements IListAlgo { /** * Singleton Pattern.     */ public static final GetLength Singleton = new GetLength(); private GetLength() {  }
/**
 * Returns Integer(0).
 * @param nu not used
 * @return Integer(0)
 */
public Object emptyCase(MTList host, Object... nu) {
    return 0;
}
 
/**
 * Return the length of the host's rest plus 1.
 * @param nu not used.
 * @return Integer > 0.
 */
public Object nonEmptyCase(NEList host, Object... nu) {
    Object restLen = host.getRest().execute(this);
     return 1 + (Integer)restLen);
}
 
 
package listFW; /** * Computes a String reprsentation of IList showing a left parenthesis followed * by elements of the IList separated by commas, ending with with a right parenthesis. * @stereotype visitor */ public class ToStringAlgo implements IListAlgo { public static final ToStringAlgo Singleton = new ToStringAlgo(); private ToStringAlgo() { }
/**
 * Returns "()".
 */
public Object emptyCase(MTList host, Object... inp) {
return "()";
}
 
/**
* Passes "(" + first to the rest of IList and asks for help to complete the computation.
*/
public Object nonEmptyCase(NEList host, Object...  inp) {
return host.getRest().execute(ToStringHelper.Singleton, "(" + host.getFirst());
}
}
 
 
/** * Helps ToStringAlgo compute the String representation of the rest of the list. */ class ToStringHelper implements IListAlgo { public static final ToStringHelper Singleton = new ToStringHelper(); private ToStringHelper() {    }
/**
* Returns the accumulated String + ")".
* At end of list: done!
*/
public Object emptyCase(MTList host, Object... acc) {
return  acc[0] + ")";
}
 
/**
* Continues accumulating the String representation by appending ", " + first to acc
* and recurse!
*/
public Object nonEmptyCase(NEList host, Object... acc) {
return host.getRest().execute(this, acc[0] + ", " + host.getFirst());
}
}
 
 

We now can use to ToStringAlgo to implement the toString() method of an IList.

package listFW;
public class MTList implements IList {
/**
* Singleton Pattern
*/
public final static MTList Singleton = new MTList();
private MTList() { }
/**
* Calls the empty case of the algorithm algo,
* passing to it itself as the host parameter
* and the given input inp as the input parameter.
* This method is marked as final to prevent all
* subclasses from overriding it.
* Finalizing a method also allows the compiler to
* generate more efficient calling code.
*/
public final Object execute(IListAlgo algo, Object... inp) {
return algo.emptyCase(this, inp);
}
public String toString() {
return (String)ToStringAlgo.Singleton.emptyCase(this);
}
}
 
package listFW;
public class NEList implements IList {
/**
* The first data element.
*/
private Object _first; 
/**
* The rest or "tail" of this NEList.
* Data Invariant: _rest != null;
*/
private IList _rest;
/**
* Initializes this NEList to a given first and a given rest.
* @param f the first element of this NEList.
* @param r != null, the rest of this NEList.
*/
public NEList(Object f, IList r) {
_first = f;
_rest = r;
    }
/**
* Returns the first data element of this NEList.
* This method is marked as final to prevent all subclasses 
* from overriding it.
* Finalizing a method also allows the compiler to generate 
* more efficient calling code.
*/
public final Object getFirst() {
return _first;
}
/**
* Returns the first data element of this NEList.
* This method is marked as final to prevent all 
* subclasses from overriding it.
* Finalizing a method also allows the compiler 
* to generate more efficient calling code.
*/
public final IList getRest() {
return _rest;
} 
/**
* Calls the nonEmptyCase method of the IListAlgo parameter, 
* passing to the method itself as the host parameter and the 
* given input as the input parameter.
* This method is marked as final to prevent all subclasses from
* overriding it. Finalizing a method also allows the compiler 
* to generate more efficient calling code.
*/
public final Object execute(IListAlgo algo, Object... inp) {
return algo.nonEmptyCase(this, inp);
}
public String toString() {
return (String)ToStringAlgo.Singleton.nonEmptyCase(this);
}
}
 

Download the above code here