// The Science of Computing Queue class.

// History:
//   August 2003 -- Created by Greg Scragg.
//   March 2004 -- made consistent with other documents for the text.
//   May 2004 -- Documentation cleaned up by Doug Baldwin.


package geneseo.cs.sc;

import java.io.*;


/**
 * Represents queues of arbitrary objects. These queues handle the standard messages
 * needed by any queue.
 * <p>This class was created to support the text <cite>Algorithms &amp; Data Structures:
 * The Science of Computing</cite> by Doug Baldwin and Greg Scragg. All references
 * in this documentation to &quot;the text&quot; refer to that book. Queues are described
 * in chapter 12 of the text; this class is basically the one developed in section
 * 12.1.6. Some methods that were &quot;left to an exercise&quot; in the text have
 * been fully implemented here, however.</p>
 */

public class Queue implements Serializable {

    private List content;
    private List endOfQueue;
        
    /**
     * Initialize a queue to be empty. For example
     * <p><code>Queue q = new Queue();</code></p>
     */ 
 
    // Creates the member List, content,and points the end of Queue pointer to that
    // empty list. 
          
    public Queue() {
        content = new List();
        endOfQueue = content;
    }     


    /**
     * Determines whether a queue is empty. For example
     * <p><code>if ( q.isEmpty() ) { ...</code></p>
     * @return True if the queue is empty, false if it is not.
     */
     
    public boolean isEmpty() {
        return content.isEmpty();
    }
    
    
    /**
     * Adds an object to the back of a queue (i.e., enqueues the
     * object). For example
     * <p><code>q.addToBack( "hello" );</code></p>
     * @param newItem The object to add to the queue.
     */
 
    public void addToBack (Object newItem) {
        endOfQueue.addItem (newItem);
        endOfQueue = endOfQueue.getRest();
    }
    

    /**
     * Removes and returns the object at the front of a Queue (i.e.,
     * dequeues that object). Requires the precondition that the queue
     * is not empty. For example
     * <p><code>Object dequeued = q.removeFromFront();</code></p>
     * @return The object removed from the queue.
     */         

    public Object removeFromFront() {
        Object temp = content.getAndRemove();
        if(content.isEmpty())
            endOfQueue = content;
        return temp;
    }
    

    /**
     * Prints the contents of a queue. For example
     * <p><code>q.printQueue();</code></p>
     */
            
    public void printQueue() {
        content.printList();
    }
    
    
    /**
     * Writes a queue to a file, replacing any previous data in that file. Exceptions
     * thrown while saving the queue produce an error message, but are not communicated
     * to client code. For example
     * <p><code>q.save( "QFile" );</code></p>
     * @param fileName The name of the file to write the queue to.
     */
    
    // This method opens a stream to the file, writes this Queue to the stream, and
    // closes the stream. If anything goes wrong while doing these things, this method
    // prints an error message but doesn't signal its client that anything has failed.
    // Simply uses the corresponding method for lists.
   
    public void save( String fileName ) {
       
        try {
       
            ObjectOutputStream out = new ObjectOutputStream( new FileOutputStream( fileName ) );
            out.writeObject( this );
            out.close();
        }
        catch ( Exception error ) {
            System.err.println( "Unable to save list: " + error );
        }
    }
     
    
    /**
     * Reads a queue from a file. The contents of the queue are replaced by the
     * contents of the file, if possible. If for some reason the file can't be read,
     * the contents of the queue are unchanged. Errors reading the file produce an
     * error message, but are not communicated to client code. For example
     * <p><code>q.restore( "QFile" );</code></p>
     * @param fileName The name of the file to restore the queue from.
     */
    
    // This opens an input stream and reads a Queue from that stream. If the read succeeds,
    // this then copies the new Queue's members into the Queue executing this method, thus
    // changing that Queue into the one read. If anything goes wrong in reading, this prints
    // an error message, but doesn't let client code know there was an error.
    // Simply uses the corresponding method for lists.
   
   public void restore( String fileName ) {
       
        try {
       
            ObjectInputStream in = new ObjectInputStream( new FileInputStream( fileName ) );
            Queue retrieved = (Queue) in.readObject();
            in.close();
       
            content = retrieved.content;
            endOfQueue = retrieved.endOfQueue;
        }
        catch ( Exception error ) {
            System.err.println( "Unable to restore a Queue: " + error );
        }
    } 

        
    /**
     * Generates a string representation of a queue. For example
     * <p><code>String text = q.toString();</code></p>
     * @return The string representation of the queue.
     */
    
    // This just returns the string representation of the "content" list.
      
    public String toString() { 
        return content.toString();
    }
        
}