// CS100J Spring 2001
// Exercise 5 solution
// Jing Ming, modifications by DIS

// create and describe the family tree for Part 3a:
//
//            Dimmu                   
//            age 60
//               |              Dimmu is Borgir's parent.    
//               |                        
//             Borgir                       
//             age 40
//             / | \            
//            /  |  \           
//     Arcturus Tad  Borknagar
//     age 20 age 18  age 17
//

public class e5sp01sol {

    public static void main(String[] args) {

	Parthon dimmu = new Parthon("Dimmu", 60, null);
	Parthon borgir = new Parthon("Borgir", 40, dimmu);
	Parthon arcturus = new Parthon("Arcturus", 20, borgir);
	Parthon tad  = new Parthon("Tad", 18, borgir);
	Parthon borknagar = new Parthon("Borknagar", 17, borgir);

	System.out.println(dimmu);
	System.out.println(borgir);
	System.out.println(arcturus);
	System.out.println(tad);
	System.out.println(borknagar);

	/* Output:
	   Dimmu,  60, no P, no GP, no OS, YC Borgir, OC Borgir
	   Borgir, 40, P Dimmu, no GP, no OS, YC Borknagar, OC Arcturus
	   Arcturus, 20, P Borgir, GP Dimmu, no OS, no YC, no OC
	   Tad, 18, P Borgir, GP Dimmu, OS Arcturus, no YC, no OC
	   Borknagar, 17, P Borgir, GP Dimmu, OS Tad, no YC, no OC
	*/
    }

} // Class e5sp01sol


// Parthenogenic alien race Parthon:
class Parthon {
    // Instance variables:
       private String  name;               // name
       private int     age;                // age
       private Parthon parent;             // parent, if any
       private Parthon olderSibling;       // closest older sibling, if any
       private Parthon youngestChild;      // youngest child, if any
    
    // Create a new youngest child of parent with $name$, $age$, no children
    // ($parent$ may be $null$)
       Parthon(String name, int age, Parthon parent) {

	   this.name   = name;
	   this.age    = age;
	   this.parent = parent;

	   // Set parent's youngest chold to current Parthon:
	      if (parent == null) 
		  olderSibling = null;
	      else {
		  olderSibling = parent.youngestChild;
		  parent.youngestChild = this;
	      }

	   youngestChild = null; // no children of current Parthon
       } 
    
    // Return labeled relative or "no $label$" (if relative does not exist)
       private String helpdescribe(String label, Parthon relative) {
	   return relative == null ? "no " + label : label + " " + relative.name;
	   /* Could have written as:
	      if (relative == null) return "no " + label;
	      else return label + " " + relative.name;
	      return "Something went wrong!";
	   */
    }
    
    // Print a description of the Parthon: name, age, names of
    // parent, grandparent, older sibling, youngest child, oldest child.
    // Use labels P, GP, OS, YC, OC, respectively.
    // If a relative "R" does not exist, indicate by printing "no R":
       public String toString() {
	   return (name + ",\t" + age
		   + ", " + helpdescribe("P", parent)
		   + ", " + helpdescribe("GP", grandparent())
		   + ", " + helpdescribe("OS", olderSibling)
		   + ", " + helpdescribe("YC", youngestChild)
		   + ", " + helpdescribe("OC", oldestChild()));
       }
    
    // Return grandparent, if any
       Parthon grandparent() {
	   return parent == null ? null : parent.parent;
       }
    
    /* the methods describeAll and oldestSibling call themselves --
       yes, if done properly, this works!  
       this powerful technique of *recursion* is usually a cs211/cs312 topic.
    */
    
    // Describe entire family tree below and including self
       public void describeAll() {
	   System.out.println(this);   // System.out.println(toString());
	   if (youngestChild != null)  System.out.println(youngestChild);
	   if (olderSibling != null)   System.out.println(olderSibling);
       }
    
    // Return oldest sibling or self (if have no oldest sibling)
       private Parthon oldestSibling() {
	   return olderSibling == null ? this : olderSibling.oldestSibling();
       }
    
    // Return oldest child, if any
       private Parthon oldestChild() {
	   return youngestChild == null ? null : youngestChild.oldestSibling();
       }
    
    // Setter and getter methods:
       public void    setName(String n)  { name = n; }
       public String  getName()          { return name; }
       public void    setAge(int a)      { age = a; }
       public int     getAge()           { return age;  }
       public Parthon getParent()        { return parent; }
       public Parthon getOlderSibling()  { return olderSibling; }
       public Parthon getYoungestChild() { return youngestChild; }

} // Class Parthon
