DictLRS.java
package dict;

import java.lang.*;
import lrs.*;
import listFW.*;
import listFW.factory.*;

/**
 * An implementation of IDictionary using an LRStruct to hold the
 * DictionaryPairs. 
 */
public class DictLRS implements IDictionary {
    
    /**
     * Visitor to check for emptiness.
     * Need only one for all DictLRS.
     * Non OO!
     */
    private static IAlgo IsEmpty = new IAlgo() {
        public Object emptyCase(LRStruct host, Object input) {
            return Boolean.TRUE;
        }
        
        public Object nonEmptyCase(LRStruct host, Object input) {
            return Boolean.FALSE;
        }
    };
    
    /*
     * A list of DictionaryPairs ordered by key
     */
    private LRStruct _lrs = new LRStruct();
    
    /**
     * Clears the contents of the dictionary leaving it empty.
     *
     * Implemented by replacing the existing LRStruct with a new,
     * empty one.
     */
    public void clear() {
        _lrs = new LRStruct();
    }
    
    /**
     * Returns true if the dictionary is empty and false otherwise.
     *
     * Implemented as a visitor to LRStruct.
     */
    public boolean isEmpty() {
        return ((Boolean)_lrs.execute(IsEmpty, null)).booleanValue();
    }
    
    /**
     * Returns false always.
     */
    public boolean isFull() {
        return false;
    }

    /**
     * Returns an IList of DictionaryPairs corresponding to the entire
     * contents of the dictionary.
     *
     * Implemented as a visitor to LRStruct.
     */
    public IList elements(final IListFactory lf) {        
        return (IList)_lrs.execute(new IAlgo() {
            public Object emptyCase(LRStruct host, Object input) {
                return lf.makeEmptyList();
            }
            
            public Object nonEmptyCase(LRStruct host, Object input) {
                return lf.makeNEList(host.getFirst(),
                                     (IList)host.getRest().execute(this, input));
            }
        }, null);
    }
    
    /**
     * Returns the DictionaryPair with the given key.  If there is not
     * a DictionaryPair with the given key, returns null. 
     *
     * Returns a DictionaryPair rather than the value alone so that
     * the user can distinguish between not finding the key and
     * finding the pair (key, null). 
     *
     * Implemented as a visitor to LRStruct.
     */
    public DictionaryPair lookup(Comparable key) {
        return (DictionaryPair)_lrs.execute(new IAlgo() {
            public Object emptyCase(LRStruct host, Object input) {
                return null;
            }
            
            public Object nonEmptyCase(LRStruct host, Object input) {
                DictionaryPair first = (DictionaryPair)host.getFirst();
                int result = first.getKey().compareTo(input);
                
                if (result > 0)  // host > input
                    return null;
                else if (result == 0) // host == input
                    return first;
                else   // host < input
                    return host.getRest().execute(this, input);
            }
        }, key);
    }
    
    /**
     * Inserts the given key and value.  If the given key is already
     * in the dictionary, the given value replaces the key's old
     * value. 
     *
     * Implemented as a visitor to LRStruct that inserts the key and
     * value in order.
     */
    public void insert(Comparable key, Object value) {
        _lrs.execute(new IAlgo() {
            public Object emptyCase(LRStruct host, Object input) {
                return host.insertFront(input);
            }
            
            public Object nonEmptyCase(LRStruct host, Object input) {
                DictionaryPair first = (DictionaryPair)host.getFirst();
                int result = first.compareTo(input);
                
                if (result > 0)  // host > input
                    return host.insertFront(input);
                else if (result == 0) // key == input
                    return host.setFirst(input);
                else   // host < input
                    return host.getRest().execute(this, input);
            }
        }, new DictionaryPair(key, value));
    }
    
    /**
     * Removes the DictionaryPair with the given key and returns it.
     * If there is not a DictionaryPair with the given key, returns
     * null.
     *
     * Implemented as a visitor to LRStruct.
     */
    public DictionaryPair remove(Comparable key) {
        return (DictionaryPair)_lrs.execute(new IAlgo() {
            public Object emptyCase(LRStruct host, Object input) {
                return null;
            }
            
            public Object nonEmptyCase(LRStruct host, Object input) {
                DictionaryPair first = (DictionaryPair)host.getFirst();
                int result = first.getKey().compareTo(input);
                
                if (result > 0)  // host > input
                    return null;
                else if (result == 0) { // host == input
                    host.removeFront();
                    return first;
                } else   // host < input
                    return host.getRest().execute(this, input);
            }
        }, key);
    }
    
    /**
     * Delegates the conversion to the LRStruct toString().
     */
    public String toString() {
        return _lrs.toString();
    }
}