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}