1
2 package org.catacomb.serial.xml;
3
4 import org.catacomb.interlish.structure.Element;
5 import org.catacomb.interlish.structure.PreSaveValidable;
6 import org.catacomb.interlish.structure.StateQueryable;
7 import org.catacomb.interlish.structure.Stateless;
8
9 import java.lang.reflect.Field;
10 import java.lang.reflect.Modifier;
11 import java.util.List;
12
13
14 public class XMLWriter {
15
16 boolean conciseTags;
17 boolean quoteStrings;
18
19
20 public XMLWriter() {
21 conciseTags = false;
22 quoteStrings = true;
23 }
24
25
26 public void setConciseTags(boolean b) {
27 conciseTags = b;
28 }
29
30
31 public void setQuoteStrings(boolean b) {
32 quoteStrings = b;
33 }
34
35
36 public static void err(String s) {
37 System.out.println(s);
38 }
39
40
41 public static XMLWriter newInstance() {
42 return new XMLWriter();
43 }
44
45
46 public static String serialize(Object ob) {
47 return getSerialization(ob);
48 }
49
50
51 public static String getSerialization(Object ob) {
52 return newInstance().writeObject(ob);
53 }
54
55
56
57 public String writeObject(Object obj) {
58 StringBuffer sb = new StringBuffer();
59 appendObject(sb, "", null, obj);
60 return sb.toString();
61 }
62
63
64 public void appendObject(StringBuffer sbv, String psk, String knownAs, Object ob) {
65
66 boolean write = true;
67
68 if (ob instanceof String) {
69 sbv.append(psk);
70 sbv.append("<String>");
71 sbv.append(ob);
72 sbv.append("</String>\n");
73 return;
74 }
75
76
77 if (ob instanceof Stateless) {
78 write = false;
79 } else if (ob instanceof StateQueryable) {
80 if (((StateQueryable)ob).hasStateInformation()) {
81
82 } else {
83 write = false;
84 }
85 }
86
87
88 if (!write) {
89
90 return;
91 }
92
93
94 if (ob instanceof Element) {
95 XMLElementWriter.appendElement(sbv, psk, (Element)ob);
96 return;
97 }
98
99
100
101 if (ob instanceof PreSaveValidable) {
102 ((PreSaveValidable)ob).preSaveValidate();
103 }
104
105 String tag = "error";
106 if (knownAs != null) {
107 tag = knownAs;
108 } else {
109 tag = ob.getClass().getName();
110
111 if (conciseTags) {
112 int ilast = tag.lastIndexOf(".");
113 if (ilast >= 0) {
114 tag = tag.substring(ilast + 1, tag.length());
115 }
116 }
117 }
118
119 sbv.append(psk);
120 sbv.append("<" + tag + ">\n");
121
122
123
124
125
126
127
128
129 String sk = psk + " ";
130
131 Field[] flds = ob.getClass().getFields();
132
133 for (int i = 0; i < flds.length; i++) {
134 String fieldName = flds[i].getName();
135 Object ret = null;
136 try {
137 ret = flds[i].get(ob);
138 } catch (Exception e) {
139 err("WARNING - failed to get field " + fieldName + " in " + ob);
140 }
141 if (Modifier.isFinal(flds[i].getModifiers()))
142 ret = null;
143
144 if (ret instanceof Double) {
145 appendNV(sbv, sk, fieldName, ((Double)ret).doubleValue());
146
147 } else if (ret instanceof Integer) {
148 appendNV(sbv, sk, fieldName, ((Integer)ret).intValue());
149
150 } else if (ret instanceof Boolean) {
151 appendNV(sbv, sk, fieldName, ((Boolean)ret).booleanValue());
152
153 } else if (ret instanceof String) {
154 appendNV(sbv, sk, fieldName, (String)ret);
155
156 } else if (ret instanceof double[]) {
157 appendNV(sbv, sk, fieldName, (double[])ret);
158
159 } else if (ret instanceof int[]) {
160 appendNV(sbv, sk, fieldName, (int[])ret);
161
162 } else if (ret instanceof boolean[]) {
163 appendNV(sbv, sk, fieldName, (boolean[])ret);
164
165 } else if (ret instanceof String[]) {
166 appendNV(sbv, sk, fieldName, (String[])ret);
167
168 } else if (ret instanceof double[][]) {
169 appendNV(sbv, sk, fieldName, (double[][])ret);
170
171 } else if (ret instanceof int[][]) {
172 appendNV(sbv, sk, fieldName, (int[][])ret);
173
174 } else if (ret != null) {
175 appendObject(sbv, sk, fieldName, ret);
176
177 }
178 }
179
180
181 if (ob instanceof List) {
182 for (Object listobj : (List)ob) {
183 appendObject(sbv, psk + " ", null, listobj);
184 }
185 }
186
187
188 sbv.append(psk);
189 sbv.append("</" + tag + ">\n");
190 }
191
192
193
194 private void appendNV(StringBuffer sbv, String sk, String name, String value) {
195 sbv.append(sk + "<" + name + ">");
196 appendString(sbv, value);
197 sbv.append("</" + name + ">\n");
198 }
199
200
201 private void appendNV(StringBuffer sbv, String sk, String name, boolean value) {
202 sbv.append(sk + "<" + name + ">");
203 sbv.append(value ? "1" : "0");
204 sbv.append("</" + name + ">\n");
205 }
206
207
208
209 private void appendNV(StringBuffer sbv, String sk, String name, int value) {
210 sbv.append(sk + "<" + name + ">");
211 sbv.append("" + value);
212 sbv.append("</" + name + ">\n");
213 }
214
215
216 private void appendNV(StringBuffer sbv, String sk, String name, double value) {
217 sbv.append(sk + "<" + name + ">");
218 sbv.append("" + value);
219 sbv.append("</" + name + ">\n");
220 }
221
222
223
224 private void appendNV(StringBuffer sbv, String sk, String name, String[] value) {
225 sbv.append(sk + "<" + name + ">\n");
226
227 for (int i = 0; i < value.length; i++) {
228 sbv.append(sk);
229 sbv.append(" ");
230 appendString(sbv, (value[i] != null ? value[i] : ""));
231 sbv.append("\n");
232 }
233 sbv.append(sk + "</" + name + ">\n");
234 }
235
236
237 private void appendNV(StringBuffer sbv, String sk, String name, int[] value) {
238 sbv.append(sk + "<" + name + ">");
239 for (int i = 0; i < value.length; i++) {
240 if (i % 16 == 0)
241 sbv.append("\n" + sk + " ");
242 sbv.append(" " + value[i] + " ");
243 }
244 sbv.append("\n");
245 sbv.append(sk + "</" + name + ">\n");
246 }
247
248
249 private void appendNV(StringBuffer sbv, String sk, String name, boolean[] value) {
250 sbv.append(sk + "<" + name + ">\n" + sk + " ");
251 for (int i = 0; i < value.length; i++) {
252 sbv.append(" " + (value[i] ? 1 : 0) + " ");
253 }
254 sbv.append("\n");
255 sbv.append(sk + "</" + name + ">\n");
256 }
257
258
259 private void appendNV(StringBuffer sbv, String sk, String name, double[] value) {
260 sbv.append(sk + "<" + name + ">");
261 for (int i = 0; i < value.length; i++) {
262 if (i % 4 == 0)
263 sbv.append("\n" + sk + " ");
264 sbv.append(" " + value[i] + " ");
265 }
266 sbv.append("\n");
267 sbv.append(sk + "</" + name + ">\n");
268 }
269
270
271
272 private void appendNV(StringBuffer sbv, String sk, String name, int[][] value) {
273 sbv.append(sk + "<" + name + ">\n");
274 for (int i = 0; i < value.length; i++) {
275 sbv.append(sk);
276 sbv.append(" <row>");
277 int[] ii = value[i];
278 for (int k = 0; k < ii.length; k++) {
279 if (k % 16 == 0)
280 sbv.append("\n " + sk + " ");
281 sbv.append(" " + ii[k] + " ");
282 }
283 sbv.append("\n");
284 sbv.append(sk);
285 sbv.append(" ");
286 sbv.append("</row>\n");
287 }
288 sbv.append(sk + "</" + name + ">\n");
289 }
290
291
292
293 private void appendNV(StringBuffer sbv, String sk, String name, double[][] value) {
294 sbv.append(sk + "<" + name + ">\n");
295 for (int i = 0; i < value.length; i++) {
296 sbv.append(sk);
297 sbv.append(" <row>");
298 double[] ii = value[i];
299 for (int k = 0; k < ii.length; k++) {
300 if (k % 4 == 0)
301 sbv.append("\n " + sk + " ");
302 sbv.append(" " + ii[k] + " ");
303 }
304 sbv.append("\n");
305 sbv.append(sk);
306 sbv.append(" ");
307 sbv.append("</row>\n");
308 }
309 sbv.append(sk + "</" + name + ">\n");
310
311 }
312
313
314
315 private void appendString(StringBuffer sbv, String sssin) {
316 String sss = sssin;
317 if (sss == null) {
318 if (quoteStrings) {
319 sbv.append("\"null\"");
320 } else {
321 sbv.append("null");
322 }
323
324 } else {
325 sss = StringEncoder.xmlEscape(sss);
326
327 if (!quoteStrings) {
328 sbv.append(sss);
329 } else {
330 sbv.append("\"");
331 sbv.append(sss);
332 sbv.append("\"");
333 }
334 }
335 }
336
337
338 }