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  
18  package org.apache.commons.configuration;
19  
20  import java.util.ArrayList;
21  import java.util.Collection;
22  import java.util.HashSet;
23  import java.util.Iterator;
24  import java.util.List;
25  import java.util.Set;
26  
27  import org.apache.commons.collections.CollectionUtils;
28  import org.apache.commons.configuration.HierarchicalConfiguration.Node;
29  import org.apache.commons.configuration.event.ConfigurationEvent;
30  import org.apache.commons.configuration.event.ConfigurationListener;
31  import org.apache.commons.configuration.tree.DefaultConfigurationNode;
32  import org.apache.commons.configuration.tree.DefaultExpressionEngine;
33  import org.apache.commons.configuration.tree.ExpressionEngine;
34  
35  import junit.framework.TestCase;
36  
37  /***
38   * Test class for HierarchicalConfiguration.
39   *
40   * @version $Id: TestHierarchicalConfiguration.java 439648 2006-09-02 20:42:10Z oheger $
41   */
42  public class TestHierarchicalConfiguration extends TestCase
43  {
44      private static String[] tables = { "users", "documents" };
45  
46      private static String[][] fields =
47      {
48          { "uid", "uname", "firstName", "lastName", "email" },
49          { "docid", "name", "creationDate", "authorID", "version" }
50      };
51  
52      private HierarchicalConfiguration config;
53  
54      protected void setUp() throws Exception
55      {
56          /***
57           * Initialize the configuration with the following structure:
58           *
59           * tables
60           *      table
61           *         name
62           *         fields
63           *             field
64           *                 name
65           *             field
66           *                 name
67           */
68          config = new HierarchicalConfiguration();
69          HierarchicalConfiguration.Node nodeTables = createNode("tables", null);
70          for(int i = 0; i < tables.length; i++)
71          {
72              HierarchicalConfiguration.Node nodeTable = createNode("table", null);
73              nodeTables.addChild(nodeTable);
74              HierarchicalConfiguration.Node nodeName = createNode("name", tables[i]);
75              nodeTable.addChild(nodeName);
76              HierarchicalConfiguration.Node nodeFields = createNode("fields", null);
77              nodeTable.addChild(nodeFields);
78  
79              for (int j = 0; j < fields[i].length; j++)
80              {
81                  nodeFields.addChild(createFieldNode(fields[i][j]));
82              }
83          }
84  
85          config.getRoot().addChild(nodeTables);
86      }
87  
88      public void testSetRoot()
89      {
90          try
91          {
92              config.setRoot(null);
93              fail("Could set null root node!");
94          }
95          catch(IllegalArgumentException iex)
96          {
97              //ok
98          }
99  
100         config.setRoot(new HierarchicalConfiguration.Node("test"));
101         assertTrue(config.isEmpty());
102     }
103 
104     public void testSetRootNode()
105     {
106         config.setRootNode(new DefaultConfigurationNode("testNode"));
107         assertNotSame("Same root node", config.getRootNode(), config.getRoot());
108         assertEquals("Wrong name of root node", "testNode", config.getRoot().getName());
109 
110         config.setRootNode(new HierarchicalConfiguration.Node("test"));
111         assertSame("Wrong root node", config.getRootNode(), config.getRoot());
112     }
113 
114     public void testSetRootNodeNull()
115     {
116         try
117         {
118             config.setRootNode(null);
119             fail("Could set null root node!");
120         }
121         catch(IllegalArgumentException iex)
122         {
123             //ok
124         }
125     }
126 
127     public void testIsEmpty()
128     {
129         assertFalse(config.isEmpty());
130         HierarchicalConfiguration conf2 = new HierarchicalConfiguration();
131         assertTrue(conf2.isEmpty());
132         HierarchicalConfiguration.Node child1 = new HierarchicalConfiguration.Node("child1");
133         HierarchicalConfiguration.Node child2 = new HierarchicalConfiguration.Node("child2");
134         child1.addChild(child2);
135         conf2.getRoot().addChild(child1);
136         assertTrue(conf2.isEmpty());
137     }
138 
139     public void testGetProperty()
140     {
141         assertNull(config.getProperty("tables.table.resultset"));
142         assertNull(config.getProperty("tables.table.fields.field"));
143 
144         Object prop = config.getProperty("tables.table(0).fields.field.name");
145         assertNotNull(prop);
146         assertTrue(prop instanceof Collection);
147         assertEquals(5, ((Collection) prop).size());
148 
149         prop = config.getProperty("tables.table.fields.field.name");
150         assertNotNull(prop);
151         assertTrue(prop instanceof Collection);
152         assertEquals(10, ((Collection) prop).size());
153 
154         prop = config.getProperty("tables.table.fields.field(3).name");
155         assertNotNull(prop);
156         assertTrue(prop instanceof Collection);
157         assertEquals(2, ((Collection) prop).size());
158 
159         prop = config.getProperty("tables.table(1).fields.field(2).name");
160         assertNotNull(prop);
161         assertEquals("creationDate", prop.toString());
162     }
163 
164     public void testSetProperty()
165     {
166         config.setProperty("tables.table(0).name", "resources");
167         assertEquals("resources", config.getString("tables.table(0).name"));
168         config.setProperty("tables.table.name", "tab1,tab2");
169         assertEquals("tab1", config.getString("tables.table(0).name"));
170         assertEquals("tab2", config.getString("tables.table(1).name"));
171 
172         config.setProperty("test.items.item", new int[] { 2, 4, 8, 16 });
173         assertEquals(3, config.getMaxIndex("test.items.item"));
174         assertEquals(8, config.getInt("test.items.item(2)"));
175         config.setProperty("test.items.item(2)", new Integer(6));
176         assertEquals(6, config.getInt("test.items.item(2)"));
177         config.setProperty("test.items.item(2)", new int[] { 7, 9, 11 });
178         assertEquals(5, config.getMaxIndex("test.items.item"));
179 
180         config.setProperty("test", Boolean.TRUE);
181         config.setProperty("test.items", "01/01/05");
182         assertEquals(5, config.getMaxIndex("test.items.item"));
183         assertTrue(config.getBoolean("test"));
184         assertEquals("01/01/05", config.getProperty("test.items"));
185 
186         config.setProperty("test.items.item", new Integer(42));
187         assertEquals(0, config.getMaxIndex("test.items.item"));
188         assertEquals(42, config.getInt("test.items.item"));
189     }
190 
191     public void testClearProperty()
192     {
193         config.clearProperty("tables.table(0).fields.field(0).name");
194         assertEquals("uname", config.getProperty("tables.table(0).fields.field(0).name"));
195         config.clearProperty("tables.table(0).name");
196         assertFalse(config.containsKey("tables.table(0).name"));
197         assertEquals("firstName", config.getProperty("tables.table(0).fields.field(1).name"));
198         assertEquals("documents", config.getProperty("tables.table.name"));
199         config.clearProperty("tables.table");
200         assertEquals("documents", config.getProperty("tables.table.name"));
201 
202         config.addProperty("test", "first");
203         config.addProperty("test.level", "second");
204         config.clearProperty("test");
205         assertEquals("second", config.getString("test.level"));
206         assertFalse(config.containsKey("test"));
207     }
208 
209     public void testClearTree()
210     {
211         Object prop = config.getProperty("tables.table(0).fields.field.name");
212         assertNotNull(prop);
213         config.clearTree("tables.table(0).fields.field(3)");
214         prop = config.getProperty("tables.table(0).fields.field.name");
215         assertNotNull(prop);
216         assertTrue(prop instanceof Collection);
217         assertEquals(4, ((Collection) prop).size());
218 
219         config.clearTree("tables.table(0).fields");
220         assertNull(config.getProperty("tables.table(0).fields.field.name"));
221         prop = config.getProperty("tables.table.fields.field.name");
222         assertNotNull(prop);
223         assertTrue(prop instanceof Collection);
224         assertEquals(5, ((Collection) prop).size());
225 
226         config.clearTree("tables.table(1)");
227         assertNull(config.getProperty("tables.table.fields.field.name"));
228     }
229 
230     public void testContainsKey()
231     {
232         assertTrue(config.containsKey("tables.table(0).name"));
233         assertTrue(config.containsKey("tables.table(1).name"));
234         assertFalse(config.containsKey("tables.table(2).name"));
235 
236         assertTrue(config.containsKey("tables.table(0).fields.field.name"));
237         assertFalse(config.containsKey("tables.table(0).fields.field"));
238         config.clearTree("tables.table(0).fields");
239         assertFalse(config.containsKey("tables.table(0).fields.field.name"));
240 
241         assertTrue(config.containsKey("tables.table.fields.field.name"));
242     }
243 
244     public void testGetKeys()
245     {
246         List keys = new ArrayList();
247         for (Iterator it = config.getKeys(); it.hasNext();)
248         {
249             keys.add(it.next());
250         }
251 
252         assertEquals(2, keys.size());
253         assertTrue(keys.contains("tables.table.name"));
254         assertTrue(keys.contains("tables.table.fields.field.name"));
255 
256         // test the order of the keys returned
257         config.addProperty("order.key1", "value1");
258         config.addProperty("order.key2", "value2");
259         config.addProperty("order.key3", "value3");
260 
261         Iterator it = config.getKeys("order");
262         assertEquals("1st key", "order.key1", it.next());
263         assertEquals("2nd key", "order.key2", it.next());
264         assertEquals("3rd key", "order.key3", it.next());
265     }
266 
267     public void testGetKeysString()
268     {
269         // add some more properties to make it more interesting
270         config.addProperty("tables.table(0).fields.field(1).type", "VARCHAR");
271         config.addProperty("tables.table(0)[@type]", "system");
272         config.addProperty("tables.table(0).size", "42");
273         config.addProperty("tables.table(0).fields.field(0).size", "128");
274         config.addProperty("connections.connection.param.url", "url1");
275         config.addProperty("connections.connection.param.user", "me");
276         config.addProperty("connections.connection.param.pwd", "secret");
277         config.addProperty("connections.connection(-1).param.url", "url2");
278         config.addProperty("connections.connection(1).param.user", "guest");
279 
280         checkKeys("tables.table(1)", new String[] { "name", "fields.field.name" });
281         checkKeys("tables.table(0)",
282                 new String[] { "name", "fields.field.name", "tables.table(0)[@type]", "size", "fields.field.type", "fields.field.size" });
283         checkKeys("connections.connection(0).param",
284                 new String[] {"url", "user", "pwd" });
285         checkKeys("connections.connection(1).param",
286                 new String[] {"url", "user" });
287     }
288 
289     public void testAddProperty()
290     {
291         config.addProperty("tables.table(0).fields.field(-1).name", "phone");
292         Object prop = config.getProperty("tables.table(0).fields.field.name");
293         assertNotNull(prop);
294         assertTrue(prop instanceof Collection);
295         assertEquals(6, ((Collection) prop).size());
296 
297         config.addProperty("tables.table(0).fields.field.name", "fax");
298         prop = config.getProperty("tables.table.fields.field(5).name");
299         assertNotNull(prop);
300         assertTrue(prop instanceof List);
301         List list = (List) prop;
302         assertEquals("phone", list.get(0));
303         assertEquals("fax", list.get(1));
304 
305         config.addProperty("tables.table(-1).name", "config");
306         prop = config.getProperty("tables.table.name");
307         assertNotNull(prop);
308         assertTrue(prop instanceof Collection);
309         assertEquals(3, ((Collection) prop).size());
310         config.addProperty("tables.table(2).fields.field(0).name", "cid");
311         config.addProperty("tables.table(2).fields.field(-1).name",
312         "confName");
313         prop = config.getProperty("tables.table(2).fields.field.name");
314         assertNotNull(prop);
315         assertTrue(prop instanceof Collection);
316         assertEquals(2, ((Collection) prop).size());
317         assertEquals("confName",
318         config.getProperty("tables.table(2).fields.field(1).name"));
319 
320         config.addProperty("connection.user", "scott");
321         config.addProperty("connection.passwd", "tiger");
322         assertEquals("tiger", config.getProperty("connection.passwd"));
323 
324         ConfigurationKey key = new ConfigurationKey();
325         key.append("tables").append("table").appendIndex(0);
326         key.appendAttribute("tableType");
327         config.addProperty(key.toString(), "system");
328         assertEquals("system", config.getProperty(key.toString()));
329 
330         try
331         {
332             config.addProperty(".", "InvalidKey");
333             fail("Could add invalid key!");
334         }
335         catch(IllegalArgumentException iex)
336         {
337             //ok
338         }
339     }
340 
341     public void testGetMaxIndex()
342     {
343         assertEquals(4, config.getMaxIndex("tables.table(0).fields.field"));
344         assertEquals(4, config.getMaxIndex("tables.table(1).fields.field"));
345         assertEquals(1, config.getMaxIndex("tables.table"));
346         assertEquals(1, config.getMaxIndex("tables.table.name"));
347         assertEquals(0, config.getMaxIndex("tables.table(0).name"));
348         assertEquals(0, config.getMaxIndex("tables.table(1).fields.field(1)"));
349         assertEquals(-1, config.getMaxIndex("tables.table(2).fields"));
350 
351         int maxIdx = config.getMaxIndex("tables.table(0).fields.field.name");
352         for(int i = 0; i <= maxIdx; i++)
353         {
354             ConfigurationKey key = new ConfigurationKey("tables.table(0).fields");
355             key.append("field").appendIndex(i).append("name");
356             assertNotNull(config.getProperty(key.toString()));
357         }
358     }
359 
360     public void testSubset()
361     {
362         // test the subset on the first table
363         Configuration subset = config.subset("tables.table(0)");
364         assertEquals(tables[0], subset.getProperty("name"));
365 
366         Object prop = subset.getProperty("fields.field.name");
367         assertNotNull(prop);
368         assertTrue(prop instanceof Collection);
369         assertEquals(5, ((Collection) prop).size());
370 
371         for (int i = 0; i < fields[0].length; i++)
372         {
373             ConfigurationKey key = new ConfigurationKey();
374             key.append("fields").append("field").appendIndex(i);
375             key.append("name");
376             assertEquals(fields[0][i], subset.getProperty(key.toString()));
377         }
378 
379         // test the subset on the second table
380         assertTrue("subset is not empty", config.subset("tables.table(2)").isEmpty());
381 
382         // test the subset on the fields
383         subset = config.subset("tables.table.fields.field");
384         prop = subset.getProperty("name");
385         assertTrue("prop is not a collection", prop instanceof Collection);
386         assertEquals(10, ((Collection) prop).size());
387 
388         assertEquals(fields[0][0], subset.getProperty("name(0)"));
389 
390         // tset the subset on the field names
391         subset = config.subset("tables.table.fields.field.name");
392         assertTrue("subset is not empty", subset.isEmpty());
393     }
394 
395     /***
396      * Tests the configurationAt() method to obtain a configuration for a sub
397      * tree.
398      */
399     public void testConfigurationAt()
400     {
401         HierarchicalConfiguration subConfig = config
402                 .configurationAt("tables.table(1)");
403         assertEquals("Wrong table name", tables[1], subConfig.getString("name"));
404         List lstFlds = subConfig.getList("fields.field.name");
405         assertEquals("Wrong number of fields", fields[1].length, lstFlds.size());
406         for (int i = 0; i < fields[1].length; i++)
407         {
408             assertEquals("Wrong field at position " + i, fields[1][i], lstFlds
409                     .get(i));
410         }
411 
412         subConfig.setProperty("name", "testTable");
413         assertEquals("Change not visible in parent", "testTable", config
414                 .getString("tables.table(1).name"));
415         config.setProperty("tables.table(1).fields.field(2).name", "testField");
416         assertEquals("Change not visible in sub config", "testField", subConfig
417                 .getString("fields.field(2).name"));
418     }
419 
420     /***
421      * Tests the configurationAt() method when the passed in key does not exist.
422      */
423     public void testConfigurationAtUnknownSubTree()
424     {
425         try
426         {
427             config.configurationAt("non.existing.key");
428             fail("Could obtain sub config for unknown key!");
429         }
430         catch (IllegalArgumentException iex)
431         {
432             // ok
433         }
434     }
435 
436     /***
437      * Tests the configurationAt() method when the passed in key selects
438      * multiple nodes. This should cause an exception.
439      */
440     public void testConfigurationAtMultipleNodes()
441     {
442         try
443         {
444             config.configurationAt("tables.table.name");
445             fail("Could create sub config with non unique key!");
446         }
447         catch (IllegalArgumentException iex)
448         {
449             // ok
450         }
451     }
452 
453     /***
454      * Tests the configurationsAt() method.
455      */
456     public void testConfigurationsAt()
457     {
458         List lstFlds = config.configurationsAt("tables.table(1).fields.field");
459         assertEquals("Wrong size of fields", fields[1].length, lstFlds.size());
460         for (int i = 0; i < fields[1].length; i++)
461         {
462             HierarchicalConfiguration sub = (HierarchicalConfiguration) lstFlds
463                     .get(i);
464             assertEquals("Wrong field at position " + i, fields[1][i], sub
465                     .getString("name"));
466         }
467     }
468 
469     /***
470      * Tests the configurationsAt() method when the passed in key does not
471      * select any sub nodes.
472      */
473     public void testConfigurationsAtEmpty()
474     {
475         assertTrue("List is not empty", config.configurationsAt("unknown.key")
476                 .isEmpty());
477     }
478 
479     public void testClone()
480     {
481         Configuration copy = (Configuration) config.clone();
482         assertTrue(copy instanceof HierarchicalConfiguration);
483         for (int i = 0; i < tables.length; i++)
484         {
485             assertEquals(tables[i], copy.getString("tables.table(" + i + ").name"));
486             for (int j = 0; j < fields[i].length; j++)
487             {
488                 assertEquals(fields[i][j], copy.getString("tables.table(" + i + ").fields.field(" + j + ").name"));
489             }
490         }
491     }
492 
493     /***
494      * Tests whether registered event handlers are handled correctly when a
495      * configuration is cloned. They should not be registered at the clone.
496      */
497     public void testCloneWithEventListeners()
498     {
499         config.addConfigurationListener(new ConfigurationListener()
500         {
501             public void configurationChanged(ConfigurationEvent event)
502             {
503                 // just a dummy
504             }
505         });
506         HierarchicalConfiguration copy = (HierarchicalConfiguration) config
507                 .clone();
508         assertTrue("Event listener registered at clone", copy
509                 .getConfigurationListeners().isEmpty());
510     }
511 
512     public void testAddNodes()
513     {
514         Collection nodes = new ArrayList();
515         nodes.add(createFieldNode("birthDate"));
516         nodes.add(createFieldNode("lastLogin"));
517         nodes.add(createFieldNode("language"));
518         config.addNodes("tables.table(0).fields", nodes);
519         assertEquals(7, config.getMaxIndex("tables.table(0).fields.field"));
520         assertEquals("birthDate", config.getString("tables.table(0).fields.field(5).name"));
521         assertEquals("lastLogin", config.getString("tables.table(0).fields.field(6).name"));
522         assertEquals("language", config.getString("tables.table(0).fields.field(7).name"));
523     }
524 
525     /***
526      * Tests the addNodes() method when the provided key does not exist. In
527      * this case, a new node (or even a complete new branch) will be created.
528      */
529     public void testAddNodesForNonExistingKey()
530     {
531         Collection nodes = new ArrayList();
532         nodes.add(createNode("usr", "scott"));
533         Node nd = createNode("pwd", "tiger");
534         nd.setAttribute(true);
535         nodes.add(nd);
536         config.addNodes("database.connection.settings", nodes);
537 
538         assertEquals("Usr node not found", "scott", config.getString("database.connection.settings.usr"));
539         assertEquals("Pwd node not found", "tiger", config.getString("database.connection.settings[@pwd]"));
540     }
541 
542     /***
543      * Tests the addNodes() method when the new nodes should be added to an
544      * attribute node. This is not allowed.
545      */
546     public void testAddNodesWithAttributeKey()
547     {
548         Collection nodes = new ArrayList();
549         nodes.add(createNode("testNode", "yes"));
550         try
551         {
552             config.addNodes("database.connection[@settings]", nodes);
553             fail("Could add nodes to an attribute node!");
554         }
555         catch(IllegalArgumentException iex)
556         {
557             //ok
558         }
559     }
560 
561     /***
562      * Tests removing children from a configuration node.
563      */
564     public void testNodeRemove()
565     {
566         HierarchicalConfiguration.Node node = new HierarchicalConfiguration.Node(
567                 "parent", "test");
568         assertFalse(node.hasChildren());
569         node.removeChildren(); // should have no effect
570         assertFalse(node.remove("child"));
571 
572         node.addChild(createNode("test", "test"));
573         assertTrue(node.hasChildren());
574         assertTrue(node.remove("test"));
575         assertFalse(node.hasChildren());
576 
577         for (int i = 0; i < 10; i++)
578         {
579             node.addChild(createNode("child" + i, "test" + i));
580         }
581         assertTrue(node.hasChildren());
582         assertFalse(node.remove("child"));
583         assertTrue(node.remove("child2"));
584         assertTrue(node.getChildren("child2").isEmpty());
585 
586         HierarchicalConfiguration.Node child = createNode("child0", "testChild");
587         assertFalse(node.remove(child));
588         node.addChild(child);
589         assertTrue(node.remove(child));
590         assertEquals(1, node.getChildren("child0").size());
591         assertEquals("test0", ((HierarchicalConfiguration.Node) node
592                 .getChildren("child0").get(0)).getValue());
593 
594         assertTrue(node.remove("child0"));
595         assertFalse(node.remove(child));
596 
597         node.removeChildren();
598         assertTrue(node.getChildren().isEmpty());
599         assertFalse(node.remove(child));
600     }
601 
602     /***
603      * Tests the visitor mechanism.
604      */
605     public void testNodeVisitor()
606     {
607         CountVisitor v = new CountVisitor();
608         config.getRoot().visit(v, null);
609         assertEquals(28, v.beforeCount);
610         assertEquals(v.beforeCount, v.afterCount);
611     }
612 
613     /***
614      * Tests setting a custom expression engine, which uses a slightly different
615      * syntax.
616      */
617     public void testSetExpressionEngine()
618     {
619         config.setExpressionEngine(null);
620         assertNotNull("Expression engine is null", config.getExpressionEngine());
621         assertSame("Default engine is not used", HierarchicalConfiguration
622                 .getDefaultExpressionEngine(), config.getExpressionEngine());
623 
624         config.setExpressionEngine(createAlternativeExpressionEngine());
625         checkAlternativeSyntax();
626     }
627 
628     /***
629      * Tests setting the default expression engine. This should impact all
630      * configuration instances that do not have their own engine.
631      */
632     public void testSetDefaultExpressionEngine()
633     {
634         ExpressionEngine engineOld = HierarchicalConfiguration.getDefaultExpressionEngine();
635         HierarchicalConfiguration
636                 .setDefaultExpressionEngine(createAlternativeExpressionEngine());
637         checkAlternativeSyntax();
638         HierarchicalConfiguration.setDefaultExpressionEngine(engineOld);
639     }
640 
641     /***
642      * Tests setting the default expression engine to null. This should not be
643      * allowed.
644      */
645     public void testSetDefaultExpressionEngineNull()
646     {
647         try
648         {
649             HierarchicalConfiguration.setDefaultExpressionEngine(null);
650             fail("Could set default expression engine to null!");
651         }
652         catch (IllegalArgumentException iex)
653         {
654             // ok
655         }
656     }
657 
658     /***
659      * Helper method for testing the getKeys(String) method.
660      * @param prefix the key to pass into getKeys()
661      * @param expected the expected result
662      */
663     private void checkKeys(String prefix, String[] expected)
664     {
665         Set values = new HashSet();
666         for(int i = 0; i < expected.length; i++)
667         {
668             values.add((expected[i].startsWith(prefix)) ? expected[i] :  prefix + "." + expected[i]);
669         }
670 
671         Iterator itKeys = config.getKeys(prefix);
672         while(itKeys.hasNext())
673         {
674             String key = (String) itKeys.next();
675             if(!values.contains(key))
676             {
677                 fail("Found unexpected key: " + key);
678             }
679             else
680             {
681                 values.remove(key);
682             }
683         }
684 
685         assertTrue("Remaining keys " + values, values.isEmpty());
686     }
687 
688     /***
689      * Helper method for checking keys using an alternative syntax.
690      */
691     private void checkAlternativeSyntax()
692     {
693         assertNull(config.getProperty("tables/table/resultset"));
694         assertNull(config.getProperty("tables/table/fields/field"));
695 
696         Object prop = config.getProperty("tables/table[0]/fields/field/name");
697         assertNotNull(prop);
698         assertTrue(prop instanceof Collection);
699         assertEquals(5, ((Collection) prop).size());
700 
701         prop = config.getProperty("tables/table/fields/field/name");
702         assertNotNull(prop);
703         assertTrue(prop instanceof Collection);
704         assertEquals(10, ((Collection) prop).size());
705 
706         prop = config.getProperty("tables/table/fields/field[3]/name");
707         assertNotNull(prop);
708         assertTrue(prop instanceof Collection);
709         assertEquals(2, ((Collection) prop).size());
710 
711         prop = config.getProperty("tables/table[1]/fields/field[2]/name");
712         assertNotNull(prop);
713         assertEquals("creationDate", prop.toString());
714 
715         Set keys = new HashSet();
716         CollectionUtils.addAll(keys, config.getKeys());
717         assertEquals("Wrong number of defined keys", 2, keys.size());
718         assertTrue("Key not found", keys.contains("tables/table/name"));
719         assertTrue("Key not found", keys
720                 .contains("tables/table/fields/field/name"));
721     }
722 
723     private ExpressionEngine createAlternativeExpressionEngine()
724     {
725         DefaultExpressionEngine engine = new DefaultExpressionEngine();
726         engine.setPropertyDelimiter("/");
727         engine.setIndexStart("[");
728         engine.setIndexEnd("]");
729         return engine;
730     }
731 
732     /***
733      * Helper method for creating a field node with its children.
734      *
735      * @param name the name of the field
736      * @return the field node
737      */
738     private static HierarchicalConfiguration.Node createFieldNode(String name)
739     {
740         HierarchicalConfiguration.Node fld = createNode("field", null);
741         fld.addChild(createNode("name", name));
742         return fld;
743     }
744 
745     /***
746      * Helper method for creating a configuration node.
747      * @param name the node's name
748      * @param value the node's value
749      * @return the new node
750      */
751     private static HierarchicalConfiguration.Node createNode(String name, Object value)
752     {
753         HierarchicalConfiguration.Node node = new HierarchicalConfiguration.Node(name);
754         node.setValue(value);
755         return node;
756     }
757 
758     /***
759      * A test visitor implementation for checking whether all visitor methods
760      * are correctly called.
761      */
762     static class CountVisitor extends HierarchicalConfiguration.NodeVisitor
763     {
764         public int beforeCount;
765 
766         public int afterCount;
767 
768         public void visitAfterChildren(Node node, ConfigurationKey key)
769         {
770             super.visitAfterChildren(node, key);
771             afterCount++;
772         }
773 
774         public void visitBeforeChildren(Node node, ConfigurationKey key)
775         {
776             super.visitBeforeChildren(node, key);
777             beforeCount++;
778         }
779     }
780 }