001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.commons.configuration;
019:
020: import java.util.ArrayList;
021: import java.util.Collection;
022: import java.util.HashSet;
023: import java.util.Iterator;
024: import java.util.List;
025: import java.util.Set;
026:
027: import org.apache.commons.collections.CollectionUtils;
028: import org.apache.commons.configuration.HierarchicalConfiguration.Node;
029: import org.apache.commons.configuration.event.ConfigurationEvent;
030: import org.apache.commons.configuration.event.ConfigurationListener;
031: import org.apache.commons.configuration.tree.DefaultConfigurationNode;
032: import org.apache.commons.configuration.tree.DefaultExpressionEngine;
033: import org.apache.commons.configuration.tree.ExpressionEngine;
034:
035: import junit.framework.TestCase;
036:
037: /**
038: * Test class for HierarchicalConfiguration.
039: *
040: * @version $Id: TestHierarchicalConfiguration.java 525488 2007-04-04 10:46:33Z oheger $
041: */
042: public class TestHierarchicalConfiguration extends TestCase {
043: private static String[] tables = { "users", "documents" };
044:
045: private static String[][] fields = {
046: { "uid", "uname", "firstName", "lastName", "email" },
047: { "docid", "name", "creationDate", "authorID", "version" } };
048:
049: private HierarchicalConfiguration config;
050:
051: protected void setUp() throws Exception {
052: /**
053: * Initialize the configuration with the following structure:
054: *
055: * tables
056: * table
057: * name
058: * fields
059: * field
060: * name
061: * field
062: * name
063: */
064: config = new HierarchicalConfiguration();
065: HierarchicalConfiguration.Node nodeTables = createNode(
066: "tables", null);
067: for (int i = 0; i < tables.length; i++) {
068: HierarchicalConfiguration.Node nodeTable = createNode(
069: "table", null);
070: nodeTables.addChild(nodeTable);
071: HierarchicalConfiguration.Node nodeName = createNode(
072: "name", tables[i]);
073: nodeTable.addChild(nodeName);
074: HierarchicalConfiguration.Node nodeFields = createNode(
075: "fields", null);
076: nodeTable.addChild(nodeFields);
077:
078: for (int j = 0; j < fields[i].length; j++) {
079: nodeFields.addChild(createFieldNode(fields[i][j]));
080: }
081: }
082:
083: config.getRoot().addChild(nodeTables);
084: }
085:
086: public void testSetRoot() {
087: try {
088: config.setRoot(null);
089: fail("Could set null root node!");
090: } catch (IllegalArgumentException iex) {
091: //ok
092: }
093:
094: config.setRoot(new HierarchicalConfiguration.Node("test"));
095: assertTrue(config.isEmpty());
096: }
097:
098: public void testSetRootNode() {
099: config.setRootNode(new DefaultConfigurationNode("testNode"));
100: assertNotSame("Same root node", config.getRootNode(), config
101: .getRoot());
102: assertEquals("Wrong name of root node", "testNode", config
103: .getRoot().getName());
104:
105: config.setRootNode(new HierarchicalConfiguration.Node("test"));
106: assertSame("Wrong root node", config.getRootNode(), config
107: .getRoot());
108: }
109:
110: public void testSetRootNodeNull() {
111: try {
112: config.setRootNode(null);
113: fail("Could set null root node!");
114: } catch (IllegalArgumentException iex) {
115: //ok
116: }
117: }
118:
119: public void testIsEmpty() {
120: assertFalse(config.isEmpty());
121: HierarchicalConfiguration conf2 = new HierarchicalConfiguration();
122: assertTrue(conf2.isEmpty());
123: HierarchicalConfiguration.Node child1 = new HierarchicalConfiguration.Node(
124: "child1");
125: HierarchicalConfiguration.Node child2 = new HierarchicalConfiguration.Node(
126: "child2");
127: child1.addChild(child2);
128: conf2.getRoot().addChild(child1);
129: assertTrue(conf2.isEmpty());
130: }
131:
132: public void testGetProperty() {
133: assertNull(config.getProperty("tables.table.resultset"));
134: assertNull(config.getProperty("tables.table.fields.field"));
135:
136: Object prop = config
137: .getProperty("tables.table(0).fields.field.name");
138: assertNotNull(prop);
139: assertTrue(prop instanceof Collection);
140: assertEquals(5, ((Collection) prop).size());
141:
142: prop = config.getProperty("tables.table.fields.field.name");
143: assertNotNull(prop);
144: assertTrue(prop instanceof Collection);
145: assertEquals(10, ((Collection) prop).size());
146:
147: prop = config.getProperty("tables.table.fields.field(3).name");
148: assertNotNull(prop);
149: assertTrue(prop instanceof Collection);
150: assertEquals(2, ((Collection) prop).size());
151:
152: prop = config
153: .getProperty("tables.table(1).fields.field(2).name");
154: assertNotNull(prop);
155: assertEquals("creationDate", prop.toString());
156: }
157:
158: public void testSetProperty() {
159: config.setProperty("tables.table(0).name", "resources");
160: assertEquals("resources", config
161: .getString("tables.table(0).name"));
162: config.setProperty("tables.table.name", "tab1,tab2");
163: assertEquals("tab1", config.getString("tables.table(0).name"));
164: assertEquals("tab2", config.getString("tables.table(1).name"));
165:
166: config
167: .setProperty("test.items.item",
168: new int[] { 2, 4, 8, 16 });
169: assertEquals(3, config.getMaxIndex("test.items.item"));
170: assertEquals(8, config.getInt("test.items.item(2)"));
171: config.setProperty("test.items.item(2)", new Integer(6));
172: assertEquals(6, config.getInt("test.items.item(2)"));
173: config
174: .setProperty("test.items.item(2)",
175: new int[] { 7, 9, 11 });
176: assertEquals(5, config.getMaxIndex("test.items.item"));
177:
178: config.setProperty("test", Boolean.TRUE);
179: config.setProperty("test.items", "01/01/05");
180: assertEquals(5, config.getMaxIndex("test.items.item"));
181: assertTrue(config.getBoolean("test"));
182: assertEquals("01/01/05", config.getProperty("test.items"));
183:
184: config.setProperty("test.items.item", new Integer(42));
185: assertEquals(0, config.getMaxIndex("test.items.item"));
186: assertEquals(42, config.getInt("test.items.item"));
187: }
188:
189: public void testClearProperty() {
190: config.clearProperty("tables.table(0).fields.field(0).name");
191: assertEquals("uname", config
192: .getProperty("tables.table(0).fields.field(0).name"));
193: config.clearProperty("tables.table(0).name");
194: assertFalse(config.containsKey("tables.table(0).name"));
195: assertEquals("firstName", config
196: .getProperty("tables.table(0).fields.field(1).name"));
197: assertEquals("documents", config
198: .getProperty("tables.table.name"));
199: config.clearProperty("tables.table");
200: assertEquals("documents", config
201: .getProperty("tables.table.name"));
202:
203: config.addProperty("test", "first");
204: config.addProperty("test.level", "second");
205: config.clearProperty("test");
206: assertEquals("second", config.getString("test.level"));
207: assertFalse(config.containsKey("test"));
208: }
209:
210: public void testClearTree() {
211: Object prop = config
212: .getProperty("tables.table(0).fields.field.name");
213: assertNotNull(prop);
214: config.clearTree("tables.table(0).fields.field(3)");
215: prop = config.getProperty("tables.table(0).fields.field.name");
216: assertNotNull(prop);
217: assertTrue(prop instanceof Collection);
218: assertEquals(4, ((Collection) prop).size());
219:
220: config.clearTree("tables.table(0).fields");
221: assertNull(config
222: .getProperty("tables.table(0).fields.field.name"));
223: prop = config.getProperty("tables.table.fields.field.name");
224: assertNotNull(prop);
225: assertTrue(prop instanceof Collection);
226: assertEquals(5, ((Collection) prop).size());
227:
228: config.clearTree("tables.table(1)");
229: assertNull(config.getProperty("tables.table.fields.field.name"));
230: }
231:
232: /**
233: * Tests removing more complex node structures.
234: */
235: public void testClearTreeComplex() {
236: final int count = 5;
237: // create the structure
238: for (int idx = 0; idx < count; idx++) {
239: config.addProperty("indexList.index(-1)[@default]",
240: Boolean.FALSE);
241: config.addProperty("indexList.index[@name]", "test" + idx);
242: config.addProperty("indexList.index.dir", "testDir" + idx);
243: }
244: assertEquals("Wrong number of nodes", count - 1, config
245: .getMaxIndex("indexList.index[@name]"));
246:
247: // Remove a sub tree
248: boolean found = false;
249: for (int idx = 0; true; idx++) {
250: String name = config.getString("indexList.index(" + idx
251: + ")[@name]");
252: if (name == null) {
253: break;
254: }
255: if ("test3".equals(name)) {
256: assertEquals("Wrong dir", "testDir3", config
257: .getString("indexList.index(" + idx + ").dir"));
258: config.clearTree("indexList.index(" + idx + ")");
259: found = true;
260: }
261: }
262: assertTrue("Key to remove not found", found);
263: assertEquals("Wrong number of nodes after remove", count - 2,
264: config.getMaxIndex("indexList.index[@name]"));
265: assertEquals("Wrong number of dir nodes after remove",
266: count - 2, config.getMaxIndex("indexList.index.dir"));
267:
268: // Verify
269: for (int idx = 0; true; idx++) {
270: String name = config.getString("indexList.index(" + idx
271: + ")[@name]");
272: if (name == null) {
273: break;
274: }
275: if ("test3".equals(name)) {
276: fail("Key was not removed!");
277: }
278: }
279: }
280:
281: public void testContainsKey() {
282: assertTrue(config.containsKey("tables.table(0).name"));
283: assertTrue(config.containsKey("tables.table(1).name"));
284: assertFalse(config.containsKey("tables.table(2).name"));
285:
286: assertTrue(config
287: .containsKey("tables.table(0).fields.field.name"));
288: assertFalse(config.containsKey("tables.table(0).fields.field"));
289: config.clearTree("tables.table(0).fields");
290: assertFalse(config
291: .containsKey("tables.table(0).fields.field.name"));
292:
293: assertTrue(config.containsKey("tables.table.fields.field.name"));
294: }
295:
296: public void testGetKeys() {
297: List keys = new ArrayList();
298: for (Iterator it = config.getKeys(); it.hasNext();) {
299: keys.add(it.next());
300: }
301:
302: assertEquals(2, keys.size());
303: assertTrue(keys.contains("tables.table.name"));
304: assertTrue(keys.contains("tables.table.fields.field.name"));
305:
306: // test the order of the keys returned
307: config.addProperty("order.key1", "value1");
308: config.addProperty("order.key2", "value2");
309: config.addProperty("order.key3", "value3");
310:
311: Iterator it = config.getKeys("order");
312: assertEquals("1st key", "order.key1", it.next());
313: assertEquals("2nd key", "order.key2", it.next());
314: assertEquals("3rd key", "order.key3", it.next());
315: }
316:
317: public void testGetKeysString() {
318: // add some more properties to make it more interesting
319: config.addProperty("tables.table(0).fields.field(1).type",
320: "VARCHAR");
321: config.addProperty("tables.table(0)[@type]", "system");
322: config.addProperty("tables.table(0).size", "42");
323: config.addProperty("tables.table(0).fields.field(0).size",
324: "128");
325: config.addProperty("connections.connection.param.url", "url1");
326: config.addProperty("connections.connection.param.user", "me");
327: config
328: .addProperty("connections.connection.param.pwd",
329: "secret");
330: config.addProperty("connections.connection(-1).param.url",
331: "url2");
332: config.addProperty("connections.connection(1).param.user",
333: "guest");
334:
335: checkKeys("tables.table(1)", new String[] { "name",
336: "fields.field.name" });
337: checkKeys("tables.table(0)", new String[] { "name",
338: "fields.field.name", "tables.table(0)[@type]", "size",
339: "fields.field.type", "fields.field.size" });
340: checkKeys("connections.connection(0).param", new String[] {
341: "url", "user", "pwd" });
342: checkKeys("connections.connection(1).param", new String[] {
343: "url", "user" });
344: }
345:
346: public void testAddProperty() {
347: config.addProperty("tables.table(0).fields.field(-1).name",
348: "phone");
349: Object prop = config
350: .getProperty("tables.table(0).fields.field.name");
351: assertNotNull(prop);
352: assertTrue(prop instanceof Collection);
353: assertEquals(6, ((Collection) prop).size());
354:
355: config.addProperty("tables.table(0).fields.field.name", "fax");
356: prop = config.getProperty("tables.table.fields.field(5).name");
357: assertNotNull(prop);
358: assertTrue(prop instanceof List);
359: List list = (List) prop;
360: assertEquals("phone", list.get(0));
361: assertEquals("fax", list.get(1));
362:
363: config.addProperty("tables.table(-1).name", "config");
364: prop = config.getProperty("tables.table.name");
365: assertNotNull(prop);
366: assertTrue(prop instanceof Collection);
367: assertEquals(3, ((Collection) prop).size());
368: config.addProperty("tables.table(2).fields.field(0).name",
369: "cid");
370: config.addProperty("tables.table(2).fields.field(-1).name",
371: "confName");
372: prop = config.getProperty("tables.table(2).fields.field.name");
373: assertNotNull(prop);
374: assertTrue(prop instanceof Collection);
375: assertEquals(2, ((Collection) prop).size());
376: assertEquals("confName", config
377: .getProperty("tables.table(2).fields.field(1).name"));
378:
379: config.addProperty("connection.user", "scott");
380: config.addProperty("connection.passwd", "tiger");
381: assertEquals("tiger", config.getProperty("connection.passwd"));
382:
383: ConfigurationKey key = new ConfigurationKey();
384: key.append("tables").append("table").appendIndex(0);
385: key.appendAttribute("tableType");
386: config.addProperty(key.toString(), "system");
387: assertEquals("system", config.getProperty(key.toString()));
388:
389: try {
390: config.addProperty(".", "InvalidKey");
391: fail("Could add invalid key!");
392: } catch (IllegalArgumentException iex) {
393: //ok
394: }
395: }
396:
397: public void testGetMaxIndex() {
398: assertEquals(4, config
399: .getMaxIndex("tables.table(0).fields.field"));
400: assertEquals(4, config
401: .getMaxIndex("tables.table(1).fields.field"));
402: assertEquals(1, config.getMaxIndex("tables.table"));
403: assertEquals(1, config.getMaxIndex("tables.table.name"));
404: assertEquals(0, config.getMaxIndex("tables.table(0).name"));
405: assertEquals(0, config
406: .getMaxIndex("tables.table(1).fields.field(1)"));
407: assertEquals(-1, config.getMaxIndex("tables.table(2).fields"));
408:
409: int maxIdx = config
410: .getMaxIndex("tables.table(0).fields.field.name");
411: for (int i = 0; i <= maxIdx; i++) {
412: ConfigurationKey key = new ConfigurationKey(
413: "tables.table(0).fields");
414: key.append("field").appendIndex(i).append("name");
415: assertNotNull(config.getProperty(key.toString()));
416: }
417: }
418:
419: public void testSubset() {
420: // test the subset on the first table
421: Configuration subset = config.subset("tables.table(0)");
422: assertEquals(tables[0], subset.getProperty("name"));
423:
424: Object prop = subset.getProperty("fields.field.name");
425: assertNotNull(prop);
426: assertTrue(prop instanceof Collection);
427: assertEquals(5, ((Collection) prop).size());
428:
429: for (int i = 0; i < fields[0].length; i++) {
430: ConfigurationKey key = new ConfigurationKey();
431: key.append("fields").append("field").appendIndex(i);
432: key.append("name");
433: assertEquals(fields[0][i], subset.getProperty(key
434: .toString()));
435: }
436:
437: // test the subset on the second table
438: assertTrue("subset is not empty", config.subset(
439: "tables.table(2)").isEmpty());
440:
441: // test the subset on the fields
442: subset = config.subset("tables.table.fields.field");
443: prop = subset.getProperty("name");
444: assertTrue("prop is not a collection",
445: prop instanceof Collection);
446: assertEquals(10, ((Collection) prop).size());
447:
448: assertEquals(fields[0][0], subset.getProperty("name(0)"));
449:
450: // tset the subset on the field names
451: subset = config.subset("tables.table.fields.field.name");
452: assertTrue("subset is not empty", subset.isEmpty());
453: }
454:
455: /**
456: * Tests the configurationAt() method to obtain a configuration for a sub
457: * tree.
458: */
459: public void testConfigurationAt() {
460: HierarchicalConfiguration subConfig = config
461: .configurationAt("tables.table(1)");
462: assertEquals("Wrong table name", tables[1], subConfig
463: .getString("name"));
464: List lstFlds = subConfig.getList("fields.field.name");
465: assertEquals("Wrong number of fields", fields[1].length,
466: lstFlds.size());
467: for (int i = 0; i < fields[1].length; i++) {
468: assertEquals("Wrong field at position " + i, fields[1][i],
469: lstFlds.get(i));
470: }
471:
472: subConfig.setProperty("name", "testTable");
473: assertEquals("Change not visible in parent", "testTable",
474: config.getString("tables.table(1).name"));
475: config.setProperty("tables.table(1).fields.field(2).name",
476: "testField");
477: assertEquals("Change not visible in sub config", "testField",
478: subConfig.getString("fields.field(2).name"));
479: }
480:
481: /**
482: * Tests the configurationAt() method when the passed in key does not exist.
483: */
484: public void testConfigurationAtUnknownSubTree() {
485: try {
486: config.configurationAt("non.existing.key");
487: fail("Could obtain sub config for unknown key!");
488: } catch (IllegalArgumentException iex) {
489: // ok
490: }
491: }
492:
493: /**
494: * Tests the configurationAt() method when the passed in key selects
495: * multiple nodes. This should cause an exception.
496: */
497: public void testConfigurationAtMultipleNodes() {
498: try {
499: config.configurationAt("tables.table.name");
500: fail("Could create sub config with non unique key!");
501: } catch (IllegalArgumentException iex) {
502: // ok
503: }
504: }
505:
506: /**
507: * Tests the configurationsAt() method.
508: */
509: public void testConfigurationsAt() {
510: List lstFlds = config
511: .configurationsAt("tables.table(1).fields.field");
512: assertEquals("Wrong size of fields", fields[1].length, lstFlds
513: .size());
514: for (int i = 0; i < fields[1].length; i++) {
515: HierarchicalConfiguration sub = (HierarchicalConfiguration) lstFlds
516: .get(i);
517: assertEquals("Wrong field at position " + i, fields[1][i],
518: sub.getString("name"));
519: }
520: }
521:
522: /**
523: * Tests the configurationsAt() method when the passed in key does not
524: * select any sub nodes.
525: */
526: public void testConfigurationsAtEmpty() {
527: assertTrue("List is not empty", config.configurationsAt(
528: "unknown.key").isEmpty());
529: }
530:
531: public void testClone() {
532: Configuration copy = (Configuration) config.clone();
533: assertTrue(copy instanceof HierarchicalConfiguration);
534: checkContent(copy);
535: }
536:
537: /**
538: * Tests whether registered event handlers are handled correctly when a
539: * configuration is cloned. They should not be registered at the clone.
540: */
541: public void testCloneWithEventListeners() {
542: config.addConfigurationListener(new ConfigurationListener() {
543: public void configurationChanged(ConfigurationEvent event) {
544: // just a dummy
545: }
546: });
547: HierarchicalConfiguration copy = (HierarchicalConfiguration) config
548: .clone();
549: assertTrue("Event listener registered at clone", copy
550: .getConfigurationListeners().isEmpty());
551: }
552:
553: public void testAddNodes() {
554: Collection nodes = new ArrayList();
555: nodes.add(createFieldNode("birthDate"));
556: nodes.add(createFieldNode("lastLogin"));
557: nodes.add(createFieldNode("language"));
558: config.addNodes("tables.table(0).fields", nodes);
559: assertEquals(7, config
560: .getMaxIndex("tables.table(0).fields.field"));
561: assertEquals("birthDate", config
562: .getString("tables.table(0).fields.field(5).name"));
563: assertEquals("lastLogin", config
564: .getString("tables.table(0).fields.field(6).name"));
565: assertEquals("language", config
566: .getString("tables.table(0).fields.field(7).name"));
567: }
568:
569: /**
570: * Tests the addNodes() method when the provided key does not exist. In
571: * this case, a new node (or even a complete new branch) will be created.
572: */
573: public void testAddNodesForNonExistingKey() {
574: Collection nodes = new ArrayList();
575: nodes.add(createNode("usr", "scott"));
576: Node nd = createNode("pwd", "tiger");
577: nd.setAttribute(true);
578: nodes.add(nd);
579: config.addNodes("database.connection.settings", nodes);
580:
581: assertEquals("Usr node not found", "scott", config
582: .getString("database.connection.settings.usr"));
583: assertEquals("Pwd node not found", "tiger", config
584: .getString("database.connection.settings[@pwd]"));
585: }
586:
587: /**
588: * Tests the addNodes() method when the new nodes should be added to an
589: * attribute node. This is not allowed.
590: */
591: public void testAddNodesWithAttributeKey() {
592: Collection nodes = new ArrayList();
593: nodes.add(createNode("testNode", "yes"));
594: try {
595: config.addNodes("database.connection[@settings]", nodes);
596: fail("Could add nodes to an attribute node!");
597: } catch (IllegalArgumentException iex) {
598: //ok
599: }
600: }
601:
602: /**
603: * Tests removing children from a configuration node.
604: */
605: public void testNodeRemove() {
606: HierarchicalConfiguration.Node node = new HierarchicalConfiguration.Node(
607: "parent", "test");
608: assertFalse(node.hasChildren());
609: node.removeChildren(); // should have no effect
610: assertFalse(node.remove("child"));
611:
612: node.addChild(createNode("test", "test"));
613: assertTrue(node.hasChildren());
614: assertTrue(node.remove("test"));
615: assertFalse(node.hasChildren());
616:
617: for (int i = 0; i < 10; i++) {
618: node.addChild(createNode("child" + i, "test" + i));
619: }
620: assertTrue(node.hasChildren());
621: assertFalse(node.remove("child"));
622: assertTrue(node.remove("child2"));
623: assertTrue(node.getChildren("child2").isEmpty());
624:
625: HierarchicalConfiguration.Node child = createNode("child0",
626: "testChild");
627: assertFalse(node.remove(child));
628: node.addChild(child);
629: assertTrue(node.remove(child));
630: assertEquals(1, node.getChildren("child0").size());
631: assertEquals("test0", ((HierarchicalConfiguration.Node) node
632: .getChildren("child0").get(0)).getValue());
633:
634: assertTrue(node.remove("child0"));
635: assertFalse(node.remove(child));
636:
637: node.removeChildren();
638: assertTrue(node.getChildren().isEmpty());
639: assertFalse(node.remove(child));
640: }
641:
642: /**
643: * Tests the visitor mechanism.
644: */
645: public void testNodeVisitor() {
646: CountVisitor v = new CountVisitor();
647: config.getRoot().visit(v, null);
648: assertEquals(28, v.beforeCount);
649: assertEquals(v.beforeCount, v.afterCount);
650: }
651:
652: /**
653: * Tests setting a custom expression engine, which uses a slightly different
654: * syntax.
655: */
656: public void testSetExpressionEngine() {
657: config.setExpressionEngine(null);
658: assertNotNull("Expression engine is null", config
659: .getExpressionEngine());
660: assertSame("Default engine is not used",
661: HierarchicalConfiguration.getDefaultExpressionEngine(),
662: config.getExpressionEngine());
663:
664: config.setExpressionEngine(createAlternativeExpressionEngine());
665: checkAlternativeSyntax();
666: }
667:
668: /**
669: * Tests setting the default expression engine. This should impact all
670: * configuration instances that do not have their own engine.
671: */
672: public void testSetDefaultExpressionEngine() {
673: ExpressionEngine engineOld = HierarchicalConfiguration
674: .getDefaultExpressionEngine();
675: HierarchicalConfiguration
676: .setDefaultExpressionEngine(createAlternativeExpressionEngine());
677: checkAlternativeSyntax();
678: HierarchicalConfiguration.setDefaultExpressionEngine(engineOld);
679: }
680:
681: /**
682: * Tests setting the default expression engine to null. This should not be
683: * allowed.
684: */
685: public void testSetDefaultExpressionEngineNull() {
686: try {
687: HierarchicalConfiguration.setDefaultExpressionEngine(null);
688: fail("Could set default expression engine to null!");
689: } catch (IllegalArgumentException iex) {
690: // ok
691: }
692: }
693:
694: /**
695: * Tests the copy constructor.
696: */
697: public void testInitCopy() {
698: HierarchicalConfiguration copy = new HierarchicalConfiguration(
699: config);
700: checkContent(copy);
701: }
702:
703: /**
704: * Tests whether the nodes of a copied configuration are independent from
705: * the source configuration.
706: */
707: public void testInitCopyUpdate() {
708: HierarchicalConfiguration copy = new HierarchicalConfiguration(
709: config);
710: config.setProperty("tables.table(0).name", "NewTable");
711: checkContent(copy);
712: }
713:
714: /**
715: * Tests interpolation facilities.
716: */
717: public void testInterpolation() {
718: config.addProperty("base.dir", "/home/foo");
719: config.addProperty("test.absolute.dir.dir1",
720: "${base.dir}/path1");
721: config.addProperty("test.absolute.dir.dir2",
722: "${base.dir}/path2");
723: config.addProperty("test.absolute.dir.dir3",
724: "${base.dir}/path3");
725:
726: Configuration sub = config.subset("test.absolute.dir");
727: for (int i = 1; i < 4; i++) {
728: assertEquals("Wrong interpolation in parent",
729: "/home/foo/path" + i, config
730: .getString("test.absolute.dir.dir" + i));
731: assertEquals("Wrong interpolation in subnode",
732: "/home/foo/path" + i, sub.getString("dir" + i));
733: }
734: }
735:
736: /**
737: * Tests the copy constructor when a null reference is passed.
738: */
739: public void testInitCopyNull() {
740: HierarchicalConfiguration copy = new HierarchicalConfiguration(
741: null);
742: assertTrue("Configuration not empty", copy.isEmpty());
743: }
744:
745: /**
746: * Helper method for testing the getKeys(String) method.
747: *
748: * @param prefix the key to pass into getKeys()
749: * @param expected the expected result
750: */
751: private void checkKeys(String prefix, String[] expected) {
752: Set values = new HashSet();
753: for (int i = 0; i < expected.length; i++) {
754: values.add((expected[i].startsWith(prefix)) ? expected[i]
755: : prefix + "." + expected[i]);
756: }
757:
758: Iterator itKeys = config.getKeys(prefix);
759: while (itKeys.hasNext()) {
760: String key = (String) itKeys.next();
761: if (!values.contains(key)) {
762: fail("Found unexpected key: " + key);
763: } else {
764: values.remove(key);
765: }
766: }
767:
768: assertTrue("Remaining keys " + values, values.isEmpty());
769: }
770:
771: /**
772: * Helper method for checking keys using an alternative syntax.
773: */
774: private void checkAlternativeSyntax() {
775: assertNull(config.getProperty("tables/table/resultset"));
776: assertNull(config.getProperty("tables/table/fields/field"));
777:
778: Object prop = config
779: .getProperty("tables/table[0]/fields/field/name");
780: assertNotNull(prop);
781: assertTrue(prop instanceof Collection);
782: assertEquals(5, ((Collection) prop).size());
783:
784: prop = config.getProperty("tables/table/fields/field/name");
785: assertNotNull(prop);
786: assertTrue(prop instanceof Collection);
787: assertEquals(10, ((Collection) prop).size());
788:
789: prop = config.getProperty("tables/table/fields/field[3]/name");
790: assertNotNull(prop);
791: assertTrue(prop instanceof Collection);
792: assertEquals(2, ((Collection) prop).size());
793:
794: prop = config
795: .getProperty("tables/table[1]/fields/field[2]/name");
796: assertNotNull(prop);
797: assertEquals("creationDate", prop.toString());
798:
799: Set keys = new HashSet();
800: CollectionUtils.addAll(keys, config.getKeys());
801: assertEquals("Wrong number of defined keys", 2, keys.size());
802: assertTrue("Key not found", keys.contains("tables/table/name"));
803: assertTrue("Key not found", keys
804: .contains("tables/table/fields/field/name"));
805: }
806:
807: /**
808: * Checks the content of the passed in configuration object. Used by some
809: * tests that copy a configuration.
810: *
811: * @param c the configuration to check
812: */
813: private void checkContent(Configuration c) {
814: for (int i = 0; i < tables.length; i++) {
815: assertEquals(tables[i], c.getString("tables.table(" + i
816: + ").name"));
817: for (int j = 0; j < fields[i].length; j++) {
818: assertEquals(fields[i][j], c.getString("tables.table("
819: + i + ").fields.field(" + j + ").name"));
820: }
821: }
822: }
823:
824: private ExpressionEngine createAlternativeExpressionEngine() {
825: DefaultExpressionEngine engine = new DefaultExpressionEngine();
826: engine.setPropertyDelimiter("/");
827: engine.setIndexStart("[");
828: engine.setIndexEnd("]");
829: return engine;
830: }
831:
832: /**
833: * Helper method for creating a field node with its children.
834: *
835: * @param name the name of the field
836: * @return the field node
837: */
838: private static HierarchicalConfiguration.Node createFieldNode(
839: String name) {
840: HierarchicalConfiguration.Node fld = createNode("field", null);
841: fld.addChild(createNode("name", name));
842: return fld;
843: }
844:
845: /**
846: * Helper method for creating a configuration node.
847: * @param name the node's name
848: * @param value the node's value
849: * @return the new node
850: */
851: private static HierarchicalConfiguration.Node createNode(
852: String name, Object value) {
853: HierarchicalConfiguration.Node node = new HierarchicalConfiguration.Node(
854: name);
855: node.setValue(value);
856: return node;
857: }
858:
859: /**
860: * A test visitor implementation for checking whether all visitor methods
861: * are correctly called.
862: */
863: static class CountVisitor extends
864: HierarchicalConfiguration.NodeVisitor {
865: public int beforeCount;
866:
867: public int afterCount;
868:
869: public void visitAfterChildren(Node node, ConfigurationKey key) {
870: super .visitAfterChildren(node, key);
871: afterCount++;
872: }
873:
874: public void visitBeforeChildren(Node node, ConfigurationKey key) {
875: super.visitBeforeChildren(node, key);
876: beforeCount++;
877: }
878: }
879: }
|