001    /*
002     * Default Queue Implementation
003     *
004     * Developed for "Rethinking CS101", a project of Lynn Andrea Stein's AP Group.
005     * For more information, see <a href="http://www.ai.mit.edu/projects/cs101/">the
006     * CS101 homepage</a> or email <las@ai.mit.edu>.
007     *
008     * Copyright (C) 1998 Massachusetts Institute of Technology.
009     * Please do not redistribute without obtaining permission.
010     */
011    
012    package cs101.util.queue;
013    
014    import java.util.Enumeration;
015    import java.util.NoSuchElementException;
016    
017    /** 
018     * Default Queue class.  Allows insertion/deletion at either end.
019     * Throws EmptyQueueException in some situations, but
020     * EmptyQueueException is a subclass of RuntimeException, so you don't
021     * have to protect Queue access with try/catch blocks.
022     * <p> 
023     * Copyright (c) 1998 Massachusetts Institute of Technology
024     *
025     * @author Todd C. Parnell, tparnell@ai.mit.edu
026     * @version $Id: DefaultQueue.java,v 1.2 2003/09/23 14:46:57 gus Exp $
027     *
028     * @see cs101.util.queue.EmptyQueueException 
029     */
030    public class DefaultQueue implements Queue {
031    
032      private Link first, last;
033      private int count;
034    
035      /** Creates a new, empty Queue */
036      public DefaultQueue () {}
037    
038      /** Creates a new Queue contining obj as the only element */
039      public DefaultQueue (Object obj) {
040        this.first = this.last = new Link (obj);
041        this.count = 1;
042      }
043    
044      /** Returns the number of elements in this. */
045      public synchronized int size() { return this.count; }
046    
047      /** 
048       * Gets the tail object from the queue </B>without</B> removing
049       * it. 
050       */
051      public synchronized Object peek() {
052        return this.peek(Queue.BACK);
053      }
054    
055      /** 
056       * Gets the object from the specified end of the queue
057       * </B>without</B> removing it. 
058       */
059      public synchronized Object peek(int end) {
060        if (this.isEmpty()) throw new EmptyQueueException();
061        if (end == Queue.FRONT)
062          return this.first.contents();
063        else
064          return this.last.contents();
065      }
066    
067      /** Puts obj into the front the queue. */
068      public synchronized void enqueue(Object obj) {
069        this.enqueue(obj, Queue.FRONT);
070      }
071    
072      /** Puts obj into the specified end of the queue. */
073      public synchronized void enqueue(Object obj, int end) {
074        if (this.isEmpty()) {
075          this.first = this.last = new Link(obj);
076        } else {
077          if (end == Queue.FRONT) {
078            Link tmp = new Link(obj);
079            tmp.setNext(this.first);
080            this.first.setPrevious(tmp);
081            this.first = tmp;
082          }
083          else /* end == Queue.BACK */ {
084            Link tmp = new Link(obj);
085            tmp.setPrevious(this.last);
086            this.last.setNext(tmp);
087            this.last = tmp;
088          }
089        }
090        this.count++;
091      }
092    
093      /** Removes and returns the Object at the tail of the queue. */
094      public synchronized Object dequeue() {
095        return this.dequeue(Queue.BACK);
096      }
097    
098      /** Removes and returns the Object at the specified end of the queue. */
099      public synchronized Object dequeue(int end) {
100        if (this.isEmpty()) throw new EmptyQueueException();
101        this.count--;
102        if (end == Queue.FRONT) {
103          Object tmp = this.first.contents();
104          Link l_tmp = this.first.next();
105          this.first.setNext(null);    // remove reference
106          this.first = l_tmp;
107          if (this.first == null) {
108            this.last = null;
109          }
110          else {
111            // remove dangling reference for gc
112            this.first.setPrevious(null);
113          }
114          return tmp;
115        }
116        else /* end == Queue.BACK */ {
117          Object tmp = this.last.contents();
118          Link l_tmp = this.last.previous();
119          this.last.setPrevious(null);
120          this.last = l_tmp;
121          if (this.last == null) {
122            this.first = null;
123          }
124          else {
125            this.last.setNext(null);
126          }
127          return tmp;
128        }
129      }
130    
131      /** Tests whether the queue is empty. */
132      public synchronized boolean isEmpty () {
133        return (this.first == null);
134      }
135    
136      /** 
137       * Returns an Enumeration of the Objects in the queue.<p> 
138       *
139       * <I>Note: Do not modify the queue while enumerating--unpredictable
140       * behavior may result.</I>
141       *
142       * @see java.util.Enumeration
143       */
144      public Enumeration elements() { 
145        return new QueueEnumeration(this.first); 
146      }
147    
148      public synchronized String toString() {
149        StringBuffer sb = new StringBuffer("cs101.util.Queue: [");
150        Enumeration enum = this.elements();
151        while (enum.hasMoreElements()) {
152          sb.append(enum.nextElement());
153          if (enum.hasMoreElements()) sb.append(", ");
154        }
155        sb.append("]");
156        return sb.toString();
157      }
158          
159      /** Inner class to make Queue.elements() happen. */
160      private class QueueEnumeration implements Enumeration {
161        private Link current;
162        
163        public QueueEnumeration(Link l) {
164          current = l;
165        }
166    
167        public boolean hasMoreElements() {
168          return (current != null);
169        }
170    
171        public Object nextElement() {
172          if (current == null) throw new NoSuchElementException();
173          Object tmp = current.contents();
174          current = current.next();
175          return tmp;
176        }
177      } // class QueueEnumeration
178      
179    
180      /** 
181       * Links form the building blocks for Queues. 
182       *
183       * @see Queue
184       */
185      class Link {
186    
187        private Link previous = null;
188        private Link next = null;
189        private Object contents;
190    
191        protected Link(Object obj) {
192          this.contents = obj;
193        }
194    
195        public Object contents() {
196          return this.contents;
197        }
198    
199        public Link next() {
200          return this.next;
201        }
202        
203        public Link previous() {
204          return this.previous;
205        }
206    
207        protected synchronized void setPrevious(Link link) {
208          this.previous = link;
209        }
210    
211        protected synchronized void setNext(Link link) {
212          this.next = link;
213        }
214    
215        public synchronized String toString() {
216          StringBuffer sb = new StringBuffer("cs101.util.Link: [previous:");
217          if (this.previous != null)
218            sb.append("linked");
219          else sb.append("null");
220          sb.append("] [contents:" + this.contents + "] [next:");
221          if (this.next != null)
222            sb.append("linked]");
223          else sb.append("null]");
224          return sb.toString();
225        }
226      } // class Link
227    }
228    
229    /*
230     * $Log: DefaultQueue.java,v $
231     * Revision 1.2  2003/09/23 14:46:57  gus
232     * javadoc fix
233     *
234     * Revision 1.1.1.1  2002/06/05 21:56:32  root
235     * CS101 comes to Olin finally.
236     *
237     * Revision 1.1  2000/04/24 22:17:18  nathanw
238     * Bulk reorganization
239     *
240     * Revision 1.3  1999/07/27 18:59:33  jsmthng
241     * Changed *all* instances of 'peak' to 'peek' this time. Really. (I
242     * hope.)
243     *
244     * Revision 1.2  1999/07/27 18:51:12  jsmthng
245     * Instances of 'peak' changed to the new spelling, 'peek', in compliance
246     * with the new version of cs101.util.Queue.
247     *
248     * Revision 1.1  1999/01/21 20:49:18  tparnell
249     * Made Queue.java an interface and added DefaultQueue.java as an implementation.
250     *
251     */