/*
 * $Log: Set.java,v $
 * Revision 1.5  1996/06/08  05:55:48  hma
 * add name to the set.
 *
 * Revision 1.4  1996/06/08  04:33:13  hma
 * added method complement( Set ), which takes the THIS set as omega.
 *
 * Revision 1.3  1996/04/14  22:45:05  inder
 * now throwing GenericException from put()
 *
 * Revision 1.2  1996/04/14  21:40:28  inder
 * wrote code to make sure that Set contains objects of only one type.
 *
 * Revision 1.1  1996/03/18  19:08:23  rlj1
 * Initial revision
 *
 */
//////////////////////////////////////////////////
package general;

// Standard packages.
import java.util.*;

// Packages specific to Network Design Tool.
import general.GenericException;
//////////////////////////////////////////////////
public class Set extends Hashtable implements Cloneable {

  private Class ClassOfMembers;	    // Type of set members.
  private String name;

  public Set(Class SetOfClass) {	   
    // REQUIRES:
    // 1. SetOfClass is the runtime representation of the class, obtained by
    // getClass() 
    // RETURNS: nothing.
    // PROMISES: 1. This set contains objects of type only SetOfClass.
    
    ClassOfMembers = SetOfClass;
    name = "unnamed";
  }

  public Object clone() {
    Set clonedSet = new Set(this.ClassOfMembers, this.name);
    Object tmpObj;
    for (Enumeration e = this.keys(); e.hasMoreElements();) {
      tmpObj = e.nextElement();
      clonedSet.put(tmpObj, this.get(tmpObj));
    }
    return clonedSet;
  }

  public synchronized String toString() {
    int max = size() - 1;
    StringBuffer buf = new StringBuffer();
    Enumeration k = keys();
    buf.append("{");
    
    for (int i = 0; i <= max; i++) {
      String s = k.nextElement().toString();
      buf.append(s);
      if (i < max) {
	buf.append(", ");
      }
    }
    buf.append("}");
    return buf.toString();
  }


  public String getName() {
    return name;
  }

  public void setName(String Name) {
    name = Name;
  }

  public Set(Class SetOfClass, String Name) {
    ClassOfMembers = SetOfClass;
    name  = Name;
  }

  /** add the Object to the set if the key is not already used */
  public boolean add(Object key, Object value) {
    if (containsKey(key))
      return false;

    put(key, value);
    return true;
  }
  

  public synchronized Object put(Object key, Object value) {
    // REQUIRES: nothing.
    // RETURNS: nothing.
    // PROMISES: 1. Throws GenericException if value is not of the type with
    // which set was created.
    
    if(value.getClass() != ClassOfMembers) 
      throw(new GenericException("Trying to put illegal value in Set!"));
    return super.put(key,value);
  }

  public synchronized Set intersection(Set a) {
    // returns the intersection of set a and "this" set
    // enumerates the key of the set a, if it's in "this" set, then
    // put the object associated with the key into the set i.
    if (a.ClassOfMembers != ClassOfMembers)
      throw (new GenericException("Set a should have the same class as this set!"));
    Set i = new Set(ClassOfMembers);
    Enumeration e = a.keys();
    Object k;
    for (; e.hasMoreElements();) {
      k = e.nextElement();
      // if the key is not contained in set a,
      // put it into the complement set
      if (containsKey(k))
	i.put(k, a.get(k));
    }
    return i;
  }

  public Vector getVector() {
    Vector v = new Vector(this.size());
    for (Enumeration e = this.elements(); e.hasMoreElements();)
      v.addElement(e.nextElement());
    return v;
  }

  public Object[] getArray() {
    Object[] o = new Object[this.size()];
    Enumeration e = elements();
    int i = 0;
    while (e.hasMoreElements()) {
      o[i] = e.nextElement();
      i++;
    }
    return o;
  }


  
  public synchronized Set complement(Set a) {
    // returns the complement of set a, "this" set is taken as omega
    // enumerates the key of the this set, if it's not in set a, then
    // put the object associated with the key into the complement set.
    if (a.ClassOfMembers != ClassOfMembers)
      throw (new GenericException("Set a should have the same class as this set!"));
    Set c = new Set(ClassOfMembers);
    Enumeration e = keys();
    Object k;
    for (; e.hasMoreElements();) {
      k = e.nextElement();
      // if the key is not contained in set a,
      // put it into the complement set
      if (!a.containsKey(k))
	c.put(k, get(k));
    }
    return c;
  }

    
} //end of class Set
//////////////////////////////////////////////////
