001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.commons.betwixt;
019:
020: import java.io.ByteArrayOutputStream;
021: import java.io.PrintStream;
022: import java.io.StringWriter;
023: import java.util.ArrayList;
024: import java.util.Collection;
025:
026: import junit.framework.Test;
027: import junit.framework.TestSuite;
028: import junit.textui.TestRunner;
029:
030: import org.apache.commons.betwixt.io.BeanWriter;
031: import org.apache.commons.betwixt.io.CyclicReferenceException;
032: import org.apache.commons.betwixt.strategy.CapitalizeNameMapper;
033: import org.apache.commons.betwixt.strategy.HyphenatedNameMapper;
034: import org.apache.commons.logging.impl.SimpleLog;
035:
036: /** Test harness for the BeanWriter
037: *
038: * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
039: * @author <a href="mailto:martin@mvdb.net">Martin van den Bemt</a>
040: * @version $Revision: 438373 $
041: */
042: public class TestBeanWriter extends AbstractTestCase {
043:
044: public static void main(String[] args) {
045: TestRunner.run(suite());
046: }
047:
048: public static Test suite() {
049: return new TestSuite(TestBeanWriter.class);
050: }
051:
052: public TestBeanWriter(String testName) {
053: super (testName);
054: }
055:
056: public void testBeanWriter() throws Exception {
057: Object bean = createBean();
058:
059: System.out.println("Now trying pretty print");
060:
061: BeanWriter writer = new BeanWriter();
062: writer.setWriteEmptyElements(true);
063: writer.setEndOfLine("\n");
064: writer.enablePrettyPrint();
065: writer.write(bean);
066: }
067:
068: public void testLooping() throws Exception {
069: StringWriter out = new StringWriter();
070: out.write("<?xml version='1.0'?>");
071: BeanWriter writer = new BeanWriter(out);
072: writer.setWriteEmptyElements(true);
073:
074: // logging for debugging jsut this method
075: writer.setEndOfLine("\n");
076: writer.enablePrettyPrint();
077: writer.write(LoopBean.createNoLoopExampleBean());
078:
079: String xml = "<?xml version='1.0'?><LoopBean id='1'><name>Root</name><friend id='2'><name>level1</name>"
080: + "<friend id='3'><name>level2</name><friend id='4'><name>level3</name><friend id='5'><name>level4</name>"
081: + "<friend id='6'><name>level5</name></friend></friend></friend></friend></friend></LoopBean>";
082:
083: String xmlOut = out.getBuffer().toString();
084: xmlAssertIsomorphicContent("Test no loop", parseString(xmlOut),
085: parseString(xml), true);
086:
087: out = new StringWriter();
088: out.write("<?xml version='1.0'?>");
089: writer = new BeanWriter(out);
090: writer.setWriteEmptyElements(true);
091: writer.write(LoopBean.createLoopExampleBean());
092: xml = "<?xml version='1.0'?><LoopBean id='1'><name>Root</name><friend id='2'><name>level1</name>"
093: + "<friend id='3'><name>level2</name><friend id='4'><name>level3</name><friend id='5'><name>level4</name>"
094: + "<friend id='6'><name>level5</name><friend idref='1'/></friend></friend></friend>"
095: + "</friend></friend></LoopBean>";
096: xmlAssertIsomorphicContent("Test loop", parseString(out
097: .getBuffer().toString()), parseString(xml), true);
098:
099: // test not writing IDs
100:
101: // log.info("Writing LoopBean.createNoLoopExampleBean...");
102:
103: out = new StringWriter();
104: out.write("<?xml version='1.0'?>");
105: writer = new BeanWriter(out);
106: writer.setWriteEmptyElements(true);
107: writer.getBindingConfiguration().setMapIDs(false);
108: writer.write(LoopBean.createNoLoopExampleBean());
109: xml = "<?xml version='1.0'?><LoopBean><name>Root</name><friend><name>level1</name><friend>"
110: + "<name>level2</name><friend><name>level3</name><friend><name>level4</name><friend>"
111: + "<name>level5</name></friend></friend>"
112: + "</friend></friend></friend></LoopBean>";
113:
114: xmlAssertIsomorphicContent("Test no loop, no ids",
115: parseString(out.getBuffer().toString()),
116: parseString(xml), true);
117:
118: // log.info("Writing LoopBean.createIdOnlyLoopExampleBean...");
119:
120: out = new StringWriter();
121: out.write("<?xml version='1.0'?>");
122: writer = new BeanWriter(out);
123: writer.setWriteEmptyElements(true);
124: writer.getBindingConfiguration().setMapIDs(false);
125: writer.write(LoopBean.createIdOnlyLoopExampleBean());
126: xml = "<?xml version='1.0'?><LoopBean><name>Root</name><friend><name>level1</name>"
127: + "<friend><name>level2</name><friend><name>level3</name><friend><name>level4</name>"
128: + "<friend><name>level5</name><friend><name>Root</name></friend></friend>"
129: + "</friend></friend></friend></friend></LoopBean>";
130:
131: xmlAssertIsomorphicContent("Test id only loop", parseString(out
132: .getBuffer().toString()), parseString(xml), true);
133:
134: try {
135: // log.info("Writing LoopBean.createLoopExampleBean...")
136: out = new StringWriter();
137: out.write("<?xml version='1.0'?>");
138: writer = new BeanWriter(out);
139: writer.setWriteEmptyElements(true);
140: writer.getBindingConfiguration().setMapIDs(false);
141: writer.write(LoopBean.createLoopExampleBean());
142: fail("CyclicReferenceException not thrown!");
143:
144: } catch (CyclicReferenceException e) {
145: // everything's fine
146: }
147: }
148:
149: public void testEscaping() throws Exception {
150: //XXX find a way to automatically verify test
151: ByteArrayOutputStream out = new ByteArrayOutputStream();
152: BeanWriter writer = new BeanWriter(out);
153: writer.setWriteEmptyElements(true);
154: writer.getBindingConfiguration().setMapIDs(false);
155: writer.setEndOfLine("\n");
156: writer.enablePrettyPrint();
157: XMLIntrospector introspector = new XMLIntrospector();
158: introspector.getConfiguration()
159: .setAttributesForPrimitives(true);
160: writer.setXMLIntrospector(introspector);
161: writer.write(new LoopBean("Escape<LessThan"));
162: writer.write(new LoopBean("Escape>GreaterThan"));
163: writer.write(new LoopBean("Escape&hersand"));
164: writer.write(new LoopBean("Escape'apostrophe"));
165: writer.write(new LoopBean("Escape\"Quote"));
166:
167: CustomerBean bean = new CustomerBean();
168: bean.setEmails(new String[] { "Escape<LessThan",
169: "Escape>GreaterThan", "Escape&hersand",
170: "Escape'apostrophe", "Escape\"Quote" });
171:
172: // The attribute value escaping needs test too..
173: bean.setName("Escape<LessThan");
174: AddressBean address = new AddressBean();
175: address.setCode("Escape>GreaterThan");
176: address.setCountry("Escape&hersand");
177: address.setCity("Escape'apostrophe");
178: address.setStreet("Escape\"Quote");
179: bean.setAddress(address);
180:
181: writer.write(bean);
182: out.flush();
183: String result = "<?xml version='1.0'?><beans>" + out.toString()
184: + "</beans>";
185:
186: // check for the elemant content..
187: assertTrue(result.indexOf("<email>Escape<LessThan</email>") > -1);
188: assertTrue(result
189: .indexOf("<email>Escape>GreaterThan</email>") > -1);
190: assertTrue(result
191: .indexOf("<email>Escape&amphersand</email>") != -1);
192: assertTrue(result.indexOf("<email>Escape'apostrophe</email>") != -1);
193: assertTrue(result.indexOf("<email>Escape\"Quote</email>") != -1);
194: // check for the attributes..
195: assertTrue(result.indexOf("name=\"Escape<LessThan\"") > -1);
196: assertTrue(result.indexOf("code=\"Escape>GreaterThan\"") > -1);
197: assertTrue(result.indexOf("country=\"Escape&amphersand\"") != -1);
198: assertTrue(result.indexOf("city=\"Escape'apostrophe\"") != -1);
199: assertTrue(result.indexOf("street=\"Escape"Quote\"") != -1);
200:
201: String xml = "<?xml version='1.0'?><beans> <LoopBean name='Escape<LessThan'/>"
202: + "<LoopBean name='Escape>GreaterThan'/><LoopBean name='Escape&amphersand'/>"
203: + "<LoopBean name='Escape'apostrophe'/><LoopBean name='Escape"Quote'/>"
204: + "<CustomerBean name='Escape<LessThan' >"
205: + "<projectMap/><projectNames/><emails><email>Escape<LessThan</email>"
206: + "<email>Escape>GreaterThan</email><email>Escape&amphersand</email>"
207: + "<email>Escape'apostrophe</email><email>Escape\"Quote</email></emails>"
208: + "<locations/><projectURLs/>"
209: + "<address code='Escape>GreaterThan' city='Escape'apostrophe' "
210: + "country='Escape&amphersand' street='Escape"Quote'/>"
211: + "<numbers/></CustomerBean></beans>";
212:
213: xmlAssertIsomorphicContent("Test escaping ",
214: parseString(result), parseString(xml), true);
215: }
216:
217: /**
218: * Testing valid endofline characters.
219: * It tests if there is a warning on System.err
220: */
221: public void testValidEndOfLine() throws Exception {
222: BeanWriter writer = new BeanWriter();
223: writer.setWriteEmptyElements(true);
224:
225: // store the system err
226: PrintStream errStream = System.err;
227: ByteArrayOutputStream warning = new ByteArrayOutputStream();
228: System.setErr(new PrintStream(warning));
229:
230: // force logging to go to System.err
231: writer.setLog(new SimpleLog("test.betwixt"));
232:
233: writer.setEndOfLine("X");
234: warning.flush();
235: assertTrue(warning.toString().startsWith("[WARN]"));
236: warning.reset();
237: writer.setEndOfLine("\tX");
238: warning.flush();
239: assertTrue(warning.toString().startsWith("[WARN]"));
240: warning.reset();
241: // now test a valid value..
242: writer.setEndOfLine(" ");
243: warning.flush();
244: assertTrue(warning.toString().equals(""));
245: warning.reset();
246: // set the System.err back again..
247: System.setErr(errStream);
248: }
249:
250: /** Test simplest case for writing empty elements */
251: public void testSimpleWriteEmptyElements() throws Exception {
252: // use same bean for both tests
253: AddressBean bean = new AddressBean();
254: bean.setStreet("Pasture Lane");
255: bean.setCity("Bradford");
256:
257: // SimpleLog log = new SimpleLog( "[SimpleEmpty:AbstractBeanWriter]" );
258: // log.setLevel(SimpleLog.LOG_LEVEL_TRACE);
259:
260: // SimpleLog baseLog = new SimpleLog( "[SimpleEmpty]" );
261: // baseLog.setLevel(SimpleLog.LOG_LEVEL_TRACE);
262:
263: // test output when writing empty elements
264: StringWriter out = new StringWriter();
265: out.write("<?xml version='1.0'?>");
266: BeanWriter writer = new BeanWriter(out);
267: writer.setWriteEmptyElements(true);
268: writer.getBindingConfiguration().setMapIDs(false);
269: writer.write(bean);
270: // baseLog.debug("SIMPLE EMPTY");
271: // baseLog.debug(out.getBuffer().toString());
272: String xml = "<?xml version='1.0'?><AddressBean><street>Pasture Lane</street><city>Bradford</city>"
273: + "<code/><country/></AddressBean>";
274: // baseLog.debug(xml);
275:
276: xmlAssertIsomorphicContent(parseString(out.getBuffer()
277: .toString()), parseString(xml), true);
278:
279: // test output when not writing empty elements
280: out = new StringWriter();
281: out.write("<?xml version='1.0'?>");
282: writer = new BeanWriter(out);
283: writer.setWriteEmptyElements(false);
284: writer.getBindingConfiguration().setMapIDs(false);
285: // writer.setAbstractBeanWriterLog(log);
286: writer.write(bean);
287: xml = "<?xml version='1.0'?><AddressBean><street>Pasture Lane</street><city>Bradford</city>"
288: + "</AddressBean>";
289: // baseLog.debug("SIMPLE NOT EMPTY");
290: // baseLog.debug(out.getBuffer().toString());
291: xmlAssertIsomorphicContent(parseString(out.getBuffer()
292: .toString()), parseString(xml), true);
293: }
294:
295: public void testArrayWrite() throws Exception {
296: ArrayBean bean = new ArrayBean("Rob");
297: bean.addHobby("Hacking open source software");
298: bean.addHobby("Playing cricket");
299: bean.addHobby("Watching rugby league");
300: bean.addHobby("Havin' it large");
301:
302: StringWriter out = new StringWriter();
303: out.write("<?xml version='1.0'?>");
304: BeanWriter writer = new BeanWriter(out);
305: writer.setWriteEmptyElements(true);
306: writer.getBindingConfiguration().setMapIDs(false);
307: writer.write(bean);
308:
309: String xml = "<?xml version='1.0'?><ArrayBean><name>Rob</name><hobbies>"
310: + "<hobby>Hacking open source software</hobby>"
311: + "<hobby>Playing cricket</hobby>"
312: + "<hobby>Watching rugby league</hobby>"
313: + "<hobby>Havin' it large</hobby>"
314: + "</hobbies></ArrayBean>";
315: xmlAssertIsomorphicContent(parseString(out.getBuffer()
316: .toString()), parseString(xml), true);
317:
318: String[] array = { "This", "That", "The Other" };
319: out = new StringWriter();
320: out.write("<?xml version='1.0'?>");
321: writer = new BeanWriter(out);
322: writer.setWriteEmptyElements(true);
323: writer.getBindingConfiguration().setMapIDs(false);
324: writer.write(array);
325:
326: xml = "<?xml version='1.0'?><Array>" + "<String>This</String>"
327: + "<String>That</String>"
328: + "<String>The Other</String>" + "</Array>";
329:
330: xmlAssertIsomorphicContent(parseString(out.getBuffer()
331: .toString()), parseString(xml), true);
332: }
333:
334: /** Test nested case for writing empty elements */
335: public void testListedWriteEmptyElements() throws Exception {
336: ListOfNames names = new ListOfNames();
337: names.addName(new NameBean("Tom"));
338: names.addName(new NameBean("Dick"));
339: names.addName(new NameBean("Harry"));
340: names.addName(new NameBean(""));
341:
342: StringWriter out = new StringWriter();
343: out.write("<?xml version='1.0'?>");
344:
345: BeanWriter writer = new BeanWriter(out);
346:
347: //SimpleLog log = new SimpleLog("[testListedWriteEmptyElements:AbstractBeanWriter]");
348: //log.setLevel(SimpleLog.LOG_LEVEL_TRACE);
349: //writer.setAbstractBeanWriterLog(log);
350:
351: //log = new SimpleLog("[testListedWriteEmptyElements:XMLIntrospector]");
352: //log.setLevel(SimpleLog.LOG_LEVEL_TRACE);
353: //writer.getXMLIntrospector().setLog(log);
354:
355: //log = new SimpleLog("[testListedWriteEmptyElements:XMLIntrospectorHelper]");
356: //log.setLevel(SimpleLog.LOG_LEVEL_TRACE);
357: //XMLIntrospectorHelper.setLog(log);
358:
359: writer.setWriteEmptyElements(false);
360: writer.getXMLIntrospector().getConfiguration()
361: .setWrapCollectionsInElement(false);
362: writer.getBindingConfiguration().setMapIDs(false);
363: writer.write("Names", names);
364:
365: String xml = "<?xml version='1.0'?><Names>"
366: + "<name><name>Tom</name></name>"
367: + "<name><name>Dick</name></name>"
368: + "<name><name>Harry</name></name>" + "</Names>";
369:
370: xmlAssertIsomorphicContent(parseString(out.getBuffer()
371: .toString()), parseString(xml), true);
372:
373: out = new StringWriter();
374: out.write("<?xml version='1.0'?>");
375:
376: writer = new BeanWriter(out);
377: writer.setWriteEmptyElements(true);
378: writer.getXMLIntrospector().getConfiguration()
379: .setWrapCollectionsInElement(false);
380: writer.getBindingConfiguration().setMapIDs(false);
381: writer.write("Names", names);
382:
383: xml = "<?xml version='1.0'?><Names>"
384: + "<name><name>Tom</name></name>"
385: + "<name><name>Dick</name></name>"
386: + "<name><name>Harry</name></name>"
387: + "<name><name/></name>" + "</Names>";
388:
389: xmlAssertIsomorphicContent(parseString(out.getBuffer()
390: .toString()), parseString(xml), true);
391:
392: out = new StringWriter();
393: out.write("<?xml version='1.0'?>");
394:
395: writer = new BeanWriter(out);
396: writer.setWriteEmptyElements(true);
397: writer.getXMLIntrospector().getConfiguration()
398: .setWrapCollectionsInElement(true);
399: writer.getBindingConfiguration().setMapIDs(false);
400: writer.write("Names", names);
401:
402: xml = "<?xml version='1.0'?><Names><names>"
403: + "<name><name>Tom</name></name>"
404: + "<name><name>Dick</name></name>"
405: + "<name><name>Harry</name></name>"
406: + "<name><name/></name></names>" + "</Names>";
407:
408: xmlAssertIsomorphicContent(parseString(out.getBuffer()
409: .toString()), parseString(xml), true);
410:
411: out = new StringWriter();
412: out.write("<?xml version='1.0'?>");
413:
414: writer = new BeanWriter(out);
415: writer.setWriteEmptyElements(false);
416: writer.getXMLIntrospector().getConfiguration()
417: .setWrapCollectionsInElement(true);
418: writer.getBindingConfiguration().setMapIDs(false);
419: writer.write("Names", names);
420:
421: xml = "<?xml version='1.0'?><Names><names>"
422: + "<name><name>Tom</name></name>"
423: + "<name><name>Dick</name></name>"
424: + "<name><name>Harry</name></name>" + "</names>"
425: + "</Names>";
426:
427: xmlAssertIsomorphicContent(parseString(out.getBuffer()
428: .toString()), parseString(xml), true);
429:
430: }
431:
432: public void testWriteNameMapperStrategy() throws Exception {
433: ListOfNames names = new ListOfNames();
434: names.addName(new NameBean("Sid James"));
435: names.addName(new NameBean("Kenneth Williams"));
436: names.addName(new NameBean("Joan Simms"));
437: names.addName(new NameBean("Charles Hawtrey"));
438:
439: StringWriter out = new StringWriter();
440: out.write("<?xml version='1.0'?>");
441:
442: BeanWriter writer = new BeanWriter(out);
443: writer.setWriteEmptyElements(true);
444: writer.getXMLIntrospector().getConfiguration()
445: .setWrapCollectionsInElement(true);
446: writer.getBindingConfiguration().setMapIDs(false);
447: writer.write("CarryOn", names);
448:
449: String xml = "<?xml version='1.0'?><CarryOn><names>"
450: + "<name><name>Sid James</name></name>"
451: + "<name><name>Kenneth Williams</name></name>"
452: + "<name><name>Joan Simms</name></name>"
453: + "<name><name>Charles Hawtrey</name></name>"
454: + "</names>" + "</CarryOn>";
455:
456: xmlAssertIsomorphicContent(parseString(out.getBuffer()
457: .toString()), parseString(xml), true);
458:
459: out = new StringWriter();
460: out.write("<?xml version='1.0'?>");
461:
462: writer = new BeanWriter(out);
463: writer.setWriteEmptyElements(true);
464: writer.getXMLIntrospector().getConfiguration()
465: .setWrapCollectionsInElement(true);
466: writer.getBindingConfiguration().setMapIDs(false);
467: writer.getXMLIntrospector().getConfiguration()
468: .setElementNameMapper(new CapitalizeNameMapper());
469: writer.write("CarryOn", names);
470:
471: xml = "<?xml version='1.0'?><CarryOn><Names>"
472: + "<Name><Name>Sid James</Name></Name>"
473: + "<Name><Name>Kenneth Williams</Name></Name>"
474: + "<Name><Name>Joan Simms</Name></Name>"
475: + "<Name><Name>Charles Hawtrey</Name></Name>"
476: + "</Names>" + "</CarryOn>";
477:
478: xmlAssertIsomorphicContent(parseString(out.getBuffer()
479: .toString()), parseString(xml), true);
480:
481: ArrayList things = new ArrayList();
482: things.add(new NameBean("Sugar"));
483: things.add(new NameBean("Spice"));
484: things.add(new NameBean("All Things Nice"));
485:
486: NoAdderBean bean = new NoAdderBean();
487: bean.setThings(things);
488:
489: out = new StringWriter();
490: out.write("<?xml version='1.0'?>");
491: writer = new BeanWriter(out);
492: writer.setWriteEmptyElements(true);
493: writer.getXMLIntrospector().getConfiguration()
494: .setWrapCollectionsInElement(true);
495: writer.getBindingConfiguration().setMapIDs(false);
496: writer.write(bean);
497:
498: xml = "<?xml version='1.0'?><NoAdderBean><things>"
499: + "<NameBean><name>Sugar</name></NameBean>"
500: + "<NameBean><name>Spice</name></NameBean>"
501: + "<NameBean><name>All Things Nice</name></NameBean>"
502: + "</things>" + "</NoAdderBean>";
503:
504: xmlAssertIsomorphicContent(parseString(out.getBuffer()
505: .toString()), parseString(xml), true);
506:
507: out = new StringWriter();
508: out.write("<?xml version='1.0'?>");
509: writer = new BeanWriter(out);
510: writer.setWriteEmptyElements(true);
511: writer.getXMLIntrospector().getConfiguration()
512: .setWrapCollectionsInElement(true);
513: writer.getBindingConfiguration().setMapIDs(false);
514: writer.getXMLIntrospector().getConfiguration()
515: .setElementNameMapper(new CapitalizeNameMapper());
516: writer.write(bean);
517:
518: xml = "<?xml version='1.0'?><NoAdderBean><Things>"
519: + "<NameBean><Name>Sugar</Name></NameBean>"
520: + "<NameBean><Name>Spice</Name></NameBean>"
521: + "<NameBean><Name>All Things Nice</Name></NameBean>"
522: + "</Things>" + "</NoAdderBean>";
523:
524: xmlAssertIsomorphicContent(parseString(out.getBuffer()
525: .toString()), parseString(xml), true);
526:
527: out = new StringWriter();
528: out.write("<?xml version='1.0'?>");
529: writer = new BeanWriter(out);
530: writer.setWriteEmptyElements(true);
531: writer.getXMLIntrospector().getConfiguration()
532: .setWrapCollectionsInElement(true);
533: writer.getBindingConfiguration().setMapIDs(false);
534: writer.getXMLIntrospector().getConfiguration()
535: .setElementNameMapper(new HyphenatedNameMapper(false));
536: writer.write(bean);
537:
538: xml = "<?xml version='1.0'?><no-adder-bean><things>"
539: + "<name-bean><name>Sugar</name></name-bean>"
540: + "<name-bean><name>Spice</name></name-bean>"
541: + "<name-bean><name>All Things Nice</name></name-bean>"
542: + "</things>" + "</no-adder-bean>";
543:
544: xmlAssertIsomorphicContent(parseString(out.getBuffer()
545: .toString()), parseString(xml), true);
546: }
547:
548: public void testBeanWriterWorksWithAnAddMethodAndACollection()
549: throws Exception {
550:
551: BeanWriter bw = new BeanWriter();
552: try {
553: bw.write(new BeanWithAddMethod());
554: } catch (IllegalArgumentException e) {
555: fail("BeanWriter fails when a method is just called add(<type>) and there is also a collection");
556: }
557: }
558:
559: // used in testBeanWriterWorksWithAnAddMethodAndACollection
560: public static class BeanWithAddMethod {
561: private Collection x;
562:
563: public void add(Object x) {
564: // do nothing
565: }
566:
567: public Collection getX() {
568: return x;
569: }
570:
571: public void setX(Collection x) {
572: this.x = x;
573: }
574: }
575: }
|