1
14 package demo.layout.genealogy.iohandler;
15
16 import org.xml.sax.helpers.DefaultHandler;
17 import org.xml.sax.SAXException;
18 import org.xml.sax.Attributes;
19
20 import java.io.Writer;
21 import java.io.OutputStream;
22
23
33
34 public class GedcomOutputter extends DefaultHandler {
35 int level = 0;
36 boolean acceptCharacters = true;
37 GedcomLine line = new GedcomLine();
38 Writer writer;
39 OutputStream out;
40
41 public GedcomOutputter(OutputStream out) {
42 this.out = out;
43 }
44
45
48 public void startDocument () throws SAXException {
49 try {
51 if (out != null) {
52 writer = new AnselOutputStreamWriter(out);
53 } else {
54 writer = new AnselOutputStreamWriter(System.out);
55 }
56 } catch (Exception err) {
57 throw new SAXException("Failed to create output stream", err);
58 }
59 }
60
61
64
65 public void endDocument () throws SAXException
66 {
67 try {
68 if (line.level>=0) flushLine();
69 writer.write("0 TRLR\n");
70 writer.close();
71 if (out != null) {
72 out.close();
73 }
74 } catch (java.io.IOException err) {
75 throw new SAXException(err);
76 }
77 }
78
79
82
83 public void startElement (String pref, String ns, String name, Attributes attributes) throws SAXException
84 {
85 if (name.equals("GED")) return;
86
87 if (line.level>=0) flushLine();
88
89 line.level = level;
90 line.id = attributes.getValue("", "ID");
91 line.tag = name;
92 line.ref = attributes.getValue("", "REF");
93 line.text.setLength(0);
94
95 acceptCharacters = true;
96 level++;
97
98 }
99
100
103
104 public void endElement (String prefix, String ns, String name) throws SAXException
105 {
106 level--;
107 if (line.level>=0) flushLine();
108 acceptCharacters = false;
109 }
110
111
114
115 public void characters (char[] ch, int start, int length) throws SAXException
116 {
117 if (!acceptCharacters) {
118 for (int i=start; i<start+length; i++) {
119 if (!Character.isWhitespace(ch[i])) {
120 throw new SAXException("Character data not allowed after end tag");
121 }
122 }
123 } else {
124 line.text.append(ch, start, length);
125 }
126
127 }
128
129
132
133 public void ignorableWhitespace (char[] ch, int start, int length)
134 {}
135
136
137
140
141 public void processingInstruction (String target, String data)
142 {}
143
144
147
148 private void flushLine() throws SAXException {
149 String text = line.text.toString().trim();
150 int base = line.level;
151 int prevnl = 0;
152 while (true) {
154 int nl = text.indexOf('\n');
155 String textline = text;
156 if (nl>=0) {
157 line.text.setLength(nl);
158 textline = text.substring(0,nl);
159 } else {
160 textline = text;
161 }
162
163 while (true) {
165 int split = -1;
166 int len = line.tag.length() + 4 +
167 (line.id==null ? 0 : line.id.length()+3) +
168 (line.ref==null ? 0 : line.ref.length()+3) +
169 textline.length();
170 if (len > 255) { split = 80;
173 while (split>0 &&
174 (Character.isWhitespace(text.charAt(split)) ||
175 Character.isWhitespace(text.charAt(split+1)))) {
176 split--;
177 }
178 if (split==0) split = 80; line.text.setLength(split);
180 line.write();
181
182 line.level = base+1;
183 line.id = null;
184 line.tag = "CONC";
185 line.ref = null;
186 line.text.setLength(0);
187 textline = textline.substring(split);
188 line.text.append(textline);
189 }
190
191 line.write();
192 if (split<0) break;
193 }
194
195 if (nl > 0 && nl+1 < text.length()) {
197 line.level = base+1;
198 line.id = null;
199 line.tag = "CONT";
200 line.ref = null;
201 line.text.setLength(0);
202 text = text.substring(nl+1);
203 line.text.append(text);
204 } else {
205 break;
206 }
207 }
208 line.text.setLength(0);
209 line.level = -1;
210 }
211
212
215
216 private class GedcomLine {
217 public int level = -1;
218 public String id;
219 public String tag;
220 public String ref;
221 public StringBuffer text = new StringBuffer();
222
223
226
227 public void write() throws SAXException {
228 try {
229 writer.write(level + " ");
230 if (id!=null) {
231 writer.write('@' + id + "@ ");
232 }
233 writer.write(tag + ' ');
234 if (ref!=null) {
235 writer.write('@' + ref + "@ ");
236 }
237 writer.write(text.toString() + '\n');
238 } catch (java.io.IOException err) {
239 throw new SAXException(err);
240 }
241 }
242 }
243
244 }
245