/******************************************************************************
    Stack

----------------------------------------------------
Copyright (c) Gunnar Gotshalks. All Rights Reserved.

Permission to use, copy, modify, and distribute this software
and its documentation for NON-COMMERCIAL purposes and
without fee is hereby granted. 
*******************************************************************************/

package FlexOr.container;
import java.util.Enumeration;

/**
The stack implements container which has the basic add and remove
methods that a stack needs.  Storage can be implemented by any Sequence type with
the default being a singly linked list. The choice of storage model is made at
stack creation time.  The front of the sequence is the top of the stack.

<P> Note that using Vector (not possible until Vector implements Sequence) gives
O(n) gives O(n) performance for remove() (pop) as the
entire contents of the Vector is shifted.  For a Vector it would be better to use
the tail end but this would give poor performance for a singly linked list implement
for pop as it would be O(n) due needing to find the predecessor.  For an array
implementation of stack storage it would be best to use a CircularArray -- element[0]
follows element[size-1] creating a ring-like structure.

@author Gunnar Gotshalks
@version 1.0 1999 Jan 16
@see SLList
@see Sequence
@see Container
*/

public class Stack implements Container {

/**
The default constructor selects a singly linked list as the storage container.
*/

  public Stack() { container = new SLList(); }
  
/**
The constructor permits the user to specify the type of storage container.

<P> The input container is cloned to minimize side effects of sharing. 
<P><PRE><B>Requires:</B> container is empty
<B>Ensures:</B> the stack uses the input storage type.
</PRE>
@exception NotEmptyException thrown when expecting an empty container but getting
a non empty container.
*/

  public Stack( final Sequence container) {
    if (container.isEmpty()) { this.container = (Sequence) container.clone(); }
    else { throw new NotEmptyException(); }
  }

/*******************************************************************************
   Defining the component objects
*******************************************************************************/
/**  The stack storage area */

  protected Sequence container;
  
/*******************************************************************************
   Access Methods -- interface to the underlying Sequence implementation.
*******************************************************************************/

/** Determines whether an element is in the stack.  Not really a stack operation
but useful for testing and debugging.
*/

  synchronized public boolean contains(final Object obj) { return container.contains(obj); }

/** Returns an enumerator over the whole stack.
@exception NoSuchElementException when nextElement is called with an empty
enumeration sequence.
*/
  
  synchronized public Enumeration<Object> elements() {
    return new Enumeration<Object> () {
      private Enumeration<Object> e = container.elements();
      public boolean hasMoreElements() { return e.hasMoreElements(); }
      public Object nextElement() { return e.nextElement(); }
    };
  }

/** Check if the stack is empty. */

  synchronized public boolean isEmpty() { return container.isEmpty(); }

/** Check if the stack is full. */

  synchronized public boolean isFull() { return container.isFull(); }

/** Returns the number of elements in the stack. */
  
  synchronized public int size() { return container.size(); }

/*******************************************************************************
   Update Methods -- interface to the underlying Sequence implementation.
*******************************************************************************/

/** Adds <CODE>obj</CODE> to the top of the stack.

<P><PRE><B>Requires:</B> True
<B>Ensures:</B> sequence = obj ^ old sequence
</PRE>
*/
  synchronized public void add(final Object obj) { container.insertAt(obj,0); }
  
/** Empty the stack.

<P><PRE><B>Requires:</B> True
<B>Ensures:</B> sequence = null // the empty sequence.
</PRE>
*/

  synchronized public void removeAll() { container.removeAll(); }

/** Return the top element in the stack.  If the stack is empty, return null.
    Should not store null in the list but can disambiguate with a check on not
    empty before the remove.

<P><PRE><B>Requires:</B> isEmpty = false
<B>Ensures:</B> old sequence = obj ^ sequence
</PRE>
*/

  synchronized public Object remove() { return container.remove(); }

/*******************************************************************************
   Object Methods
*******************************************************************************/

/** Return a shallow copy of the stack.
<P><PRE><B>Requires:</B> True
<B>Ensures:</B> result = copy of stack
</PRE>
*/

  synchronized public Object clone() {
    Stack result = new Stack();
    result.container = (Sequence) container.clone();
    return result;
  }
  
/** Return a string representation of the contents.
<P><PRE><B>Requires:</B> True
<B>Ensures:</B> result = string representation of contents
</PRE>
*/
  
  synchronized public String toString() { return container.toString(); }

/** Check for equality of contents of two stacks.  By equality we mean an
equal sequence of elements as returned by the Enumerator for each stack.
<P><PRE><B>Requires:</B> True
<B>Ensures:</B> result = true => contents are equal
                result = false => contents are not equal
</PRE>
 */

  synchronized public boolean equals(final Object obj) {
    if (obj == null || ! (obj instanceof Stack)) return false;
    else return container.equals( ((Stack) obj).container);
  }

}