001    package rac;
002    
003    import listFW.*;
004    import listFW.factory.*;
005    import lrs.*;
006    
007    /**
008     * Implements a factory for restricted access containers.  These
009     * restricted access containers are implemented using an LRStruct to
010     * hold the data objects.
011     * @author Mathias Ricken - Copyright 2008 - All rights reserved.
012     */
013    public abstract class ALRSRACFactory<T> implements IRACFactory<T> {
014      /**
015       * Implements a general-purpose restricted access container using
016       * an LRStruct.  How? 
017       *
018       * The next item to remove is always at the front of the list of
019       * contained objects.  This is invariant!
020       *
021       * Insertion is, however, delegated to a strategy routine; and
022       * this strategy is provided to the container.  This strategy
023       * varies to implement the desired kind of container, e.g., queue
024       * vs. stack.
025       *
026       * This inner class is protected so that classes derived from its
027       * factory can reuse it to create other kinds of restricted access
028       * container. 
029       */
030      protected class LRSRAContainer<T> implements IRAContainer<T> {
031        private IAlgo<T,LRStruct<T>,T> _insertStrategy;
032        private LRStruct<T> _lrs;
033        
034        public LRSRAContainer(IAlgo<T,LRStruct<T>,T> strategy) {
035          _insertStrategy = strategy;
036          _lrs = new LRStruct<T>();
037        }
038        
039        /**
040         * Empty the container.
041         */
042        public void clear() {
043          _lrs = new LRStruct<T>();
044        }
045            
046        /**
047         * Return TRUE if the container is full; otherwise, return
048         * FALSE. 
049         *
050         * This implementation can hold an arbitrary number of
051         * objects.  Thus, always return false.
052         */
053        public boolean isFull() {
054          return false;
055        }
056        
057        /**
058         * Return an immutable list of all elements in the container.
059         */
060        public IList<T> elements(final IListFactory<T> fact) {
061          return _lrs.execute(new IAlgo<T,IList<T>,Void>() {               
062            public IList<T> emptyCase(LRStruct<T> host, Void... input) {
063              return fact.makeEmptyList();
064            }
065            
066            public IList<T> nonEmptyCase(LRStruct<T> host, Void... input) {
067              return fact.makeNEList(host.getFirst(),
068                                     host.getRest().execute(this, input));
069            }
070          });
071        }
072        
073        /**
074         * Remove the next item from the container and return it.
075         */
076        public T get() {
077          return _lrs.removeFront();
078        }
079        
080        /**
081         * Add an item to the container.
082         */
083        @SuppressWarnings("unchecked")
084        public void put(T input) {
085          _lrs.execute(_insertStrategy, input);
086        }
087        
088        /**
089         * Return the next element in this IRAContainer withour removing it.
090         * @throw an Exception if this IRAContainer is empty.
091         */
092        public T peek() {
093          return _lrs.getFirst();
094        }
095        
096        /**
097         * Extensibility hook to accept a visitor algorithm.
098         * @param v  The visitor to execute
099         * @param inp An arbitrary input parameter for the visitor
100         * @return The return value of the calculation performed by the visitor.
101         */
102        public <R,P> R execute(final IRACVisitor<T,R,P> v, P... inp) { 
103          return _lrs.execute(new IAlgo<T,R,P>() {
104            public R emptyCase(LRStruct<T> host, P... i) {
105              return v.emptyCase(LRSRAContainer.this, i);
106            }
107            public R nonEmptyCase(LRStruct<T> host, P... i) {
108              return v.nonEmptyCase(LRSRAContainer.this, i);          
109            }
110          }, inp);
111        }
112        
113      }    
114    }
115