Splitter.java
package lrs.visitor;
import lrs.*;

/**
* Splits the host in half.  The host gets the first n/2 elements,
* and the other half gets the last n - n/2 elements.
*/
public class Splitter implements IAlgo {
    public final static Splitter Singleton = new Splitter ();

    private Splitter() {
    }

    /**
     * @param host
     * @param input
     * @return
     */
    public Object emptyCase(LRStruct host, Object input) {
        return new LRStruct();
    }

    /**
    *  Asks the host's tail to split passing host as a potential "split point".
     * @param host
     * @param input not used
     * @return
     */
    public Object nonEmptyCase(LRStruct host, Object input) {
        return host.getRest().execute(new Advance0(), host);
    }

    /**
     * "Quick and dirty" test.
     * @param args
     */
    public static void main(String[] args) {
        LRStruct l1 = new LRStruct ();
        System.out.println ("l1: " + l1);
        System.out.println ("Splitting l1...");
        LRStruct l2 = (LRStruct)l1.execute(Splitter.Singleton, null);
        System.out.println ("l1: " + l1);
        System.out.println ("l2: " + l2);

        l1.insertFront (new Integer (-9));
        l1.insertFront (new Integer (15));
        l1.insertFront (new Integer (263));
        l1.insertFront (new Integer (-72));
        l1.insertFront (new Integer (0));
        System.out.println ("l1: " + l1);
        System.out.println ("Splitting l1...");
        l2 = (LRStruct)l1.execute(Splitter.Singleton, null);
        System.out.println ("l1: " + l1);
        System.out.println ("l2: " + l2);

        l1.insertFront (new Integer (99));
        l1.insertFront (new Integer (-55));
        l1.insertFront (new Integer (12));
        l1.insertFront (new Integer (48));
        System.out.println ("l1: " + l1);
        System.out.println ("Splitting l1...");
        l2 = (LRStruct)l1.execute(Splitter.Singleton, null);
        System.out.println ("l1: " + l1);
        System.out.println ("l2: " + l2);
    }
}

class Advance0 implements IAlgo {

    IAlgo advance1 = new IAlgo() {
        /**
        * We know the input is a potential split point and now we are at the end of
        * the original list.  So we split right here at the split point.
        * @param host
        * @param accSplit
        * @return
        */
        public Object emptyCase(LRStruct host, Object accSplit) {
            return cutAt((LRStruct)accSplit);
        }

        /**
        *  Asks the host's tail to split passing input as a potential "split point".
        * @param host
        * @param accSplit  a LRStruct.
        * @return
        */
        public Object nonEmptyCase(LRStruct host, Object accSplit) {
            return host.getRest().execute(Advance0.this, accSplit);
        }
    };

    /**
    * We know the input is a potential split point and now we are at the end of
    * the original list.  So we split right here at the split point.
    * @param host
    * @param accSplit a LRStruct
    * @return
    */
    public Object emptyCase(LRStruct host, Object accSplit) {
        return cutAt((LRStruct)accSplit);
    }

    /**
    * We have not reached the end yet, so we advance the accumlated split point
    * by one.
    * @param host
    * @param accSplit
    * @return
    */
    public Object nonEmptyCase(LRStruct host, Object accSplit) {
        return host.getRest().execute(advance1, ((LRStruct)accSplit).getRest());
    }

    /**
     * Cut off the list containing splitPoint at splitPoint.
     * Return a list that shares the same node with splitPoint.
     * @param splitPoint
     * @return
     */
    private LRStruct cutAt(LRStruct splitPoint) {
        LRStruct tailHalf = new LRStruct ();
        tailHalf.execute (Becomes.Singleton, splitPoint);
        splitPoint.execute (Becomes.Singleton, new LRStruct ());
        return tailHalf;
    }
}