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.recursion;
18  
19  import java.io.StringWriter;
20  import java.io.Writer;
21  import java.util.List;
22  
23  import junit.framework.Test;
24  import junit.framework.TestSuite;
25  
26  import org.apache.commons.betwixt.AbstractTestCase;
27  import org.apache.commons.betwixt.XMLIntrospector;
28  import org.apache.commons.betwixt.io.BeanReader;
29  import org.apache.commons.betwixt.io.BeanWriter;
30  import org.apache.commons.betwixt.io.CyclicReferenceException;
31  
32  
33  /***
34   * This will test the recursive behaviour of betwixt.
35   *
36   * @author <a href="mailto:martin@mvdb.net">Martin van den Bemt</a>
37   * @version $Id: TestRecursion.java,v 1.14 2004/02/28 13:38:36 yoavs Exp $
38   */
39  public class TestRecursion extends AbstractTestCase
40  {
41      
42  
43      
44      public TestRecursion(String testName)
45      {
46          super(testName);
47      }
48      
49      public static Test suite()
50      {
51          return new TestSuite(TestRecursion.class);
52      }
53      
54      /***
55       * This will test reading a simple recursive xml file
56       * 
57       */
58      public void testReadwithCollectionsInElementRoundTrip()
59      throws Exception
60      {
61          //SimpleLog log = new SimpleLog("[testReadwithCollectionsInElementRoundTrip:XMLIntrospectorHelper]");
62          //log.setLevel(SimpleLog.LOG_LEVEL_TRACE);
63          //XMLIntrospectorHelper.setLog(log);
64          
65          //log = new SimpleLog("[testReadwithCollectionsInElementRoundTrip:XMLIntrospector]");
66          //log.setLevel(SimpleLog.LOG_LEVEL_TRACE);
67      
68          XMLIntrospector intro = createXMLIntrospector();
69          //intro.setLog(log);
70          intro.setWrapCollectionsInElement(true);
71          
72          //log = new SimpleLog("[testReadwithCollectionsInElementRoundTrip:BeanReader]");
73          //log.setLevel(SimpleLog.LOG_LEVEL_TRACE);
74          
75          BeanReader reader = new BeanReader();
76          reader.setXMLIntrospector(intro);
77          //reader.setLog(log);
78          reader.registerBeanClass(ElementBean.class);
79          
80          ElementBean bean = (ElementBean) reader.parse(
81                      getTestFileURL("src/test/org/apache/commons/betwixt/recursion/recursion.xml"));
82          
83          List elements = bean.getElements();
84          assertEquals("Root elements size", 2, elements.size());
85          Element elementOne = (Element) elements.get(0);
86          assertEquals("Element one name", "element1", elementOne.getName());
87          Element elementTwo = (Element) elements.get(1);
88          assertEquals("Element two name", "element2", elementTwo.getName());
89          assertEquals("Element two children", 0, elementTwo.getElements().size());
90          elements = elementOne.getElements();
91          assertEquals("Element one children", 2, elements.size());
92          Element elementOneOne = (Element) elements.get(0);
93          assertEquals("Element one one name", "element11", elementOneOne.getName());
94          Element elementOneTwo = (Element) elements.get(1);
95          assertEquals("Element one two name", "element12", elementOneTwo.getName());
96          assertEquals("Element one two children", 0, elementOneTwo.getElements().size());
97          elements = elementOneOne.getElements();
98          assertEquals("Element one one children", 2, elements.size());
99          Element elementOneOneOne = (Element) elements.get(0);
100         assertEquals("Element one one one name", "element111", elementOneOneOne.getName());
101         Element elementOneOneTwo = (Element) elements.get(1);
102         assertEquals("Element one one two name", "element112", elementOneOneTwo.getName());        
103         
104         StringWriter buffer = new StringWriter();
105         write (bean, buffer, true);
106             
107         String xml = "<?xml version='1.0'?><ElementBean><elements><element name='element1'>"
108                     + "<elements><element name='element11'><elements><element name='element111'>"
109                     + "<elements/></element><element name='element112'><elements/></element>"
110                     + "</elements></element><element name='element12'><elements/></element>"
111                     + "</elements></element><element name='element2'><elements/>"
112                     + "</element></elements></ElementBean>";
113         
114         xmlAssertIsomorphic(	
115                     parseString(xml), 
116                     parseString(buffer.getBuffer().toString()), 
117                     true);
118     }
119     /***
120      * This will test reading a simple recursive xml file
121      */
122     public void testReadWithoutCollectionsInElementRoundTrip()
123     throws Exception
124     {
125 //        SimpleLog log = new SimpleLog("[testReadWithoutCollectionsInElementRoundTrip:BeanRuleSet]");
126 //        log.setLevel(SimpleLog.LOG_LEVEL_TRACE);
127 //        BeanRuleSet.setLog(log);
128         
129 //	log = new SimpleLog("[testReadWithoutCollectionsInElementRoundTrip:XMLIntrospector]");
130 //        log.setLevel(SimpleLog.LOG_LEVEL_TRACE);
131  
132         XMLIntrospector intro = createXMLIntrospector();
133         intro.setWrapCollectionsInElement(false);
134 //        intro.setLog(log);
135 //        log = new SimpleLog("[testReadWithoutCollectionsInElementRoundTrip:XMLIntrospectorHelper]");
136 //        log.setLevel(SimpleLog.LOG_LEVEL_TRACE);
137 //        XMLIntrospectorHelper.setLog(log);
138         BeanReader reader = new BeanReader();
139 //        log = new SimpleLog("[testReadWithoutCollectionsInElementRoundTrip:BeanReader]");
140 //        log.setLevel(SimpleLog.LOG_LEVEL_TRACE);
141 //        reader.setLog(log);
142         reader.setXMLIntrospector(intro);
143         reader.registerBeanClass(ElementBean.class);
144         ElementBean bean = (ElementBean) reader.
145                         parse(getTestFileURL("src/test/org/apache/commons/betwixt/recursion/recursion2.xml"));
146         List elements = bean.getElements();
147         assertEquals("Number of elements in root bean", 2, elements.size());
148         Element elementOne = (Element) bean.elements.get(0);
149         assertEquals("First element name", "element1", elementOne.getName());
150         Element elementTwo = (Element) bean.elements.get(1);
151         assertEquals("Second element name", "element2", elementTwo.getName());
152         
153         elements = elementOne.getElements();
154         assertEquals("Number of child elements in first element", 2, elements.size());
155         Element elementOneOne = (Element) elements.get(0);
156         assertEquals("11 element name", "element11", elementOneOne.getName());
157         Element elementOneTwo = (Element) elements.get(1);
158         assertEquals("12 element name", "element12", elementOneTwo.getName());
159         
160         elements = elementOneOne.getElements();
161         assertEquals("Number of child elements in element 11", 2, elements.size());
162         Element elementOneOneOne = (Element) elements.get(0);
163         assertEquals("111 element name", "element111", elementOneOneOne.getName());
164 
165         assertEquals("111 child elements ", 0, elementOneOneOne.getElements().size());
166         
167         Element elementOneOneTwo = (Element) elements.get(1);
168         assertEquals("112 element name", "element112", elementOneOneTwo.getName());
169         assertEquals("112 child elements ", 0, elementOneOneTwo.getElements().size());
170         
171         elements = elementOneTwo.getElements();
172         assertEquals("Number of child elements in element 12", 0, elements.size());
173         
174         elements = elementTwo.getElements();
175         assertEquals("Number of child elements in element 2", 0, elements.size());
176         
177         StringWriter buffer = new StringWriter();
178         buffer.write("<?xml version='1.0'?>");
179         write (bean, buffer, false);
180  
181         String xml = "<ElementBean><element name='element1'><element name='element11'><element name='element111' />"
182                 + "<element name='element112' /> </element><element name='element12' /> </element>"
183                 + "<element name='element2' /> </ElementBean>";
184         
185         xmlAssertIsomorphic(parseString(xml), parseString(buffer.getBuffer().toString()), true);
186         
187     }
188     
189     /***
190      * Opens a writer and writes an object model according to the
191      * retrieved bean
192      */
193     private void write(Object bean, Writer out, boolean wrapIt)
194     throws Exception
195     {
196         BeanWriter writer = new BeanWriter(out);
197         writer.setWriteEmptyElements( true );
198         writer.setXMLIntrospector(createXMLIntrospector());
199         // specifies weather to use collection elements or not.
200         writer.getXMLIntrospector().setWrapCollectionsInElement(wrapIt);
201         // we don't want to write Id attributes to every element
202         // we just want our opbject model written nothing more..
203         writer.setWriteIDs(false);
204         // the source has 2 spaces indention and \n as line seperator.
205         writer.setIndent("  ");
206         writer.setEndOfLine("\n");
207         writer.write(bean);
208     }
209     /***
210      * Set up the XMLIntroSpector
211      */
212     protected XMLIntrospector createXMLIntrospector() {
213         XMLIntrospector introspector = new XMLIntrospector();
214 
215         // set elements for attributes to true
216         introspector.setAttributesForPrimitives(true);
217         introspector.setWrapCollectionsInElement(false);
218         
219         return introspector;
220     }
221     
222 
223     /***
224      */
225     public void testBeanWithIdProperty() throws Exception
226     {
227         IdBean bean = new IdBean("Hello, World");
228         bean.setNotId("Not ID");
229         StringWriter out = new StringWriter();
230         out.write("<?xml version='1.0'?>");
231         BeanWriter writer = new BeanWriter(out);
232         writer.setWriteEmptyElements( true );
233         writer.getXMLIntrospector().setAttributesForPrimitives(true);
234         writer.setWriteIDs(true);
235         writer.write(bean);
236         
237         String xml = "<?xml version='1.0'?><IdBean notId='Not ID' id='Hello, World'/>";
238         
239         xmlAssertIsomorphic(parseString(xml), parseString(out.getBuffer().toString()), true);
240     }    
241     
242     /***
243      * Check that a cyclic reference exception is not thrown in this case 
244      */
245     public void testCyclicReferenceStack1() throws Exception
246     {
247         Element alpha = new Element("Alpha");
248         Element beta = new Element("Beta");
249         Element gamma = new Element("Gamma");
250         Element epsilon = new Element("Epsilon");
251         
252         alpha.addElement(beta);
253         beta.addElement(gamma);
254         gamma.addElement(epsilon);
255         alpha.addElement(epsilon);
256         
257         StringWriter stringWriter = new StringWriter();
258         BeanWriter writer = new BeanWriter(stringWriter);
259         writer.setWriteEmptyElements( true );
260         writer.setWriteIDs(false);
261         writer.write(alpha);
262 
263         String xml = "<?xml version='1.0'?><Element><name>Alpha</name><elements><element>"
264                     + "<name>Beta</name><elements><element><name>Gamma</name><elements>"
265                     + "<element><name>Epsilon</name><elements/></element></elements>"
266                     + "</element></elements></element><element><name>Epsilon</name>"
267                     + "<elements/></element></elements></Element>";
268         
269         xmlAssertIsomorphic(parseString(xml), parseString(stringWriter.getBuffer().toString()), true);
270     }    
271 
272     /***
273      * This should throw a cyclic reference
274      */
275     public void testCyclicReferenceStack2() throws Exception
276     {
277         Element alpha = new Element("Alpha");
278         Element beta = new Element("Beta");
279         Element gamma = new Element("Gamma");
280         Element epsilon = new Element("Epsilon");
281         
282         alpha.addElement(beta);
283         beta.addElement(gamma);
284         gamma.addElement(epsilon);
285         epsilon.addElement(beta);
286         
287         StringWriter stringWriter = new StringWriter();
288         BeanWriter writer = new BeanWriter(stringWriter);
289         writer.setWriteEmptyElements( true );
290         writer.setWriteIDs(false);
291         
292         //SimpleLog log = new SimpleLog("[testCyclicReferenceStack2:BeanWriter]");
293         //log.setLevel(SimpleLog.LOG_LEVEL_TRACE);
294         //writer.setLog(log);
295         
296         //log = new SimpleLog("[testCyclicReferenceStack2:BeanWriter]");
297         //log.setLevel(SimpleLog.LOG_LEVEL_TRACE);
298         //writer.setAbstractBeanWriterLog(log);
299         
300         try {
301             writer.write(alpha);
302             fail("Cycle was not detected!");
303             
304         } catch (CyclicReferenceException e) {
305             // that's what we expected!
306         }
307     }  
308 }
309