// File EmployeeTest.java 

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

public class EmployeeTest 
{   public static void main(String[] args)
    {   EmployeeRoster allEmps = new EmployeeRoster();

        CEO c1 = new CEO("C1",new StringId("1"),null);
        Clerical s1  = new Clerical("S1",new StringId("101"),c1);
        c1.newSecretary(s1);  
        allEmps.hire(c1);  allEmps.hire(s1);
        System.out.println( "1:  " + c1.name());       //  1
        System.out.println( "2:  " + c1.dept());       //  2
        System.out.println( "3:  " + c1.secretary());  //  3
        System.out.println( "4:  " + s1.dept());       //  4

        Manager m2  = new Manager("M2",new StringId("2"),c1,"Dept2",null);
        Clerical s2 = new Clerical("S2",new StringId("102"),m2);
        Staff p2    = new Staff("P2",new StringId("52"),m2);
        m2.newSecretary(s2);
        allEmps.hire(m2);  allEmps.hire(s2);  allEmps.hire(p2);
        System.out.println( "5:  " + s2.boss());          //  5
        System.out.println( "6:  " + s2.boss().boss() );  //  6

        Manager m3  = new Manager("M3",new StringId("3"),c1,"Dept3",null);
        Clerical s3 = new Clerical("S3",new StringId("103"),m3);
        Staff p3    = new Staff("P3",new StringId("53"),m3);
        m3.newSecretary(s3);
        allEmps.hire(m3); allEmps.hire(s3); allEmps.hire(p3);

        Enumeration enum = allEmps.elements();
        for (int j = 7 ; enum.hasMoreElements(); j++)	 // 7++
        {   Employee e = (Employee) enum.nextElement();
            System.out.println( String.valueOf(j) + ":  " + e.name()) ;
        }

	// Partial testing of Problem #9
        Identifier pid = new ProjectId(7); 
        Identifier qid = new ProjectId(9); 
	Identifier rid = new ProjectId(7);
        System.out.println("Projectid 7? " + 
			   ((Integer)pid.getId()).intValue()); 
        System.out.println("Projectid 9? " + 
			   ((Integer)qid.getId()).intValue()); 
        System.out.println("Projectid 7 (second)? " + 
			   ((Integer)rid.getId()).intValue()); 
        System.out.println("Projectid 7=9? " + pid.equals(qid));
        System.out.println("Projectid 7=7? " + pid.equals(rid));
	Identifier sid = new StringId("7");
	Identifier tid = new StringId("7");
        System.out.println("Projectid 7= StringId 7? " + pid.equals(sid));

	// Partial testing of Problem #10
	Programmer hacker = 
	    new Programmer("Hacker",new StringId("Pr1"),m3,pid);
	Programmer cracker = 
	    new Programmer("Cracker",new StringId("Pr2"),m3,qid);
	Programmer smacker = 
	    new Programmer("Smacker",new StringId("Pr3"),m2,pid);
	System.out.println("Hacker and Cracker same proj? " +
			   hacker.sameProject(cracker));
	System.out.println("Hacker and Smacker same proj? " +
			   hacker.sameProject(smacker));
	System.out.println("Hacker and m3 same proj? " +
			   hacker.sameProject(m3));

	System.out.println("Hacker's boss? " + hacker.boss() );
        System.out.println("Hacker:  " + hacker) ;
    }
}

interface Identifier
{   public Object getId();
    public boolean equals(Object i);
}

class StringId implements Identifier 
{   public StringId(String i) { _id = i; } 
    public Object getId() { return _id; } 

    public boolean equals(Object i) 
    {   if (i instanceof StringId) 
        {   StringId sid = (StringId) i;
            String   s   = (String) sid.getId();
            return _id.equals(s);
        }
        else return false;
    }
    private String _id; 
}

abstract class Employee
{   public Employee(String n, Identifier i, Manager s)
    {  _name = n; _id = i; _supervisor = s; }

    public String name() { return _name; }
    public Identifier id() { return _id; }
    public Manager boss() { return _supervisor; }
    abstract public String dept();
    public void newSupervisor(Manager m) { _supervisor = m; }

    public String toString() 
    { return "[" + name() + "," + (String) id().getId() 
             + "," + dept() + "]" ; 
    }
    private String     _name;       // this employee's name
    private Identifier _id;         // this employee's unique id
    private Manager    _supervisor; // this employee's immediate supervisor
}

class Staff extends Employee
{   public Staff(String n, Identifier i, Manager s) { super(n,i,s);} 
    public String dept() { return boss().dept(); };
}

class Clerical extends Staff
{   public Clerical(String n, Identifier i, Manager s) { super(n,i,s);} }

class Manager extends Employee
{   public Manager(String n, Identifier i, Manager s, String d, Clerical c)
    { super(n,i,s); _dept = d; _secretary = c; }

    public Clerical secretary() { return _secretary; }
    public void newSecretary(Clerical c) { _secretary = c; }
    public String dept() { return _dept; }

    private String   _dept;       // the department supervised 
    private Clerical _secretary;  // the manager's secretary
}


class CEO extends Manager // Chief Executive Officer
{   public CEO(String n, Identifier i, Clerical c) 
    { super(n,i,null,"CEO",c);} 
}

class EmployeeRoster
{   public EmployeeRoster() { _roster = new Vector(); }

    public void hire(Employee e)  // add to vector if not there
    {   for (int i = 0;  i < _roster.size(); i++)
        {   Employee f = (Employee) (_roster.elementAt(i));
            if ( f.id().equals(e.id()) ) return;
        }
        _roster.addElement(e);
    }

    public void fire(Employee e)   // remove from vector
    {   for (int i = 0;  i < _roster.size(); i++)
        {   Employee f = (Employee) _roster.elementAt(i);
            if ( f.id().equals(e.id()) ) _roster.removeElementAt(i);
        }
    }

    public Enumeration elements() { return _roster.elements(); }
    public void terminate() { _roster = null; }

    private Vector _roster;  // the employees 
}

class ProjectId implements Identifier // Problem #9
{   public ProjectId(int i) { _id = i; } 
    public Object getId() { return new Integer(_id); } 

    public boolean equals(Object i) 
    {   if (i instanceof ProjectId) 
        {   ProjectId pid = (ProjectId) i;
            int v = ((Integer) pid.getId()).intValue();
            return _id == v ;
        }
        else 
            return false;
    }
    private int _id; 
}

class Programmer extends Staff // Problem #10
{   public Programmer(String n, Identifier i, Manager s, Identifier p) 
    {   super(n,i,s);  _project = p; }

    public Identifier getProject() { return _project; }

    public void setProject(Identifier p)
    {   _project = p; }

    public boolean sameProject (Employee e)
    {   if (e instanceof Programmer)
        {   Identifier epid = ((Programmer) e).getProject();
            return _project.equals(epid);
        }
    else
        return false;
    }

    private Identifier _project;  // ProjectId?
}

