View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.configuration.tree;
18  
19  import static org.junit.Assert.assertEquals;
20  import static org.junit.Assert.assertFalse;
21  import static org.junit.Assert.assertNotSame;
22  import static org.junit.Assert.assertNull;
23  import static org.junit.Assert.assertSame;
24  import static org.junit.Assert.assertTrue;
25  
26  import java.util.Iterator;
27  import java.util.List;
28  import java.util.StringTokenizer;
29  
30  import org.junit.Before;
31  import org.junit.Test;
32  
33  /**
34   * Test class for DefaultConfigurationNode.
35   *
36   * @author <a
37   * href="http://commons.apache.org/configuration/team-list.html">Commons
38   * Configuration team</a>
39   * @version $Id: TestDefaultConfigurationNode.java 1225917 2011-12-30 20:42:09Z oheger $
40   */
41  public class TestDefaultConfigurationNode
42  {
43      /** Constant array for the field names. */
44      private static final String[] FIELD_NAMES =
45      { "UID", "NAME", "FIRSTNAME", "LASTLOGIN"};
46  
47      /** Constant array for the field data types. */
48      private static final String[] FIELD_TYPES =
49      { "long", "string", "string", "date"};
50  
51      /** Constant array for additional field attributes. */
52      private static final String[] FIELD_ATTRS =
53      { "primarykey,unique", "notnull", "notnull", null};
54  
55      /** The node to be tested. */
56      DefaultConfigurationNode node;
57  
58      @Before
59      public void setUp() throws Exception
60      {
61          node = new DefaultConfigurationNode();
62          node.setName("table");
63          node.setReference("TestReference");
64          node.addAttribute(new DefaultConfigurationNode("type", "system"));
65          node.addChild(new DefaultConfigurationNode("name", "users"));
66  
67          // Add nodes for the table's fields
68          for (int i = 0; i < FIELD_NAMES.length; i++)
69          {
70              DefaultConfigurationNode field = new DefaultConfigurationNode(
71                      "field");
72              field
73                      .addChild(new DefaultConfigurationNode("name",
74                              FIELD_NAMES[i]));
75              field.addAttribute(new DefaultConfigurationNode("type",
76                      FIELD_TYPES[i]));
77              if (FIELD_ATTRS[i] != null)
78              {
79                  StringTokenizer tok = new StringTokenizer(FIELD_ATTRS[i], ", ");
80                  while (tok.hasMoreTokens())
81                  {
82                      field.addAttribute(new DefaultConfigurationNode(
83                              "attribute", tok.nextToken()));
84                  }
85              }
86              node.addChild(field);
87          }
88      }
89  
90      /**
91       * Tests a newly created, uninitialized node.
92       */
93      @Test
94      public void testNewNode()
95      {
96          node = new DefaultConfigurationNode();
97          assertNull("name is not null", node.getName());
98          assertNull("value is not null", node.getValue());
99          assertNull("reference is not null", node.getReference());
100         assertTrue("Children are not empty", node.getChildren().isEmpty());
101         assertTrue("Named children are not empty", node.getChildren("test")
102                 .isEmpty());
103         assertEquals("Children cound is not 0", 0, node.getChildrenCount());
104         assertEquals("Named children count is not 0", 0, node
105                 .getChildrenCount("test"));
106         assertTrue("Attributes are not empty", node.getAttributes().isEmpty());
107         assertTrue("Named attributes are not empty", node.getAttributes("test")
108                 .isEmpty());
109         assertNull("Node has a parent", node.getParentNode());
110         assertFalse("Node is defined", node.isDefined());
111     }
112 
113     /**
114      * Tries to access an attribute using an invalid index.
115      */
116     @Test(expected = IndexOutOfBoundsException.class)
117     public void testGetAttributeNonExisting()
118     {
119         node = new DefaultConfigurationNode();
120         node.getAttribute(0);
121     }
122 
123     /**
124      * Tests accessing a node's reference.
125      */
126     @Test
127     public void testGetReference()
128     {
129         assertEquals("Reference was not stored", "TestReference", node
130                 .getReference());
131     }
132 
133     /**
134      * Tests accessing the node's children.
135      */
136     @Test
137     public void testGetChildren()
138     {
139         assertEquals("Number of children incorrect", FIELD_NAMES.length + 1,
140                 node.getChildrenCount());
141         List<ConfigurationNode> children = node.getChildren();
142         Iterator<ConfigurationNode> it = children.iterator();
143         DefaultConfigurationNode child = (DefaultConfigurationNode) it.next();
144         assertEquals("Wrong node", "name", child.getName());
145         checkFieldNodes(it);
146     }
147 
148     /**
149      * Tests accessing the node's children by name.
150      */
151     @Test
152     public void testGetChildrenByName()
153     {
154         List<ConfigurationNode> children = node.getChildren("field");
155         assertEquals("Incorrect number of child nodes", FIELD_NAMES.length,
156                 children.size());
157         assertEquals("Incorrect result of getChildrenCount()",
158                 FIELD_NAMES.length, node.getChildrenCount("field"));
159         checkFieldNodes(children.iterator());
160         assertTrue("Found non existing nodes", node.getChildren("test")
161                 .isEmpty());
162         assertEquals("Wrong children list for null", node.getChildren(), node
163                 .getChildren(null));
164     }
165 
166     /**
167      * Tests adding a new child node.
168      */
169     @Test
170     public void testAddChild()
171     {
172         int cnt = node.getChildrenCount();
173         DefaultConfigurationNode ndNew = new DefaultConfigurationNode("test",
174                 "xyz");
175         node.addChild(ndNew);
176         assertEquals("New node was not added", cnt + 1, node.getChildrenCount());
177         List<ConfigurationNode> children = node.getChildren();
178         assertEquals("Incorrect number of children", node.getChildrenCount(),
179                 children.size());
180         assertSame("Node was not added to end", ndNew, children.get(cnt));
181         assertEquals("Incorrect number of named children", 1, node
182                 .getChildrenCount(ndNew.getName()));
183         assertFalse("Child is an attribute", ndNew.isAttribute());
184         assertSame("Parent was not set", node, ndNew.getParentNode());
185     }
186 
187     /**
188      * Tries to add a null child node.
189      */
190     @Test(expected = IllegalArgumentException.class)
191     public void testAddChildNull()
192     {
193         node.addChild(null);
194     }
195 
196     /**
197      * Tries to add a node without a name.
198      */
199     @Test(expected = IllegalArgumentException.class)
200     public void testAddUndefinedChild()
201     {
202         node.addChild(new DefaultConfigurationNode());
203     }
204 
205     /**
206      * Tests removing a child node.
207      */
208     @Test
209     public void testRemoveChild()
210     {
211         DefaultConfigurationNode child = (DefaultConfigurationNode) node
212                 .getChildren().get(3);
213         int cnt = node.getChildrenCount();
214         node.removeChild(child);
215         assertEquals("Child was not removed", cnt - 1, node.getChildrenCount());
216         for (ConfigurationNode nd : node.getChildren())
217         {
218             assertNotSame("Found removed node", child, nd);
219         }
220         assertNull("Parent reference was not removed", child.getParentNode());
221     }
222 
223     /**
224      * Tests removing a child node that does not belong to this node.
225      */
226     @Test
227     public void testRemoveNonExistingChild()
228     {
229         int cnt = node.getChildrenCount();
230         node.removeChild(new DefaultConfigurationNode("test"));
231         node.removeChild(new DefaultConfigurationNode());
232         node.removeChild((ConfigurationNode) null);
233         node.removeChild("non existing child node");
234         node.removeChild((String) null);
235         assertEquals("Children were changed", cnt, node.getChildrenCount());
236     }
237 
238     /**
239      * Tests removing children by their name.
240      */
241     @Test
242     public void testRemoveChildByName()
243     {
244         int cnt = node.getChildrenCount();
245         node.removeChild("name");
246         assertEquals("Child was not removed", cnt - 1, node.getChildrenCount());
247         assertEquals("Still found name child", 0, node.getChildrenCount("name"));
248         node.removeChild("field");
249         assertEquals("Still remaining nodes", 0, node.getChildrenCount());
250     }
251 
252     /**
253      * Tests removing all children at once.
254      */
255     @Test
256     public void testRemoveChildren()
257     {
258         node.removeChildren();
259         assertEquals("Children count is not 0", 0, node.getChildrenCount());
260         assertTrue("Children are not empty", node.getChildren().isEmpty());
261     }
262 
263     /**
264      * Tests accessing a child by its index.
265      */
266     @Test
267     public void testGetChild()
268     {
269         ConfigurationNode child = node.getChild(2);
270         assertEquals("Wrong child returned", child, node.getChildren().get(2));
271     }
272 
273     /**
274      * Tests accessing child nodes with invalid indices.
275      */
276     @Test(expected = IndexOutOfBoundsException.class)
277     public void testGetChildInvalidIndex()
278     {
279         node.getChild(4724);
280     }
281 
282     /**
283      * Tests accessing the node's attributes.
284      */
285     @Test
286     public void testGetAttributes()
287     {
288         assertEquals("Number of attributes incorrect", 1, node
289                 .getAttributeCount());
290         List<ConfigurationNode> attributes = node.getAttributes();
291         Iterator<ConfigurationNode> it = attributes.iterator();
292         DefaultConfigurationNode attr = (DefaultConfigurationNode) it.next();
293         assertEquals("Wrong node", "type", attr.getName());
294         assertFalse("More attributes", it.hasNext());
295     }
296 
297     /**
298      * Tests accessing the node's attributes by name.
299      */
300     @Test
301     public void testGetAttributesByName()
302     {
303         assertEquals("Incorrect number of attributes", 1, node
304                 .getAttributeCount("type"));
305         DefaultConfigurationNode field = (DefaultConfigurationNode) node
306                 .getChildren().get(1);
307         assertEquals("Incorrect number of attributes", 2, field
308                 .getAttributeCount("attribute"));
309         List<ConfigurationNode> attrs = field.getAttributes("attribute");
310         assertEquals("Wrong value", "primarykey",
311                 ((DefaultConfigurationNode) attrs.get(0)).getValue());
312         assertEquals("Wrong value", "unique", ((DefaultConfigurationNode) attrs
313                 .get(1)).getValue());
314     }
315 
316     /**
317      * Tests adding a new attribute node.
318      */
319     @Test
320     public void testAddAttribute()
321     {
322         int cnt = node.getAttributeCount();
323         DefaultConfigurationNode ndNew = new DefaultConfigurationNode("test",
324                 "xyz");
325         node.addAttribute(ndNew);
326         assertEquals("New node was not added", cnt + 1, node
327                 .getAttributeCount());
328         List<ConfigurationNode> attrs = node.getAttributes();
329         assertEquals("Incorrect number of attributes",
330                 node.getAttributeCount(), attrs.size());
331         assertSame("Node was not added to end", ndNew, attrs.get(cnt));
332         assertEquals("Incorrect number of named attributes", 1, node
333                 .getAttributeCount(ndNew.getName()));
334         assertTrue("Child is no attribute", ndNew.isAttribute());
335         assertSame("Parent was not set", node, ndNew.getParentNode());
336     }
337 
338     /**
339      * Tests removing an attribute node.
340      */
341     @Test
342     public void testRemoveAttribute()
343     {
344         DefaultConfigurationNode attr = (DefaultConfigurationNode) node
345                 .getAttributes().get(0);
346         int cnt = node.getAttributeCount();
347         node.removeAttribute(attr);
348         assertEquals("Attribute was not removed", cnt - 1, node
349                 .getAttributeCount());
350         for (ConfigurationNode nd : node.getAttributes())
351         {
352             assertNotSame("Found removed node", attr, nd);
353         }
354         assertNull("Parent reference was not removed", attr.getParentNode());
355     }
356 
357     /**
358      * Tests removing attributes by their names.
359      */
360     @Test
361     public void testRemoveAttributeByName()
362     {
363         ConfigurationNode field = node.getChild(1);
364         assertEquals("Incorrect number of attributes", 3, field
365                 .getAttributeCount());
366         field.removeAttribute("attribute");
367         assertEquals("Not all nodes removed", 1, field.getAttributeCount());
368         assertTrue("Remaining attributes", field.getAttributes("attribute")
369                 .isEmpty());
370         field.removeAttribute("type");
371         assertEquals("Remaining attributes", 0, field.getAttributeCount());
372     }
373 
374     /**
375      * Tests removing all attributes.
376      */
377     @Test
378     public void testRemoveAttributes()
379     {
380         node.removeAttributes();
381         assertEquals("Not all attributes removed", 0, node.getAttributeCount());
382         assertTrue("Attributes not empty", node.getAttributes().isEmpty());
383     }
384 
385     /**
386      * Tests changing a node's attribute state.
387      */
388     @Test(expected = IllegalStateException.class)
389     public void testChangeAttributeState()
390     {
391         ConfigurationNode attr = node.getAttribute(0);
392         attr.setAttribute(false);
393     }
394 
395     /**
396      * Tests the visit() method using a simple visitor.
397      */
398     @Test
399     public void testVisit()
400     {
401         CountNodeVisitor visitor = new CountNodeVisitor();
402         node.visit(visitor);
403         assertEquals("Not all nodes visited", 19, visitor.beforeCalls);
404         assertEquals("Different number of before and after calls",
405                 visitor.beforeCalls, visitor.afterCalls);
406     }
407 
408     /**
409      * Tests the visit() method with a visitor that terminates the visit
410      * process.
411      */
412     @Test
413     public void testVisitWithTerminate()
414     {
415         CountNodeVisitor visitor = new CountNodeVisitor(10);
416         node.visit(visitor);
417         assertEquals("Incorrect number of nodes visited", visitor.maxCalls,
418                 visitor.beforeCalls);
419         assertEquals("Different number of before and after calls",
420                 visitor.beforeCalls, visitor.afterCalls);
421     }
422 
423     /**
424      * Tests the visit() method when null is passed in. This should throw an
425      * exception.
426      */
427     @Test(expected = IllegalArgumentException.class)
428     public void testVisitWithNullVisitor()
429     {
430         node.visit(null);
431     }
432 
433     /**
434      * Tests cloning a node.
435      */
436     @Test
437     public void testClone()
438     {
439         node.setValue("TestValue");
440         DefaultConfigurationNode clone = (DefaultConfigurationNode) node.clone();
441         assertEquals("Value not cloned", "TestValue", clone.getValue());
442         assertEquals("Name not cloned", "table", clone.getName());
443         assertEquals("Reference not cloned", "TestReference", clone.getReference());
444         assertEquals("Children were cloned", 0, clone.getChildrenCount());
445         assertEquals("Attributes were cloned", 0, clone.getAttributeCount());
446     }
447 
448     /**
449      * Helper method for checking the child nodes of type &quot;field&quot;.
450      *
451      * @param itFields the iterator with the child nodes
452      */
453     private void checkFieldNodes(Iterator<ConfigurationNode> itFields)
454     {
455         for (int i = 0; i < FIELD_NAMES.length; i++)
456         {
457             DefaultConfigurationNode child = (DefaultConfigurationNode) itFields
458                     .next();
459             assertEquals("Wrong node", "field", child.getName());
460             List<ConfigurationNode> nameNodes = child.getChildren("name");
461             assertEquals("Wrong number of name nodes", 1, nameNodes.size());
462             DefaultConfigurationNode nameNode = (DefaultConfigurationNode) nameNodes
463                     .get(0);
464             assertEquals("Wrong field name", FIELD_NAMES[i], nameNode
465                     .getValue());
466         }
467     }
468 
469     /**
470      * A test visitor implementation that is able to count the number of visits.
471      * It also supports a maximum number of visits to be set; if this number is
472      * reached, the <code>terminate()</code> method returns <b>true</b>.
473      */
474     public static class CountNodeVisitor implements ConfigurationNodeVisitor
475     {
476         public int beforeCalls;
477 
478         public int afterCalls;
479 
480         public int maxCalls;
481 
482         public CountNodeVisitor()
483         {
484             this(Integer.MAX_VALUE);
485         }
486 
487         public CountNodeVisitor(int maxNumberOfVisits)
488         {
489             maxCalls = maxNumberOfVisits;
490         }
491 
492         public void visitBeforeChildren(ConfigurationNode node)
493         {
494             beforeCalls++;
495         }
496 
497         public void visitAfterChildren(ConfigurationNode node)
498         {
499             afterCalls++;
500         }
501 
502         public boolean terminate()
503         {
504             return beforeCalls >= maxCalls;
505         }
506     }
507 }