    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 }