source: src/main/java/weka/core/Queue.java @ 28

Last change on this file since 28 was 4, checked in by gnappo, 14 years ago

Import di weka.

File size: 8.7 KB
Line 
1/*
2 *    This program is free software; you can redistribute it and/or modify
3 *    it under the terms of the GNU General Public License as published by
4 *    the Free Software Foundation; either version 2 of the License, or
5 *    (at your option) any later version.
6 *
7 *    This program is distributed in the hope that it will be useful,
8 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
9 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 *    GNU General Public License for more details.
11 *
12 *    You should have received a copy of the GNU General Public License
13 *    along with this program; if not, write to the Free Software
14 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
15 */
16
17/*
18 *    Queue.java
19 *    Copyright (C) 1999 University of Waikato, Hamilton, New Zealand
20 *
21 *    Modified March-May 2004 by Mark Utting to add JML specs
22 *    (this was done as the example solution of an assignment for a
23 *     software engineering course, so the specifications are more precise
24 *     and complete than one would normally do).
25 *    Passed a static analysis using ESC/Java-2.0a6 with no warnings.
26 */
27
28package weka.core;
29
30import java.io.Serializable;
31
32/**
33 * Class representing a FIFO queue.
34 *
35 * @author Len Trigg (trigg@cs.waikato.ac.nz)
36 * @version $Revision: 5953 $
37 */
38public class Queue
39  extends Object
40  implements Serializable, RevisionHandler {
41
42  /** for serialization */
43  private static final long serialVersionUID = -1141282001146389780L;
44
45  /**
46   * Represents one node in the queue.
47   */
48  protected class QueueNode
49    implements Serializable, RevisionHandler {
50
51    /** for serialization */
52    private static final long serialVersionUID = -5119358279412097455L;
53
54    /** The next node in the queue */
55    protected /*@ spec_public @*/ QueueNode m_Next;
56
57    /** The nodes contents
58     */
59    protected /*@ non_null spec_public @*/ Object m_Contents;
60
61    /**
62     * Creates a queue node with the given contents
63     */
64    //@ requires contents != null;
65    //@ assignable m_Contents, m_Next;
66    //@ ensures m_Contents == contents;
67    //@ ensures m_Next == null;
68    public QueueNode(Object contents) {
69      m_Contents = contents;
70      next(null);
71    }
72
73    /**
74     * Sets the next node in the queue, and returns it.
75     */
76    //@ requires next != this ;
77    //@ assignable m_Next;
78    //@ ensures m_Next==next && \result==next;
79    public QueueNode next(QueueNode next) {
80      return m_Next = next;
81    } //@ nowarn Invariant; // Because it stupidly checks the Queue invariant!
82
83    /**
84     * Gets the next node in the queue.
85     */
86    //@ ensures \result == m_Next;
87    public /*@ pure @*/ QueueNode next() {
88      return m_Next;
89    }
90
91    /**
92     * Sets the contents of the node.
93     */
94    //@ requires contents != null;
95    //@ assignable m_Contents;
96    //@ ensures  m_Contents == contents && \result == contents;
97    public Object contents(Object contents) {
98      return m_Contents = contents;
99    }
100
101    /**
102     * Returns the contents in the node.
103     */
104      //@ ensures \result == m_Contents;
105    public /*@ pure @*/ Object contents() {
106      return m_Contents;
107    }
108   
109    /**
110     * Returns the revision string.
111     *
112     * @return          the revision
113     */
114    public String getRevision() {
115      return RevisionUtils.extract("$Revision: 5953 $");
116    }
117  }
118
119  /** Store a reference to the head of the queue */
120  protected /*@ spec_public @*/ QueueNode m_Head = null;
121
122  /** Store a reference to the tail of the queue */
123  protected /*@ spec_public @*/ QueueNode m_Tail = null;
124
125  /** Store the c m_Tail.m_Nexturrent number of elements in the queue */
126  protected /*@ spec_public @*/ int m_Size = 0;
127
128  //@ public invariant m_Head == null <==> m_Tail == null;
129  //@public invariant m_Tail != null ==> m_Tail.m_Next == null;
130  //@ public invariant m_Size >= 0;
131  //@ public invariant m_Size == 0 <==> m_Head == null;
132  //@ public invariant m_Size == 1 <==> m_Head != null && m_Head == m_Tail;
133  //@ public invariant m_Size > 1 ==> m_Head != m_Tail;
134  //@ public invariant m_Size > 1 <== m_Head != m_Tail;
135
136
137
138  /**
139   * Removes all objects from the queue m_Tail.m_Next.
140   */
141  //@ assignable m_Size, m_Head, m_Tail;
142  //@ ensures m_Size == 0;
143  //@ ensures m_Head == null;
144  //@ ensures m_Tail == null;
145  public final synchronized void removeAllElements() {
146    m_Size = 0;
147    m_Head = null;
148    m_Tail = null;
149  }
150
151  /**
152   * Appends an object to the back of the queue.
153   *
154   * @param item the object to be appended
155   * @return the object appended
156   */
157  //@ requires item != null;
158  //@ assignable m_Head, m_Tail, m_Tail.m_Next, m_Head.m_Next, m_Size;
159  //@ ensures m_Head != null;
160  //@ ensures m_Tail != \old(m_Tail);
161  //@ ensures m_Size == \old(m_Size) + 1;
162  //@ ensures \old(m_Size) == 0 ==> m_Head == m_Tail;
163  //@ ensures \old(m_Size) != 0 ==> m_Head == \old(m_Head);
164  //@ ensures m_Tail.contents() == \old(item);
165  //@ ensures \result == item;
166  public synchronized Object push(Object item) {
167    QueueNode newNode = new QueueNode(item);
168   
169    if (m_Head == null) {
170      m_Head = m_Tail = newNode;
171    } else {
172      m_Tail = m_Tail.next(newNode);
173    }
174    m_Size++;
175    return item;
176  }
177
178  /**
179   * Pops an object from the front of the queue.
180   *
181   * @return the object at the front of the queue
182   * @exception RuntimeException if the queue is empty
183   */
184  //@ assignable m_Head, m_Tail, m_Size;
185  //@ ensures m_Size == \old(m_Size) - 1;
186  //@ ensures m_Head == \old(m_Head.m_Next);
187  //@ ensures m_Head != null ==> m_Tail == \old(m_Tail);
188  //@ ensures \result == \old(m_Head.m_Contents);
189  //@ signals (RuntimeException) \old(m_Head) == null;
190  public synchronized Object pop() 
191      throws RuntimeException   // REDUNDANT, BUT ESCJAVA REQUIRES THIS
192  {
193    if (m_Head == null) {
194        throw new RuntimeException("Queue is empty");
195    }
196    Object retval = m_Head.contents();
197    m_Size--;
198    m_Head = m_Head.next();
199    // Here we need to either tell ESC/Java some facts about
200    // the contents of the list after popping off the head,
201    // or turn off the 'invariant' warnings.
202    //
203    //@ assume m_Size == 0 <==> m_Head == null;
204    //@ assume m_Size == 1 <==> m_Head == m_Tail;
205    if (m_Head == null) {
206      m_Tail = null;
207    }
208    return retval;
209  }
210
211  /**
212   * Gets object from the front of the queue.
213   *
214   * @return the object at the front of the queue
215   * @exception RuntimeException if the queue is empty
216   */
217  //@ ensures \result == \old(m_Head.m_Contents);
218  //@ signals (RuntimeException) \old(m_Head) == null;
219  public /*@ pure @*/ synchronized Object peek() 
220    throws RuntimeException
221  { 
222    if (m_Head == null) {
223      throw new RuntimeException("Queue is empty");
224    }
225    return m_Head.contents();
226  }
227
228  /**
229   * Checks if queue is empty.
230   *
231   * @return true if queue is empty
232   */
233  //@ ensures \result <==> m_Head == null;
234  public /*@ pure @*/ boolean empty() {
235    return m_Head == null;
236  }
237
238  /**
239   * Gets queue's size.
240   *
241   * @return size of queue
242   */
243  //@ ensures \result == m_Size;
244  public /*@ pure @*/ int size() {
245    return m_Size;
246  }
247
248  /**
249   * Produces textual description of queue.
250   *
251   * @return textual description of queue
252   */
253  //@ also
254  //@ ensures \result != null;
255  //@ ensures (* \result == textual description of the queue *);
256  public  /*@ pure @*/ String toString() {
257
258    String retval = "Queue Contents "+m_Size+" elements\n";
259    QueueNode current = m_Head;
260    if (current == null) {
261      return retval + "Empty\n";
262    } else {
263      while (current != null) {
264        retval += current.contents().toString()+"\n"; //@nowarn Modifies;
265        current = current.next();
266      }
267    }
268    return retval;
269  } //@ nowarn Post;
270 
271  /**
272   * Returns the revision string.
273   *
274   * @return            the revision
275   */
276  public String getRevision() {
277    return RevisionUtils.extract("$Revision: 5953 $");
278  }
279
280  /**
281   * Main method for testing this class.
282   *
283   * @param argv a set of strings that are pushed on a test queue
284   */
285  //@ requires argv.length >= 0;
286  //@ requires argv != null;
287  //@ requires (\forall int i; 0 <= i && i < argv.length; argv[i] != null);
288  public static void main(String [] argv) {
289
290    try {
291      Queue queue = new Queue();
292      for(int i = 0; i < argv.length; i++) {
293        queue.push(argv[i]);
294      }
295      System.out.println("After pushing command line arguments");
296      System.out.println(queue.toString());
297      while (!queue.empty()) {
298        System.out.println("Pop: " + queue.pop().toString());
299      }
300      // try one more pop, to make sure we get an exception
301      try 
302        {
303          queue.pop();
304          System.out.println("ERROR: pop did not throw exception!");
305        }
306      catch (RuntimeException ex)
307        {
308          System.out.println("Pop on empty queue correctly gave exception.");
309        }
310    } catch (Exception ex) {
311      System.out.println(ex.getMessage());
312    }
313  }
314}
Note: See TracBrowser for help on using the repository browser.