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

// Based on SpeciesSet

public class SpeciesTreeSet {
    // OVERVIEW: SpeciesTreeSets are unbounded, mutable sets of SpeciesTree.
    //    A typical SpeciesTreeSet is { x1, ..., xn }

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

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

    public void insert (/*@non_null@*/ SpeciesTree 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 union (SpeciesTreeSet s) {
	// MODIFIES: this
	// EFFECTS: Adds all elements of s to the elements of this: this_post = this_pre U s
	//    If s is null, does nothing.
	if (s != null) { 
	    int oldsize = size ();
	    for (Enumeration e = s.elements (); e.hasMoreElements (); ) {
		insert ((SpeciesTree) e.nextElement ());
	    }

	    if (size () != oldsize + s.size ()) {
		System.err.println ("Size mismatch!");
		System.err.println (toString () + " / " + s.toString ());
	    }
	}
    }

    public void remove (/*@non_null@*/ SpeciesTree 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@*/ SpeciesTree s) {
	// EFFECTS: Returns true iff s is an element of this.  
	return getIndex (s) >= 0;
    }

    private int getIndex (/*@non_null@*/ SpeciesTree 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 int size () {
	// EFFECTS: Returns the number of elements in this.
	return els.size ();
    }

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

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

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

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

	    res += els.elementAt (i);
	}

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