1   /*
2    * Copyright 2001-2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
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          // logging for debugging jsut this method 
74  //        SimpleLog log = new SimpleLog("[testLooping:BeanWriter]");
75  //        log.setLevel(SimpleLog.LOG_LEVEL_TRACE);
76  //        writer.setLog(log);
77          
78  //        log = new SimpleLog("[testLooping:AbstractBeanWriter]");
79  //        log.setLevel(SimpleLog.LOG_LEVEL_TRACE);
80  //        writer.setAbstractBeanWriterLog(log);
81          
82  //        log = new SimpleLog("[testLooping]");
83  //        log.setLevel(SimpleLog.LOG_LEVEL_TRACE);
84          
85          writer.enablePrettyPrint();
86          writer.write( LoopBean.createNoLoopExampleBean() );    
87          
88          String xml ="<?xml version='1.0'?><LoopBean><name>Root</name><friend><name>level1</name>"
89                  + "<friend><name>level2</name><friend><name>level3</name><friend><name>level4</name>"
90                  + "<friend><name>level5</name></friend></friend></friend></friend></friend></LoopBean>";
91        
92          xmlAssertIsomorphicContent(
93                              "Test no loop",
94                              parseString(out.getBuffer().toString()),
95                              parseString(xml), 
96                              true);        
97          
98          out = new StringWriter();
99          out.write("<?xml version='1.0'?>");
100         writer = new BeanWriter(out);
101         writer.setWriteEmptyElements( true );
102         writer.write( LoopBean.createLoopExampleBean() );  
103         xml ="<?xml version='1.0'?><LoopBean><name>Root</name><friend><name>level1</name>"
104                 + "<friend><name>level2</name><friend><name>level3</name><friend><name>level4</name>"
105                 + "<friend><name>level5</name><friend idref='1'/></friend></friend></friend>"
106                 + "</friend></friend></LoopBean>";
107         xmlAssertIsomorphicContent(
108                             "Test loop",
109                             parseString(out.getBuffer().toString()),
110                             parseString(xml), 
111                             true);  
112         
113         // test not writing IDs
114 
115         
116 //        log.info("Writing LoopBean.createNoLoopExampleBean...");
117         
118         out = new StringWriter();
119         out.write("<?xml version='1.0'?>");
120         writer = new BeanWriter(out);
121         writer.setWriteEmptyElements( true );
122         writer.setWriteIDs(false);
123         writer.write( LoopBean.createNoLoopExampleBean() );
124         xml ="<?xml version='1.0'?><LoopBean><name>Root</name><friend><name>level1</name><friend>"
125             + "<name>level2</name><friend><name>level3</name><friend><name>level4</name><friend>"
126             + "<name>level5</name></friend></friend>"
127             + "</friend></friend></friend></LoopBean>";
128                 
129         xmlAssertIsomorphicContent(	
130                             "Test no loop, no ids",
131                             parseString(out.getBuffer().toString()),
132                             parseString(xml), 
133                             true); 
134         
135 //        log.info("Writing LoopBean.createIdOnlyLoopExampleBean...");
136         
137         out = new StringWriter();
138         out.write("<?xml version='1.0'?>");
139         writer = new BeanWriter(out);
140         writer.setWriteEmptyElements( true );
141         writer.setWriteIDs(false);
142         writer.write( LoopBean.createIdOnlyLoopExampleBean() );
143         xml = "<?xml version='1.0'?><LoopBean><name>Root</name><friend><name>level1</name>"
144             + "<friend><name>level2</name><friend><name>level3</name><friend><name>level4</name>"
145             + "<friend><name>level5</name><friend><name>Root</name></friend></friend>"
146             + "</friend></friend></friend></friend></LoopBean>";
147                 
148         xmlAssertIsomorphicContent(	
149                             "Test id only loop",
150                             parseString(out.getBuffer().toString()),
151                             parseString(xml), 
152                             true); 
153         
154         try {   
155 //            log.info("Writing LoopBean.createLoopExampleBean...")
156             out = new StringWriter();
157             out.write("<?xml version='1.0'?>");
158             writer = new BeanWriter(out);
159             writer.setWriteEmptyElements( true );
160             writer.setWriteIDs(false);
161             writer.write( LoopBean.createLoopExampleBean() );   
162             fail("CyclicReferenceException not thrown!");
163             
164         } catch (CyclicReferenceException e) {
165             // everything's fine
166         }
167     }
168     
169     public void testEscaping() throws Exception {
170         //XXX find a way to automatically verify test
171         ByteArrayOutputStream out = new ByteArrayOutputStream();
172         BeanWriter writer = new BeanWriter(out);
173         writer.setWriteEmptyElements( true );
174         writer.enablePrettyPrint(); 
175         XMLIntrospector introspector = new XMLIntrospector();
176         introspector.setAttributesForPrimitives(true);
177         writer.setXMLIntrospector(introspector);
178         writer.write(new LoopBean("Escape<LessThan"));
179         writer.write(new LoopBean("Escape>GreaterThan"));
180         writer.write(new LoopBean("Escape&amphersand"));
181         writer.write(new LoopBean("Escape'apostrophe"));
182         writer.write(new LoopBean("Escape\"Quote"));
183         
184         CustomerBean bean = new CustomerBean();
185         bean.setEmails( new String[] { 
186                                         "Escape<LessThan",
187                                         "Escape>GreaterThan",
188                                         "Escape&amphersand",
189                                         "Escape'apostrophe",
190                                         "Escape\"Quote"} );
191                                         
192         // The attribute value escaping needs test too..
193         bean.setName("Escape<LessThan");
194         AddressBean address = new AddressBean();
195         address.setCode("Escape>GreaterThan");
196         address.setCountry("Escape&amphersand");
197         address.setCity("Escape'apostrophe");
198         address.setStreet("Escape\"Quote");
199         bean.setAddress(address);
200         
201         writer.write(bean);
202         out.flush();
203         String result = "<?xml version='1.0'?><beans>" + out.toString() + "</beans>";
204         
205         // check for the elemant content..
206         assertTrue(result.indexOf("<email>Escape&lt;LessThan</email>") > -1 );
207         assertTrue(result.indexOf("<email>Escape&gt;GreaterThan</email>") > -1);
208         assertTrue(result.indexOf("<email>Escape&amp;amphersand</email>") != -1);
209         assertTrue(result.indexOf("<email>Escape'apostrophe</email>") != -1);
210         assertTrue(result.indexOf("<email>Escape\"Quote</email>") != -1);
211         // check for the attributes..
212         assertTrue(result.indexOf("name=\"Escape&lt;LessThan\"") > -1 );
213         assertTrue(result.indexOf("code=\"Escape&gt;GreaterThan\"") > -1);
214         assertTrue(result.indexOf("country=\"Escape&amp;amphersand\"") != -1);
215         assertTrue(result.indexOf("city=\"Escape&apos;apostrophe\"") != -1);
216         assertTrue(result.indexOf("street=\"Escape&quot;Quote\"") != -1);
217         
218         String xml="<?xml version='1.0'?><beans>  <LoopBean name='Escape&lt;LessThan'/>"
219             + "<LoopBean name='Escape&gt;GreaterThan'/><LoopBean name='Escape&amp;amphersand'/>"
220             + "<LoopBean name='Escape&apos;apostrophe'/><LoopBean name='Escape&quot;Quote'/>"
221             + "<CustomerBean name='Escape&lt;LessThan' time='' date='' bigDecimal='' "
222             + "bigInteger='' timestamp='' ID='' nickName=''>"
223             + "<projectMap/><projectNames/><emails><email>Escape&lt;LessThan</email>"
224             + "<email>Escape&gt;GreaterThan</email><email>Escape&amp;amphersand</email>"
225             + "<email>Escape'apostrophe</email><email>Escape\"Quote</email></emails>"
226             + "<locations/><projectURLs/>"
227             + "<address code='Escape&gt;GreaterThan' city='Escape&apos;apostrophe' "
228             + "country='Escape&amp;amphersand' street='Escape&quot;Quote'/>"
229             + "<numbers/></CustomerBean></beans>";
230             
231         xmlAssertIsomorphicContent(
232                             "Test escaping ",
233                             parseString(result),
234                             parseString(xml), 
235                             true);  
236     }
237     /***
238      * Testing valid endofline characters.
239      * It tests if there is a warning on System.err
240      */
241     public void testValidEndOfLine() throws Exception {
242         BeanWriter writer = new BeanWriter();
243         writer.setWriteEmptyElements(true);
244         
245         // store the system err
246         PrintStream errStream = System.err;
247         ByteArrayOutputStream warning = new ByteArrayOutputStream();
248         System.setErr(new PrintStream(warning));
249         
250         // force logging to go to System.err
251         writer.setLog( new SimpleLog( "test.betwixt" ) );
252         
253         
254         writer.setEndOfLine("X");
255         warning.flush();
256         assertTrue(warning.toString().startsWith("[WARN]"));
257         warning.reset();
258         writer.setEndOfLine("\tX");
259         warning.flush();
260         assertTrue(warning.toString().startsWith("[WARN]"));
261         warning.reset();
262         // now test a valid value..
263         writer.setEndOfLine(" ");
264         warning.flush();
265         assertTrue(warning.toString().equals(""));
266         warning.reset();
267         // set the System.err back again..
268         System.setErr(errStream);
269     }
270     
271     /*** Test simplest case for writing empty elements */
272     public void testSimpleWriteEmptyElements() throws Exception{
273         // use same bean for both tests
274         AddressBean bean = new AddressBean();
275         bean.setStreet("Pasture Lane");
276         bean.setCity("Bradford");
277         
278 //        SimpleLog log = new SimpleLog( "[SimpleEmpty:AbstractBeanWriter]" );
279 //        log.setLevel(SimpleLog.LOG_LEVEL_TRACE);
280         
281 //        SimpleLog baseLog = new SimpleLog( "[SimpleEmpty]" );
282 //        baseLog.setLevel(SimpleLog.LOG_LEVEL_TRACE);
283         
284         // test output when writing empty elements
285         StringWriter out = new StringWriter();
286         out.write("<?xml version='1.0'?>");
287         BeanWriter writer = new BeanWriter(out);
288         writer.setWriteEmptyElements(true);
289         writer.setWriteIDs(false);
290         writer.write(bean);
291 //        baseLog.debug("SIMPLE EMPTY");
292 //        baseLog.debug(out.getBuffer().toString());
293         String xml = "<?xml version='1.0'?><AddressBean><street>Pasture Lane</street><city>Bradford</city>"
294                     + "<code/><country/></AddressBean>";
295 //        baseLog.debug(xml);
296 
297         xmlAssertIsomorphicContent(parseString(out.getBuffer().toString()),parseString(xml), true);
298         
299         // test output when not writing empty elements
300         out = new StringWriter();
301         out.write("<?xml version='1.0'?>");
302         writer = new BeanWriter(out);
303         writer.setWriteEmptyElements(false);
304         writer.setWriteIDs(false);
305 //        writer.setAbstractBeanWriterLog(log);
306         writer.write(bean);
307         xml = "<?xml version='1.0'?><AddressBean><street>Pasture Lane</street><city>Bradford</city>"
308                     + "</AddressBean>";
309 //        baseLog.debug("SIMPLE NOT EMPTY");
310 //        baseLog.debug(out.getBuffer().toString());
311         xmlAssertIsomorphicContent(parseString(out.getBuffer().toString()),parseString(xml), true);
312     }
313     
314     /*** Test nested case for writing empty elements */
315     public void testNestedWriteEmptyElements() throws Exception{
316         
317         // write same bean both times
318         LoopBean root = new LoopBean("base");
319         LoopBean middle = new LoopBean(null);
320         root.setFriend(middle);
321         middle.setFriend(new LoopBean(null));
322         
323 //        SimpleLog baseLog = new SimpleLog( "[NestedEmpty]" );
324 //        baseLog.setLevel(SimpleLog.LOG_LEVEL_TRACE);
325     
326         // test output when writing empty elements
327         StringWriter out = new StringWriter();
328         out.write("<?xml version='1.0'?>");
329         BeanWriter writer = new BeanWriter(out);
330         writer.setWriteEmptyElements(true);
331         writer.setWriteIDs(false);
332         writer.write(root);
333 //        baseLog.debug("NESTED EMPTY");
334 //        baseLog.debug(out.getBuffer().toString());
335         String xml = "<?xml version='1.0'?><LoopBean><name>base</name><friend><name/><friend><name/></friend>"
336                     + "</friend></LoopBean>";
337         xmlAssertIsomorphicContent(parseString(out.getBuffer().toString()),parseString(xml), true);
338         
339         // test output when not writing empty elements
340         out = new StringWriter();
341         out.write("<?xml version='1.0'?>");
342         writer = new BeanWriter(out);
343         writer.setWriteEmptyElements(false);
344         writer.setWriteIDs(false);
345         writer.write(root);
346 //        baseLog.debug("NESTED NOT EMPTY");
347 //        baseLog.debug(out.getBuffer().toString());
348         xml = "<?xml version='1.0'?><LoopBean><name>base</name></LoopBean>";
349         xmlAssertIsomorphicContent(parseString(out.getBuffer().toString()),parseString(xml), true);
350         
351     }
352     
353     public void testArrayWrite() throws Exception {
354         ArrayBean bean = new ArrayBean("Rob");
355         bean.addHobby("Hacking open source software");
356         bean.addHobby("Playing cricket");
357         bean.addHobby("Watching rugby league");
358         bean.addHobby("Havin' it large");
359     
360         StringWriter out = new StringWriter();
361         out.write("<?xml version='1.0'?>");
362         BeanWriter writer = new BeanWriter(out);
363         writer.setWriteEmptyElements(true);
364         writer.setWriteIDs(false);
365         writer.write(bean);
366         
367         String xml = "<?xml version='1.0'?><ArrayBean><name>Rob</name><hobbies>"
368          + "<hobby>Hacking open source software</hobby>" 
369          + "<hobby>Playing cricket</hobby>" 
370          + "<hobby>Watching rugby league</hobby>" 
371          + "<hobby>Havin' it large</hobby>"
372          +"</hobbies></ArrayBean>";
373         xmlAssertIsomorphicContent(
374                             parseString(out.getBuffer().toString()),
375                             parseString(xml), 
376                             true);
377                             
378         String [] array = {"This", "That", "The Other"};
379         out = new StringWriter();
380         out.write("<?xml version='1.0'?>");
381         writer = new BeanWriter(out);
382         writer.setWriteEmptyElements(true);
383         writer.setWriteIDs(false);
384         writer.write(array);
385         
386         xml = "<?xml version='1.0'?><Array>"
387          + "<String>This</String>" 
388          + "<String>That</String>" 
389          + "<String>The Other</String>" 
390          +"</Array>";
391          
392         xmlAssertIsomorphicContent(
393                             parseString(out.getBuffer().toString()),
394                             parseString(xml), 
395                             true);
396     }
397     
398     
399     /*** Test nested case for writing empty elements */
400     public void testListedWriteEmptyElements() throws Exception {
401         ListOfNames names = new ListOfNames();
402         names.addName(new NameBean("Tom"));
403         names.addName(new NameBean("Dick"));
404         names.addName(new NameBean("Harry"));
405         names.addName(new NameBean(""));
406     
407         StringWriter out = new StringWriter();
408         out.write("<?xml version='1.0'?>");
409 
410         BeanWriter writer = new BeanWriter(out);
411         
412         //SimpleLog log = new SimpleLog("[testListedWriteEmptyElements:AbstractBeanWriter]");
413         //log.setLevel(SimpleLog.LOG_LEVEL_TRACE);
414         //writer.setAbstractBeanWriterLog(log);
415         
416         //log = new SimpleLog("[testListedWriteEmptyElements:XMLIntrospector]");
417         //log.setLevel(SimpleLog.LOG_LEVEL_TRACE);
418         //writer.getXMLIntrospector().setLog(log);
419         
420         //log = new SimpleLog("[testListedWriteEmptyElements:XMLIntrospectorHelper]");
421         //log.setLevel(SimpleLog.LOG_LEVEL_TRACE);
422         //XMLIntrospectorHelper.setLog(log);
423         
424         writer.setWriteEmptyElements(false);
425         writer.getXMLIntrospector().setWrapCollectionsInElement(false);
426         writer.setWriteIDs(false);
427         writer.write("Names", names);
428         
429         String xml = "<?xml version='1.0'?><Names>"
430          + "<name><name>Tom</name></name>" 
431          + "<name><name>Dick</name></name>" 
432          + "<name><name>Harry</name></name>" 
433          +"</Names>";
434          
435         xmlAssertIsomorphicContent(
436                             parseString(out.getBuffer().toString()),
437                             parseString(xml), 
438                             true);
439                             
440         out = new StringWriter();
441         out.write("<?xml version='1.0'?>");
442 
443         writer = new BeanWriter(out);
444         writer.setWriteEmptyElements(true);
445         writer.getXMLIntrospector().setWrapCollectionsInElement(false);
446         writer.setWriteIDs(false);
447         writer.write("Names", names);
448         
449         xml = "<?xml version='1.0'?><Names>"
450          + "<name><name>Tom</name></name>" 
451          + "<name><name>Dick</name></name>" 
452          + "<name><name>Harry</name></name>" 
453          + "<name><name/></name>"
454          +"</Names>";
455          
456         xmlAssertIsomorphicContent(
457                             parseString(out.getBuffer().toString()),
458                             parseString(xml), 
459                             true);
460                             
461         out = new StringWriter();
462         out.write("<?xml version='1.0'?>");
463 
464         writer = new BeanWriter(out);
465         writer.setWriteEmptyElements(true);
466         writer.getXMLIntrospector().setWrapCollectionsInElement(true);
467         writer.setWriteIDs(false);
468         writer.write("Names", names);
469         
470         xml = "<?xml version='1.0'?><Names><names>"
471          + "<name><name>Tom</name></name>" 
472          + "<name><name>Dick</name></name>" 
473          + "<name><name>Harry</name></name>" 
474          + "<name><name/></name></names>"
475          +"</Names>";
476          
477         xmlAssertIsomorphicContent(
478                             parseString(out.getBuffer().toString()),
479                             parseString(xml), 
480                             true);
481                             
482         out = new StringWriter();
483         out.write("<?xml version='1.0'?>");
484 
485         writer = new BeanWriter(out);
486         writer.setWriteEmptyElements(false);
487         writer.getXMLIntrospector().setWrapCollectionsInElement(true);
488         writer.setWriteIDs(false);
489         writer.write("Names", names);
490         
491         xml = "<?xml version='1.0'?><Names><names>"
492          + "<name><name>Tom</name></name>" 
493          + "<name><name>Dick</name></name>" 
494          + "<name><name>Harry</name></name>" 
495          + "</names>"
496          +"</Names>";
497          
498         xmlAssertIsomorphicContent(
499                             parseString(out.getBuffer().toString()),
500                             parseString(xml), 
501                             true);
502                             
503     }
504     
505     public void testWriteNameMapperStrategy() throws Exception {
506         ListOfNames names = new ListOfNames();
507         names.addName(new NameBean("Sid James"));
508         names.addName(new NameBean("Kenneth Williams"));
509         names.addName(new NameBean("Joan Simms"));
510         names.addName(new NameBean("Charles Hawtrey"));
511         
512         StringWriter out = new StringWriter();
513         out.write("<?xml version='1.0'?>");
514 
515         BeanWriter writer = new BeanWriter(out);
516         writer.setWriteEmptyElements(true);
517         writer.getXMLIntrospector().setWrapCollectionsInElement(true);
518         writer.setWriteIDs(false);
519         writer.write("CarryOn", names);
520         
521         String xml = "<?xml version='1.0'?><CarryOn><names>"
522          + "<name><name>Sid James</name></name>" 
523          + "<name><name>Kenneth Williams</name></name>" 
524          + "<name><name>Joan Simms</name></name>" 
525          + "<name><name>Charles Hawtrey</name></name>" 
526          + "</names>"
527          +"</CarryOn>";
528          
529         xmlAssertIsomorphicContent(
530                             parseString(out.getBuffer().toString()),
531                             parseString(xml), 
532                             true);
533                             
534         out = new StringWriter();
535         out.write("<?xml version='1.0'?>");
536 
537         writer = new BeanWriter(out);
538         writer.setWriteEmptyElements(true);
539         writer.getXMLIntrospector().setWrapCollectionsInElement(true);
540         writer.setWriteIDs(false);
541         writer.getXMLIntrospector().setElementNameMapper(new CapitalizeNameMapper());
542         writer.write("CarryOn", names);
543         
544         xml = "<?xml version='1.0'?><CarryOn><Names>"
545          + "<Name><Name>Sid James</Name></Name>" 
546          + "<Name><Name>Kenneth Williams</Name></Name>" 
547          + "<Name><Name>Joan Simms</Name></Name>" 
548          + "<Name><Name>Charles Hawtrey</Name></Name>" 
549          + "</Names>"
550          +"</CarryOn>";
551          
552         xmlAssertIsomorphicContent(
553                             parseString(out.getBuffer().toString()),
554                             parseString(xml), 
555                             true);
556                             
557         ArrayList things = new ArrayList();
558         things.add(new NameBean("Sugar"));
559         things.add(new NameBean("Spice"));
560         things.add(new NameBean("All Things Nice"));
561         
562         NoAdderBean bean = new NoAdderBean();
563         bean.setThings(things);
564         
565         out = new StringWriter();
566         out.write("<?xml version='1.0'?>");
567         writer = new BeanWriter(out);
568         writer.setWriteEmptyElements(true);
569         writer.getXMLIntrospector().setWrapCollectionsInElement(true);
570         writer.setWriteIDs(false);
571         writer.write(bean);
572         
573         xml = "<?xml version='1.0'?><NoAdderBean><things>"
574          + "<NameBean><name>Sugar</name></NameBean>" 
575          + "<NameBean><name>Spice</name></NameBean>" 
576          + "<NameBean><name>All Things Nice</name></NameBean>" 
577          + "</things>"
578          +"</NoAdderBean>";
579          
580         xmlAssertIsomorphicContent(
581                             parseString(out.getBuffer().toString()),
582                             parseString(xml), 
583                             true);
584         
585         out = new StringWriter();
586         out.write("<?xml version='1.0'?>");
587         writer = new BeanWriter(out);
588         writer.setWriteEmptyElements(true);
589         writer.getXMLIntrospector().setWrapCollectionsInElement(true);
590         writer.setWriteIDs(false);
591         writer.getXMLIntrospector().setElementNameMapper(new CapitalizeNameMapper());
592         writer.write(bean);
593         
594         xml = "<?xml version='1.0'?><NoAdderBean><Things>"
595          + "<NameBean><Name>Sugar</Name></NameBean>" 
596          + "<NameBean><Name>Spice</Name></NameBean>" 
597          + "<NameBean><Name>All Things Nice</Name></NameBean>" 
598          + "</Things>"
599          +"</NoAdderBean>";
600          
601         xmlAssertIsomorphicContent(
602                             parseString(out.getBuffer().toString()),
603                             parseString(xml), 
604                             true);
605                             
606         out = new StringWriter();
607         out.write("<?xml version='1.0'?>");
608         writer = new BeanWriter(out);
609         writer.setWriteEmptyElements(true);
610         writer.getXMLIntrospector().setWrapCollectionsInElement(true);
611         writer.setWriteIDs(false);
612         writer.getXMLIntrospector().setElementNameMapper(new HyphenatedNameMapper(false));
613         writer.write(bean);
614         
615         xml = "<?xml version='1.0'?><no-adder-bean><things>"
616          + "<name-bean><name>Sugar</name></name-bean>" 
617          + "<name-bean><name>Spice</name></name-bean>" 
618          + "<name-bean><name>All Things Nice</name></name-bean>" 
619          + "</things>"
620          +"</no-adder-bean>";
621          
622         xmlAssertIsomorphicContent(
623                             parseString(out.getBuffer().toString()),
624                             parseString(xml), 
625                             true);
626     }
627     
628     public void testBeanWriterWorksWithAnAddMethodAndACollection() throws Exception {
629 
630         BeanWriter bw = new BeanWriter();
631         try {
632             bw.write(new BeanWithAddMethod());
633         } catch (IllegalArgumentException e) {
634             fail("BeanWriter fails when a method is just called add(<type>) and there is also a collection");
635         }
636     }
637     
638     // used in testBeanWriterWorksWithAnAddMethodAndACollection
639     public static class BeanWithAddMethod {
640         private Collection x;
641         public void add(Object x)
642         {
643             // do nothing
644         }
645 
646         public Collection getX() {
647             return x;
648         }
649 
650         public void setX(Collection x) {
651             this.x = x;
652         }        
653     }
654 }
655