import java.util.Vector;
import java.util.Enumeration;

// Based on StringSet

public class SpeciesSet {
    // OVERVIEW: SpeciesSets are unbounded, mutable sets of Species.
    //    A typical SpeciesSet is { x1, ..., xn }

    private Vector els;
    //@invariant els != null
    //@invariant els.elementType == \type(Species)
    //@invariant els.containsNull == false
    // invariant els does not contain two species with the same name.

    public SpeciesSet () {
	// EFFECTS: Initializes this to be empty: { }
	els = new Vector ();
	//@set els.elementType = \type(Species)
	//@set els.containsNull = false
    }

    public SpeciesSet (/*@non_null@*/ SpeciesSet s) {
	// EFFECTS: Initializes this to be a copy of s.
	els = new Vector (s.els.size ());
	for (int i = 0; i < s.els.size (); i++) {
	    els.add ((Species) s.els.elementAt (i)); //@nowarn Pre
	}
	//@set els.elementType = \type(Species)
	//@set els.containsNull = false
    }

    public void insert (/*@non_null@*/ Species s) {
	// MODIFIES: this
	// EFFECTS: Adds x to the elements of this: this_post = this_pre U { s }
	if (getIndex (s) < 0) els.add (s); 
    }

    public void remove (/*@non_null@*/ Species s) {
	// MODIFIES: this
	// EFFECTS: Removes s from this: this_post = this_pre - { s }
	int i = getIndex (s);
	if (i < 0) return;
	els.removeElementAt (i);
    }

    public boolean isIn (/*@non_null@*/ String s) {
	// EFFECTS: Returns true iff s is the name of a Species of this.  
	for (int i = 0; i < els.size (); i++) {
	    if (s.equals (((Species) els.elementAt (i)).getName ()))
		return true;
	    }

	return false;
    }
	
    public boolean isIn (/*@non_null@*/ Species s) {
	// EFFECTS: Returns true iff s is an element of this.  
	return getIndex (s) >= 0;
    }

    private int getIndex (/*@non_null@*/ Species s) 
	//@ensures \result >= -1
	//@ensures \result < els.elementCount
    {
	// EFFECTS: If x is in this returns index where x appears, else returns -1.
	for (int i = 0; i < els.size (); i++) {
	    if (s.equals (els.elementAt (i))) {
		return i;
	    }
	}
	return -1;
    }

    public boolean isEmpty () {
	// EFFECTS: Returns true iff the set has no elements.
	return els.size () == 0;
    }

    public int size () {
	// EFFECTS: Returns the number of elements in this.
	return els.size ();
    }

    public /*@non_null@*/ Enumeration elements () 
	//@ensures \result.returnsNull == false
	//@ensures \result.elementType == \type(Species)
    {
	// EFFECTS: Returns an interator that iterates through the elements of the set.
	return els.elements ();
    }

    public Species [] toArray () 
	// EFFECTS: Returns an array containing all the elements in this.
	//@ensures \result != null
	//@ensures \nonnullelements (\result)
    {
	Species [] res = new Species [els.size ()];

	for (int i = 0; i < els.size (); i++) {
	    res[i] = (Species) els.elementAt (i);
	}

	return res;
    }

    public String toString () {
	// EFFECTS: Returns a String depecting the set.
	String res = "SpeciesSet:{ ";
	boolean firstone = true;

	for (int i = 0; i < els.size (); i++) {
	    if (firstone) {
		firstone = false;
	    } else {
		res += ", ";
	    }

	    res += els.elementAt (i);
	}

	res += "}";
	return res;
    }
}