001package edu.pdx.cs410J.family;
002
003import java.io.*;
004import java.text.*;
005import java.util.*;
006
007/**
008 * This class dumps a family tree to a text file in a format that can
009 * be read by a person.
010 *
011 * @author David Whitlock
012 */
013public class PrettyPrinter implements Dumper {
014
015  private PrintWriter pw;     // Where to pretty print to
016
017  /**
018   * Creates a new pretty printer that prints to a file of a given
019   * name.  If the file does not exist, it is created.
020   */
021  public PrettyPrinter(String fileName) throws IOException {
022    this(new File(fileName));
023  }
024
025  /**
026   * Creates a new pretty printer that prints to a given file.
027   */
028  public PrettyPrinter(File file) throws IOException {
029    this(new PrintWriter(new FileWriter(file), true));
030  }
031
032  /**
033   * Creates a new pretty printer that prints to a
034   * <code>PrintWriter</code>.  This way, we can print to destinations
035   * other than files (such as the console).
036   */
037  PrettyPrinter(PrintWriter pw) {
038    this.pw = pw;
039  }
040  
041  /**
042   * Prints the contents of the given family tree in a human-readable
043   * format.
044   */
045  public void dump(FamilyTree tree) {
046
047    // We want to print the contents of the family tree sorted by id
048    // number.  We'll use an instance of PersonSorter along with a
049    // TreeSet to sort the Persons.
050    SortedSet<Person> sortedTree = new TreeSet<Person>(new PersonSorter());
051    sortedTree.addAll(tree.getPeople());
052
053    // Print a banner
054    pw.println("Your Family Tree\n");
055
056    DateFormat df = DateFormat.getDateInstance(DateFormat.LONG);
057
058    // Iterate over the people in the sorted tree in order and print
059    // out a description of each person.
060    Iterator iter = sortedTree.iterator();
061    while (iter.hasNext()) {
062      Person person = (Person) iter.next();
063
064      pw.println("Person " + person.getId() + ": " +
065                 person.getFullName());
066
067      Date dob = person.getDateOfBirth();
068      if (dob != null) {
069        pw.print("  Born on " + df.format(dob));
070      }
071
072      Date dod = person.getDateOfDeath();
073      if (dod != null) {
074        pw.print(", died on " + df.format(dod));
075      }
076
077      if (dob != null || dod != null) {
078        // Only print a newline if a date was printed
079        pw.println("");
080      }
081
082      Person mother = person.getMother();
083      if (mother != null) {
084        pw.println("  Mother: " + mother.getFullName() + " (" +
085                   mother.getId() + ")");
086      }
087
088      Person father = person.getFather();
089      if (father != null) {
090        pw.println("  Father: " + father.getFullName() + " (" +
091                   father.getId() + ")");
092      }
093
094      Iterator marriages = person.getMarriages().iterator();
095      while (marriages.hasNext()) {
096        Marriage marriage = (Marriage) marriages.next();
097        Person spouse;
098
099        if(marriage.getWife().equals(person)) {
100          spouse = marriage.getHusband();
101
102        } else {
103          spouse = marriage.getWife();
104        }
105
106        pw.print("  Married " + spouse.getFullName());
107
108        Date date = marriage.getDate();
109        if(date != null) {
110          pw.print(" on " + df.format(date));
111        }
112
113        String location = marriage.getLocation();
114        if(location != null) {
115          pw.print(" in " + location);
116        }
117
118        pw.println("");
119      }
120
121      // Put a blank line between people for readability
122      pw.println("");
123
124    }
125
126    // Flush and close the PrintWriter for good measure
127    pw.flush();
128    pw.close();
129
130  }
131
132  /**
133   * Inner class used only by the dump method.  It is used to sort
134   * <code>Person</code>s by their id.
135   */
136  class PersonSorter implements Comparator<Person> {
137
138    /**
139     * Compares two <code>Person</code>s.  If the id of person one is less
140     * than the id of person two, then person one is less than person
141     * two.  If the id of person one is greater than the id of person
142     * two, then person one greater than person two.  If the id of
143     * person one is equal to the id of person two, then the two
144     * persons are equal.
145     */
146    public int compare(Person p1, Person p2) {
147      return p1.getId() - p2.getId();
148    }
149
150    /**
151     * Compares one <code>PersonSorter</code> to another.  All
152     * <code>PersonSorter</code>s are the same.
153     */
154    public boolean equals(Object o) {
155      if (o instanceof PersonSorter) {
156        return(true);
157
158      } else {
159        return(false);
160      }
161    }
162
163  }
164
165  /**
166   * Test program.  Create a simple family tree and print it to the
167   * console.
168   */
169  public static void main(String[] args) {
170    // Make some people
171    Person me = PersonMain.me();
172    Person mom = PersonMain.mom(me);
173    Person dad = PersonMain.dad(me);
174
175    me.setMother(mom);
176    me.setFather(dad);
177
178    Marriage marriage = new Marriage(dad, mom);
179    marriage.setLocation("Durham, NH");
180
181    try {
182      DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM);
183      marriage.setDate(df.parse("Jul 12, 1969"));
184
185    } catch (ParseException ex) {
186      System.out.println("** Malformed marriage date?");
187      System.exit(1);
188    }
189
190    mom.addMarriage(marriage);
191    dad.addMarriage(marriage);
192
193    // Create a family tree.  Add people in an interesting order.
194    FamilyTree tree = new FamilyTree();
195    tree.addPerson(dad);
196    tree.addPerson(mom);
197    tree.addPerson(me);
198
199    // Pretty print the tree to the console
200    PrintWriter out = new PrintWriter(System.out, true);
201    PrettyPrinter pretty = new PrettyPrinter(out);
202    pretty.dump(tree);
203  }
204
205}