/** * Recursive list of objects. * @author Jeff Raab */ public class RecursiveList implements IList, Position { /** First object in this. */ protected Object first; /** Rest of this. */ protected IList rest; /** * Constructs a recursive list containing the given object. * @param anObject object to be stored in the list */ public RecursiveList(Object anObject) { this(anObject, EmptyRecursiveList.EMPTY); } /** * Constructs a recursive list containing the given object, * with the given rest of the list. * @param anObject object to be stored in the list * @param aList rest of the list */ public RecursiveList(Object anObject, IList aList) { first = anObject; rest = aList; } /** Returns the first element in this. */ public Object element() { return first; } /** Returns the first position in this. */ public Position first() { return this; } /** Returns the last position in this. */ public Position last() { if (isLast(this)) { return this; } return rest.last(); } /** * Returns the position in this * that comes before the given position. * @param aPosition position for which previous position is desired */ public Position before(Position aPosition) { if ((aPosition == this) && isFirst(this)) { throw new RuntimeException("Position is first"); } if (aPosition == rest) { return this; } return rest.before(aPosition); } /** * Returns the position in this * that comes before the given position. * @param aPosition position for which previous position is desired */ public Position after(Position aPosition) { if (aPosition == this) { if (isLast(this)) { throw new RuntimeException("Position is last"); } else { return (RecursiveList)rest; } } return rest.after(aPosition); } /** * Returns whether or not the given position is first in this. * @param aPosition position to test */ public boolean isFirst(Position aPosition) { return (this == aPosition); } /** * Returns whether or not the given position is last in this. * @param aPosition position to test */ public boolean isLast(Position aPosition) { if (aPosition == this) { return rest.isEmpty(); } return rest.isLast(aPosition); } /** * Inserts the given object at the beginning of this, * increasing the size of this by 1. * @param anObject object to insert */ public IList insertFirst(Object anObject) { return new RecursiveList(anObject, this); } /** * Inserts the given object at the end of this, * increasing the size of this by 1. * @param anObject object to insert */ public IList insertLast(Object anObject) { rest = rest.insertLast(anObject); return this; } /** * Inserts the given object before the given position in this, * increasing the size of this by 1. * @param aPosition position to insert before * @param anObject object to insert */ public IList insertBefore(Position aPosition, Object anObject) { if (aPosition == this) { return new RecursiveList(anObject, this); } rest = rest.insertBefore(aPosition, anObject); return this; } /** * Inserts the given object after the given position in this, * increasing the size of this by 1. * @param aPosition position to insert before * @param anObject object to insert */ public IList insertAfter(Position aPosition, Object anObject) { if (aPosition == this) { rest = new RecursiveList(anObject, rest); return rest; } rest = rest.insertAfter(aPosition, anObject); return this; } /** Removes the first element of this. */ public IList removeFirst() { return rest; } /** Removes the last element of this. */ public IList removeLast() { if (isLast(this)) { return EmptyRecursiveList.EMPTY; } rest = rest.removeLast(); return this; } /** * Removes the given position from this. * @param aPosition position to remove */ public IList remove(Position aPosition) { if (aPosition == this) { return rest; } rest = rest.remove(aPosition); return this; } /** * Returns the element in the given position of this * and replaces it with the given object. * @param aPosition position of element to replace * @param anObject object to store in the given position */ public Object replaceElement(Position aPosition, Object anObject) { if (aPosition == this) { Object temp = first; first = anObject; return first; } return rest.replaceElement(aPosition, anObject); } /** Returns the size of this. */ public int size() { return 1 + rest.size(); } /** Returns whether or not this is empty. */ public boolean isEmpty() { return false; } }