1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.betwixt;
18
19 import java.io.ByteArrayOutputStream;
20 import java.io.PrintStream;
21 import java.io.StringWriter;
22 import java.util.ArrayList;
23 import java.util.Collection;
24
25 import junit.framework.Test;
26 import junit.framework.TestSuite;
27 import junit.textui.TestRunner;
28
29 import org.apache.commons.betwixt.io.BeanWriter;
30 import org.apache.commons.betwixt.io.CyclicReferenceException;
31 import org.apache.commons.betwixt.strategy.CapitalizeNameMapper;
32 import org.apache.commons.betwixt.strategy.HyphenatedNameMapper;
33 import org.apache.commons.logging.impl.SimpleLog;
34
35 /*** Test harness for the BeanWriter
36 *
37 * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
38 * @author <a href="mailto:martin@mvdb.net">Martin van den Bemt</a>
39 * @version $Revision: 1.13 $
40 */
41 public class TestBeanWriter extends AbstractTestCase {
42
43 public static void main( String[] args ) {
44 TestRunner.run( suite() );
45 }
46
47 public static Test suite() {
48 return new TestSuite(TestBeanWriter.class);
49 }
50
51 public TestBeanWriter(String testName) {
52 super(testName);
53 }
54
55 public void testBeanWriter() throws Exception {
56 Object bean = createBean();
57
58 System.out.println( "Now trying pretty print" );
59
60 BeanWriter writer = new BeanWriter();
61 writer.setWriteEmptyElements(true);
62 writer.enablePrettyPrint();
63 writer.write( bean );
64 }
65
66
67 public void testLooping() throws Exception {
68 StringWriter out = new StringWriter();
69 out.write("<?xml version='1.0'?>");
70 BeanWriter writer = new BeanWriter(out);
71 writer.setWriteEmptyElements( true );
72
73
74
75
76
77
78
79
80
81
82
83
84
85 writer.enablePrettyPrint();
86 writer.write( LoopBean.createNoLoopExampleBean() );
87
88 String xml ="<?xml version='1.0'?><LoopBean id='1'><name>Root</name><friend id='2'><name>level1</name>"
89 + "<friend id='3'><name>level2</name><friend id='4'><name>level3</name><friend id='5'><name>level4</name>"
90 + "<friend id='6'><name>level5</name></friend></friend></friend></friend></friend></LoopBean>";
91
92 String xmlOut = out.getBuffer().toString();
93 xmlAssertIsomorphicContent(
94 "Test no loop",
95 parseString(xmlOut),
96 parseString(xml),
97 true);
98
99 out = new StringWriter();
100 out.write("<?xml version='1.0'?>");
101 writer = new BeanWriter(out);
102 writer.setWriteEmptyElements( true );
103 writer.write( LoopBean.createLoopExampleBean() );
104 xml ="<?xml version='1.0'?><LoopBean id='1'><name>Root</name><friend id='2'><name>level1</name>"
105 + "<friend id='3'><name>level2</name><friend id='4'><name>level3</name><friend id='5'><name>level4</name>"
106 + "<friend id='6'><name>level5</name><friend idref='1'/></friend></friend></friend>"
107 + "</friend></friend></LoopBean>";
108 xmlAssertIsomorphicContent(
109 "Test loop",
110 parseString(out.getBuffer().toString()),
111 parseString(xml),
112 true);
113
114
115
116
117
118
119 out = new StringWriter();
120 out.write("<?xml version='1.0'?>");
121 writer = new BeanWriter(out);
122 writer.setWriteEmptyElements( true );
123 writer.getBindingConfiguration().setMapIDs(false);
124 writer.write( LoopBean.createNoLoopExampleBean() );
125 xml ="<?xml version='1.0'?><LoopBean><name>Root</name><friend><name>level1</name><friend>"
126 + "<name>level2</name><friend><name>level3</name><friend><name>level4</name><friend>"
127 + "<name>level5</name></friend></friend>"
128 + "</friend></friend></friend></LoopBean>";
129
130 xmlAssertIsomorphicContent(
131 "Test no loop, no ids",
132 parseString(out.getBuffer().toString()),
133 parseString(xml),
134 true);
135
136
137
138 out = new StringWriter();
139 out.write("<?xml version='1.0'?>");
140 writer = new BeanWriter(out);
141 writer.setWriteEmptyElements( true );
142 writer.getBindingConfiguration().setMapIDs(false);
143 writer.write( LoopBean.createIdOnlyLoopExampleBean() );
144 xml = "<?xml version='1.0'?><LoopBean><name>Root</name><friend><name>level1</name>"
145 + "<friend><name>level2</name><friend><name>level3</name><friend><name>level4</name>"
146 + "<friend><name>level5</name><friend><name>Root</name></friend></friend>"
147 + "</friend></friend></friend></friend></LoopBean>";
148
149 xmlAssertIsomorphicContent(
150 "Test id only loop",
151 parseString(out.getBuffer().toString()),
152 parseString(xml),
153 true);
154
155 try {
156
157 out = new StringWriter();
158 out.write("<?xml version='1.0'?>");
159 writer = new BeanWriter(out);
160 writer.setWriteEmptyElements( true );
161 writer.getBindingConfiguration().setMapIDs(false);
162 writer.write( LoopBean.createLoopExampleBean() );
163 fail("CyclicReferenceException not thrown!");
164
165 } catch (CyclicReferenceException e) {
166
167 }
168 }
169
170 public void testEscaping() throws Exception {
171
172 ByteArrayOutputStream out = new ByteArrayOutputStream();
173 BeanWriter writer = new BeanWriter(out);
174 writer.setWriteEmptyElements( true );
175 writer.getBindingConfiguration().setMapIDs(false);
176 writer.enablePrettyPrint();
177 XMLIntrospector introspector = new XMLIntrospector();
178 introspector.getConfiguration().setAttributesForPrimitives(true);
179 writer.setXMLIntrospector(introspector);
180 writer.write(new LoopBean("Escape<LessThan"));
181 writer.write(new LoopBean("Escape>GreaterThan"));
182 writer.write(new LoopBean("Escape&hersand"));
183 writer.write(new LoopBean("Escape'apostrophe"));
184 writer.write(new LoopBean("Escape\"Quote"));
185
186 CustomerBean bean = new CustomerBean();
187 bean.setEmails( new String[] {
188 "Escape<LessThan",
189 "Escape>GreaterThan",
190 "Escape&hersand",
191 "Escape'apostrophe",
192 "Escape\"Quote"} );
193
194
195 bean.setName("Escape<LessThan");
196 AddressBean address = new AddressBean();
197 address.setCode("Escape>GreaterThan");
198 address.setCountry("Escape&hersand");
199 address.setCity("Escape'apostrophe");
200 address.setStreet("Escape\"Quote");
201 bean.setAddress(address);
202
203 writer.write(bean);
204 out.flush();
205 String result = "<?xml version='1.0'?><beans>" + out.toString() + "</beans>";
206
207
208 assertTrue(result.indexOf("<email>Escape<LessThan</email>") > -1 );
209 assertTrue(result.indexOf("<email>Escape>GreaterThan</email>") > -1);
210 assertTrue(result.indexOf("<email>Escape&amphersand</email>") != -1);
211 assertTrue(result.indexOf("<email>Escape'apostrophe</email>") != -1);
212 assertTrue(result.indexOf("<email>Escape\"Quote</email>") != -1);
213
214 assertTrue(result.indexOf("name=\"Escape<LessThan\"") > -1 );
215 assertTrue(result.indexOf("code=\"Escape>GreaterThan\"") > -1);
216 assertTrue(result.indexOf("country=\"Escape&amphersand\"") != -1);
217 assertTrue(result.indexOf("city=\"Escape'apostrophe\"") != -1);
218 assertTrue(result.indexOf("street=\"Escape"Quote\"") != -1);
219
220 String xml="<?xml version='1.0'?><beans> <LoopBean name='Escape<LessThan'/>"
221 + "<LoopBean name='Escape>GreaterThan'/><LoopBean name='Escape&amphersand'/>"
222 + "<LoopBean name='Escape'apostrophe'/><LoopBean name='Escape"Quote'/>"
223 + "<CustomerBean name='Escape<LessThan' time='' date='' bigDecimal='' "
224 + "bigInteger='' timestamp='' ID='' nickName=''>"
225 + "<projectMap/><projectNames/><emails><email>Escape<LessThan</email>"
226 + "<email>Escape>GreaterThan</email><email>Escape&amphersand</email>"
227 + "<email>Escape'apostrophe</email><email>Escape\"Quote</email></emails>"
228 + "<locations/><projectURLs/>"
229 + "<address code='Escape>GreaterThan' city='Escape'apostrophe' "
230 + "country='Escape&amphersand' street='Escape"Quote'/>"
231 + "<numbers/></CustomerBean></beans>";
232
233 xmlAssertIsomorphicContent(
234 "Test escaping ",
235 parseString(result),
236 parseString(xml),
237 true);
238 }
239 /***
240 * Testing valid endofline characters.
241 * It tests if there is a warning on System.err
242 */
243 public void testValidEndOfLine() throws Exception {
244 BeanWriter writer = new BeanWriter();
245 writer.setWriteEmptyElements(true);
246
247
248 PrintStream errStream = System.err;
249 ByteArrayOutputStream warning = new ByteArrayOutputStream();
250 System.setErr(new PrintStream(warning));
251
252
253 writer.setLog( new SimpleLog( "test.betwixt" ) );
254
255
256 writer.setEndOfLine("X");
257 warning.flush();
258 assertTrue(warning.toString().startsWith("[WARN]"));
259 warning.reset();
260 writer.setEndOfLine("\tX");
261 warning.flush();
262 assertTrue(warning.toString().startsWith("[WARN]"));
263 warning.reset();
264
265 writer.setEndOfLine(" ");
266 warning.flush();
267 assertTrue(warning.toString().equals(""));
268 warning.reset();
269
270 System.setErr(errStream);
271 }
272
273 /*** Test simplest case for writing empty elements */
274 public void testSimpleWriteEmptyElements() throws Exception{
275
276 AddressBean bean = new AddressBean();
277 bean.setStreet("Pasture Lane");
278 bean.setCity("Bradford");
279
280
281
282
283
284
285
286
287 StringWriter out = new StringWriter();
288 out.write("<?xml version='1.0'?>");
289 BeanWriter writer = new BeanWriter(out);
290 writer.setWriteEmptyElements(true);
291 writer.getBindingConfiguration().setMapIDs(false);
292 writer.write(bean);
293
294
295 String xml = "<?xml version='1.0'?><AddressBean><street>Pasture Lane</street><city>Bradford</city>"
296 + "<code/><country/></AddressBean>";
297
298
299 xmlAssertIsomorphicContent(parseString(out.getBuffer().toString()),parseString(xml), true);
300
301
302 out = new StringWriter();
303 out.write("<?xml version='1.0'?>");
304 writer = new BeanWriter(out);
305 writer.setWriteEmptyElements(false);
306 writer.getBindingConfiguration().setMapIDs(false);
307
308 writer.write(bean);
309 xml = "<?xml version='1.0'?><AddressBean><street>Pasture Lane</street><city>Bradford</city>"
310 + "</AddressBean>";
311
312
313 xmlAssertIsomorphicContent(parseString(out.getBuffer().toString()),parseString(xml), true);
314 }
315
316 /*** Test nested case for writing empty elements */
317 public void testNestedWriteEmptyElements() throws Exception{
318
319
320 LoopBean root = new LoopBean("base");
321 LoopBean middle = new LoopBean(null);
322 root.setFriend(middle);
323 middle.setFriend(new LoopBean(null));
324
325
326
327
328
329 StringWriter out = new StringWriter();
330 out.write("<?xml version='1.0'?>");
331 BeanWriter writer = new BeanWriter(out);
332 writer.setWriteEmptyElements(true);
333 writer.getBindingConfiguration().setMapIDs(false);
334 writer.write(root);
335
336
337 String xml = "<?xml version='1.0'?><LoopBean><name>base</name><friend><name/><friend><name/></friend>"
338 + "</friend></LoopBean>";
339 xmlAssertIsomorphicContent(parseString(out.getBuffer().toString()),parseString(xml), true);
340
341
342 out = new StringWriter();
343 out.write("<?xml version='1.0'?>");
344 writer = new BeanWriter(out);
345 writer.setWriteEmptyElements(false);
346 writer.getBindingConfiguration().setMapIDs(false);
347 writer.write(root);
348
349
350 xml = "<?xml version='1.0'?><LoopBean><name>base</name></LoopBean>";
351 xmlAssertIsomorphicContent(parseString(out.getBuffer().toString()),parseString(xml), true);
352
353 }
354
355 public void testArrayWrite() throws Exception {
356 ArrayBean bean = new ArrayBean("Rob");
357 bean.addHobby("Hacking open source software");
358 bean.addHobby("Playing cricket");
359 bean.addHobby("Watching rugby league");
360 bean.addHobby("Havin' it large");
361
362 StringWriter out = new StringWriter();
363 out.write("<?xml version='1.0'?>");
364 BeanWriter writer = new BeanWriter(out);
365 writer.setWriteEmptyElements(true);
366 writer.getBindingConfiguration().setMapIDs(false);
367 writer.write(bean);
368
369 String xml = "<?xml version='1.0'?><ArrayBean><name>Rob</name><hobbies>"
370 + "<hobby>Hacking open source software</hobby>"
371 + "<hobby>Playing cricket</hobby>"
372 + "<hobby>Watching rugby league</hobby>"
373 + "<hobby>Havin' it large</hobby>"
374 +"</hobbies></ArrayBean>";
375 xmlAssertIsomorphicContent(
376 parseString(out.getBuffer().toString()),
377 parseString(xml),
378 true);
379
380 String [] array = {"This", "That", "The Other"};
381 out = new StringWriter();
382 out.write("<?xml version='1.0'?>");
383 writer = new BeanWriter(out);
384 writer.setWriteEmptyElements(true);
385 writer.getBindingConfiguration().setMapIDs(false);
386 writer.write(array);
387
388 xml = "<?xml version='1.0'?><Array>"
389 + "<String>This</String>"
390 + "<String>That</String>"
391 + "<String>The Other</String>"
392 +"</Array>";
393
394 xmlAssertIsomorphicContent(
395 parseString(out.getBuffer().toString()),
396 parseString(xml),
397 true);
398 }
399
400
401 /*** Test nested case for writing empty elements */
402 public void testListedWriteEmptyElements() throws Exception {
403 ListOfNames names = new ListOfNames();
404 names.addName(new NameBean("Tom"));
405 names.addName(new NameBean("Dick"));
406 names.addName(new NameBean("Harry"));
407 names.addName(new NameBean(""));
408
409 StringWriter out = new StringWriter();
410 out.write("<?xml version='1.0'?>");
411
412 BeanWriter writer = new BeanWriter(out);
413
414
415
416
417
418
419
420
421
422
423
424
425
426 writer.setWriteEmptyElements(false);
427 writer.getXMLIntrospector().getConfiguration().setWrapCollectionsInElement(false);
428 writer.getBindingConfiguration().setMapIDs(false);
429 writer.write("Names", names);
430
431 String xml = "<?xml version='1.0'?><Names>"
432 + "<name><name>Tom</name></name>"
433 + "<name><name>Dick</name></name>"
434 + "<name><name>Harry</name></name>"
435 +"</Names>";
436
437 xmlAssertIsomorphicContent(
438 parseString(out.getBuffer().toString()),
439 parseString(xml),
440 true);
441
442 out = new StringWriter();
443 out.write("<?xml version='1.0'?>");
444
445 writer = new BeanWriter(out);
446 writer.setWriteEmptyElements(true);
447 writer.getXMLIntrospector().getConfiguration().setWrapCollectionsInElement(false);
448 writer.getBindingConfiguration().setMapIDs(false);
449 writer.write("Names", names);
450
451 xml = "<?xml version='1.0'?><Names>"
452 + "<name><name>Tom</name></name>"
453 + "<name><name>Dick</name></name>"
454 + "<name><name>Harry</name></name>"
455 + "<name><name/></name>"
456 +"</Names>";
457
458 xmlAssertIsomorphicContent(
459 parseString(out.getBuffer().toString()),
460 parseString(xml),
461 true);
462
463 out = new StringWriter();
464 out.write("<?xml version='1.0'?>");
465
466 writer = new BeanWriter(out);
467 writer.setWriteEmptyElements(true);
468 writer.getXMLIntrospector().getConfiguration().setWrapCollectionsInElement(true);
469 writer.getBindingConfiguration().setMapIDs(false);
470 writer.write("Names", names);
471
472 xml = "<?xml version='1.0'?><Names><names>"
473 + "<name><name>Tom</name></name>"
474 + "<name><name>Dick</name></name>"
475 + "<name><name>Harry</name></name>"
476 + "<name><name/></name></names>"
477 +"</Names>";
478
479 xmlAssertIsomorphicContent(
480 parseString(out.getBuffer().toString()),
481 parseString(xml),
482 true);
483
484 out = new StringWriter();
485 out.write("<?xml version='1.0'?>");
486
487 writer = new BeanWriter(out);
488 writer.setWriteEmptyElements(false);
489 writer.getXMLIntrospector().getConfiguration().setWrapCollectionsInElement(true);
490 writer.getBindingConfiguration().setMapIDs(false);
491 writer.write("Names", names);
492
493 xml = "<?xml version='1.0'?><Names><names>"
494 + "<name><name>Tom</name></name>"
495 + "<name><name>Dick</name></name>"
496 + "<name><name>Harry</name></name>"
497 + "</names>"
498 +"</Names>";
499
500 xmlAssertIsomorphicContent(
501 parseString(out.getBuffer().toString()),
502 parseString(xml),
503 true);
504
505 }
506
507 public void testWriteNameMapperStrategy() throws Exception {
508 ListOfNames names = new ListOfNames();
509 names.addName(new NameBean("Sid James"));
510 names.addName(new NameBean("Kenneth Williams"));
511 names.addName(new NameBean("Joan Simms"));
512 names.addName(new NameBean("Charles Hawtrey"));
513
514 StringWriter out = new StringWriter();
515 out.write("<?xml version='1.0'?>");
516
517 BeanWriter writer = new BeanWriter(out);
518 writer.setWriteEmptyElements(true);
519 writer.getXMLIntrospector().getConfiguration().setWrapCollectionsInElement(true);
520 writer.getBindingConfiguration().setMapIDs(false);
521 writer.write("CarryOn", names);
522
523 String xml = "<?xml version='1.0'?><CarryOn><names>"
524 + "<name><name>Sid James</name></name>"
525 + "<name><name>Kenneth Williams</name></name>"
526 + "<name><name>Joan Simms</name></name>"
527 + "<name><name>Charles Hawtrey</name></name>"
528 + "</names>"
529 +"</CarryOn>";
530
531 xmlAssertIsomorphicContent(
532 parseString(out.getBuffer().toString()),
533 parseString(xml),
534 true);
535
536 out = new StringWriter();
537 out.write("<?xml version='1.0'?>");
538
539 writer = new BeanWriter(out);
540 writer.setWriteEmptyElements(true);
541 writer.getXMLIntrospector().getConfiguration().setWrapCollectionsInElement(true);
542 writer.getBindingConfiguration().setMapIDs(false);
543 writer.getXMLIntrospector().getConfiguration().setElementNameMapper(new CapitalizeNameMapper());
544 writer.write("CarryOn", names);
545
546 xml = "<?xml version='1.0'?><CarryOn><Names>"
547 + "<Name><Name>Sid James</Name></Name>"
548 + "<Name><Name>Kenneth Williams</Name></Name>"
549 + "<Name><Name>Joan Simms</Name></Name>"
550 + "<Name><Name>Charles Hawtrey</Name></Name>"
551 + "</Names>"
552 +"</CarryOn>";
553
554 xmlAssertIsomorphicContent(
555 parseString(out.getBuffer().toString()),
556 parseString(xml),
557 true);
558
559 ArrayList things = new ArrayList();
560 things.add(new NameBean("Sugar"));
561 things.add(new NameBean("Spice"));
562 things.add(new NameBean("All Things Nice"));
563
564 NoAdderBean bean = new NoAdderBean();
565 bean.setThings(things);
566
567 out = new StringWriter();
568 out.write("<?xml version='1.0'?>");
569 writer = new BeanWriter(out);
570 writer.setWriteEmptyElements(true);
571 writer.getXMLIntrospector().getConfiguration().setWrapCollectionsInElement(true);
572 writer.getBindingConfiguration().setMapIDs(false);
573 writer.write(bean);
574
575 xml = "<?xml version='1.0'?><NoAdderBean><things>"
576 + "<NameBean><name>Sugar</name></NameBean>"
577 + "<NameBean><name>Spice</name></NameBean>"
578 + "<NameBean><name>All Things Nice</name></NameBean>"
579 + "</things>"
580 +"</NoAdderBean>";
581
582 xmlAssertIsomorphicContent(
583 parseString(out.getBuffer().toString()),
584 parseString(xml),
585 true);
586
587 out = new StringWriter();
588 out.write("<?xml version='1.0'?>");
589 writer = new BeanWriter(out);
590 writer.setWriteEmptyElements(true);
591 writer.getXMLIntrospector().getConfiguration().setWrapCollectionsInElement(true);
592 writer.getBindingConfiguration().setMapIDs(false);
593 writer.getXMLIntrospector().getConfiguration().setElementNameMapper(new CapitalizeNameMapper());
594 writer.write(bean);
595
596 xml = "<?xml version='1.0'?><NoAdderBean><Things>"
597 + "<NameBean><Name>Sugar</Name></NameBean>"
598 + "<NameBean><Name>Spice</Name></NameBean>"
599 + "<NameBean><Name>All Things Nice</Name></NameBean>"
600 + "</Things>"
601 +"</NoAdderBean>";
602
603 xmlAssertIsomorphicContent(
604 parseString(out.getBuffer().toString()),
605 parseString(xml),
606 true);
607
608 out = new StringWriter();
609 out.write("<?xml version='1.0'?>");
610 writer = new BeanWriter(out);
611 writer.setWriteEmptyElements(true);
612 writer.getXMLIntrospector().getConfiguration().setWrapCollectionsInElement(true);
613 writer.getBindingConfiguration().setMapIDs(false);
614 writer.getXMLIntrospector().getConfiguration().setElementNameMapper(new HyphenatedNameMapper(false));
615 writer.write(bean);
616
617 xml = "<?xml version='1.0'?><no-adder-bean><things>"
618 + "<name-bean><name>Sugar</name></name-bean>"
619 + "<name-bean><name>Spice</name></name-bean>"
620 + "<name-bean><name>All Things Nice</name></name-bean>"
621 + "</things>"
622 +"</no-adder-bean>";
623
624 xmlAssertIsomorphicContent(
625 parseString(out.getBuffer().toString()),
626 parseString(xml),
627 true);
628 }
629
630 public void testBeanWriterWorksWithAnAddMethodAndACollection() throws Exception {
631
632 BeanWriter bw = new BeanWriter();
633 try {
634 bw.write(new BeanWithAddMethod());
635 } catch (IllegalArgumentException e) {
636 fail("BeanWriter fails when a method is just called add(<type>) and there is also a collection");
637 }
638 }
639
640
641 public static class BeanWithAddMethod {
642 private Collection x;
643 public void add(Object x)
644 {
645
646 }
647
648 public Collection getX() {
649 return x;
650 }
651
652 public void setX(Collection x) {
653 this.x = x;
654 }
655 }
656 }
657