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 destination (for example, a
009 * file) in a text-based format that is meant to be parsed by a
010 * TextParser.  It is not necessarily human-readable.
011 *
012 * @see TextParser
013 *
014 * @author David Whitlock
015 */
016public class TextDumper implements Dumper {
017
018  private PrintWriter pw;      // Dumping destination
019
020  /**
021   * Creates a new text dumper that dumps to a file of a given name.
022   * If the file does not exist, it is created.
023   */
024  public TextDumper(String fileName) throws IOException {
025    this(new File(fileName));
026  }
027
028  /**
029   * Creates a new text dumper that dumps to a given file.
030   */
031  public TextDumper(File file) throws IOException {
032    this(new PrintWriter(new FileWriter(file), true));
033  }
034
035  /**
036   * Creates a new text dumper that prints to a
037   * <code>PrintWriter</code>.  This way, we can dump to destinations
038   * other than files.  
039   */
040  public TextDumper(PrintWriter pw) {
041    this.pw = pw;
042  }
043
044  /**
045   * Dumps the contents of a family tree to the desired desitination.
046   */
047  public void dump(FamilyTree tree) {
048    // A word about the encoding of the family tree.  Each data item
049    // (a person or a marriage) is preceeded by a header describing
050    // the type of data and its size.  For instance,
051    //          P 7
052    // encodes a Person whose data takes up 7 lines in the file (not
053    // including the header).
054    //
055    // Each attribute of a person is specified by an abbreviation of
056    // the attribute followed by a string representation of the value.
057    // For instance, a person's father is represented by 
058    //              f: 4 
059    // "f" for father and the father's id, 4.  
060    //
061    // Marriages are handled separately and are dumped to the file
062    // after all of the people.
063
064    // Keep track of all of the marriages we've encountered
065    Set<Marriage> marriages = new HashSet<Marriage>();
066
067    DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM);
068
069    // Examine every person in the family tree and dump their data to
070    // the destination PrintWriter.
071    Iterator iter = tree.getPeople().iterator();
072    while (iter.hasNext()) {
073      Person person = (Person) iter.next();
074
075      int lines = 0;   // How many lines in the encoding
076      StringBuffer data = new StringBuffer();
077
078      data.append("id: " + person.getId() + "\n");
079      lines++;
080
081      data.append("g: " + person.getGender() + "\n");
082      lines++;
083
084      String firstName = person.getFirstName();
085      if (firstName != null) {
086        data.append("fn: " + firstName + "\n");
087        lines++;
088      }
089
090      String middleName = person.getMiddleName();
091      if (middleName != null) {
092        data.append("mn: " + middleName + "\n");
093        lines++;
094      }
095
096      String lastName = person.getLastName();
097      if (lastName != null) {
098        data.append("ln: " + lastName + "\n");
099        lines++;
100      }
101
102      Person mother = person.getMother();
103      if (mother != null) {
104        data.append("m: " + mother.getId() + "\n");
105        lines++;
106      }
107
108      Person father = person.getFather();
109      if (father != null) {
110        data.append("f: " + father.getId() + "\n");
111        lines++;
112      }
113
114      Date dob = person.getDateOfBirth();
115      if (dob != null) {
116        data.append("dob: " + df.format(dob) + "\n");
117        lines++;
118      }
119
120      Date dod = person.getDateOfDeath();
121      if (dod != null) {
122        data.append("dod: " + df.format(dod) + "\n");
123        lines++;
124      }
125
126      // Make note of all marriages
127      marriages.addAll(person.getMarriages());
128
129      // Write the header followed by the data to the destination
130      pw.println("P " + lines);
131      pw.print(data.toString());
132    }
133
134    // Now we have to dump the marriages
135    iter = marriages.iterator();
136    while (iter.hasNext()) {
137      Marriage marriage = (Marriage) iter.next();
138      
139      int lines = 0;
140      StringBuffer data = new StringBuffer();
141
142      // Write the id's of the husband and wife
143      data.append(marriage.getHusband().getId() + " " +
144                  marriage.getWife().getId() + "\n");
145      lines++;
146
147      String location = marriage.getLocation();
148      if (location != null) {
149        data.append("l: " + location + "\n");
150        lines++;
151      }
152
153      Date date = marriage.getDate();
154      if (date != null) {
155        data.append("d: " + df.format(date) + "\n");
156        lines++;
157      }
158
159      // Write the header followed by the data to the destination
160      pw.println("M " + lines);
161      pw.print(data.toString());
162    }
163
164    // Flush and close the PrintWriter
165    pw.flush();
166    pw.close();
167  }
168
169  /**
170   * Test program.  Create a simple family tree and dump it to the
171   * file specified by the first argument.
172   */
173  public static void main(String[] args) {
174    if (args.length == 0) {
175      System.err.println("** No file specified");
176      System.exit(1);
177    }
178
179    String fileName = args[0];
180
181    // Make some people
182    Person me = PersonMain.me();
183    Person mom = PersonMain.mom(me);
184    Person dad = PersonMain.dad(me);
185
186    me.setMother(mom);
187    me.setFather(dad);
188
189    Marriage marriage = new Marriage(dad, mom);
190    marriage.setLocation("Durham, NH");
191
192    try {
193      DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM);
194      marriage.setDate(df.parse("Jul 12, 1969"));
195
196    } catch (ParseException ex) {
197      System.out.println("** Malformed marriage date?");
198      System.exit(1);
199    }
200
201    mom.addMarriage(marriage);
202    dad.addMarriage(marriage);
203
204    // Create a family tree.  Add people in an interesting order.
205    FamilyTree tree = new FamilyTree();
206    tree.addPerson(dad);
207    tree.addPerson(mom);
208    tree.addPerson(me);
209
210    // Dump the family tree to the file
211    try {
212      TextDumper dumper = new TextDumper(fileName);
213      dumper.dump(tree);
214
215    } catch (IOException ex) {
216      System.err.println("** IOException while dealing with " +
217                         fileName);
218      System.exit(1);
219    }
220
221  }
222
223}