1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.configuration;
18
19 import java.util.HashSet;
20 import java.util.List;
21 import java.util.NoSuchElementException;
22 import java.util.Set;
23
24 import org.apache.commons.collections.CollectionUtils;
25 import org.apache.commons.configuration.tree.ConfigurationNode;
26 import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine;
27
28 import junit.framework.TestCase;
29
30 /***
31 * Test case for SubnodeConfiguration.
32 *
33 * @author Oliver Heger
34 * @version $Id: TestSubnodeConfiguration.java 439648 2006-09-02 20:42:10Z oheger $
35 */
36 public class TestSubnodeConfiguration extends TestCase
37 {
38 /*** An array with names of tables (test data). */
39 private static final String[] TABLE_NAMES =
40 { "documents", "users" };
41
42 /*** An array with the fields of the test tables (test data). */
43 private static final String[][] TABLE_FIELDS =
44 {
45 { "docid", "docname", "author", "dateOfCreation", "version", "size" },
46 { "userid", "uname", "firstName", "lastName" } };
47
48 /*** The parent configuration. */
49 HierarchicalConfiguration parent;
50
51 /*** The subnode configuration to be tested. */
52 SubnodeConfiguration config;
53
54 /*** Stores the root node of the subnode config. */
55 ConfigurationNode subnode;
56
57 /*** Stores a counter for the created nodes. */
58 int nodeCounter;
59
60 protected void setUp() throws Exception
61 {
62 super.setUp();
63 parent = setUpParentConfig();
64 nodeCounter = 0;
65 }
66
67 /***
68 * Tests creation of a subnode config.
69 */
70 public void testInitSubNodeConfig()
71 {
72 setUpSubnodeConfig();
73 assertSame("Wrong root node in subnode", getSubnodeRoot(parent), config
74 .getRoot());
75 assertSame("Wrong parent config", parent, config.getParent());
76 }
77
78 /***
79 * Tests constructing a subnode configuration with a null parent. This
80 * should cause an exception.
81 */
82 public void testInitSubNodeConfigWithNullParent()
83 {
84 try
85 {
86 config = new SubnodeConfiguration(null, getSubnodeRoot(parent));
87 fail("Could set a null parent config!");
88 }
89 catch (IllegalArgumentException iex)
90 {
91
92 }
93 }
94
95 /***
96 * Tests constructing a subnode configuration with a null root node. This
97 * should cause an exception.
98 */
99 public void testInitSubNodeConfigWithNullNode()
100 {
101 try
102 {
103 config = new SubnodeConfiguration(parent, null);
104 fail("Could set a null root node!");
105 }
106 catch (IllegalArgumentException iex)
107 {
108
109 }
110 }
111
112 /***
113 * Tests if properties of the sub node can be accessed.
114 */
115 public void testGetProperties()
116 {
117 setUpSubnodeConfig();
118 assertEquals("Wrong table name", TABLE_NAMES[0], config
119 .getString("name"));
120 List fields = config.getList("fields.field.name");
121 assertEquals("Wrong number of fields", TABLE_FIELDS[0].length, fields
122 .size());
123 for (int i = 0; i < TABLE_FIELDS[0].length; i++)
124 {
125 assertEquals("Wrong field at position " + i, TABLE_FIELDS[0][i],
126 fields.get(i));
127 }
128 }
129
130 /***
131 * Tests setting of properties in both the parent and the subnode
132 * configuration and whether the changes are visible to each other.
133 */
134 public void testSetProperty()
135 {
136 setUpSubnodeConfig();
137 config.setProperty(null, "testTable");
138 config.setProperty("name", TABLE_NAMES[0] + "_tested");
139 assertEquals("Root value was not set", "testTable", parent
140 .getString("tables.table(0)"));
141 assertEquals("Table name was not changed", TABLE_NAMES[0] + "_tested",
142 parent.getString("tables.table(0).name"));
143
144 parent.setProperty("tables.table(0).fields.field(1).name", "testField");
145 assertEquals("Field name was not changed", "testField", config
146 .getString("fields.field(1).name"));
147 }
148
149 /***
150 * Tests adding of properties.
151 */
152 public void testAddProperty()
153 {
154 setUpSubnodeConfig();
155 config.addProperty("[@table-type]", "test");
156 assertEquals("parent.createNode() was not called", 1, nodeCounter);
157 assertEquals("Attribute not set", "test", parent
158 .getString("tables.table(0)[@table-type]"));
159
160 parent.addProperty("tables.table(0).fields.field(-1).name", "newField");
161 List fields = config.getList("fields.field.name");
162 assertEquals("New field was not added", TABLE_FIELDS[0].length + 1,
163 fields.size());
164 assertEquals("Wrong last field", "newField", fields
165 .get(fields.size() - 1));
166 }
167
168 /***
169 * Tests listing the defined keys.
170 */
171 public void testGetKeys()
172 {
173 setUpSubnodeConfig();
174 Set keys = new HashSet();
175 CollectionUtils.addAll(keys, config.getKeys());
176 assertEquals("Incorrect number of keys", 2, keys.size());
177 assertTrue("Key 1 not contained", keys.contains("name"));
178 assertTrue("Key 2 not contained", keys.contains("fields.field.name"));
179 }
180
181 /***
182 * Tests setting the exception on missing flag. The subnode config obtains
183 * this flag from its parent.
184 */
185 public void testSetThrowExceptionOnMissing()
186 {
187 parent.setThrowExceptionOnMissing(true);
188 setUpSubnodeConfig();
189 assertTrue("Exception flag not fetchted from parent", config
190 .isThrowExceptionOnMissing());
191 try
192 {
193 config.getString("non existing key");
194 fail("Could fetch non existing key!");
195 }
196 catch (NoSuchElementException nex)
197 {
198
199 }
200
201 config.setThrowExceptionOnMissing(false);
202 assertTrue("Exception flag reset on parent", parent
203 .isThrowExceptionOnMissing());
204 }
205
206 /***
207 * Tests handling of the delimiter parsing disabled flag. This is shared
208 * with the parent, too.
209 */
210 public void testSetDelimiterParsingDisabled()
211 {
212 parent.setDelimiterParsingDisabled(true);
213 setUpSubnodeConfig();
214 parent.setDelimiterParsingDisabled(false);
215 assertTrue("Delimiter parsing flag was not received from parent",
216 config.isDelimiterParsingDisabled());
217 config.addProperty("newProp", "test1,test2,test3");
218 assertEquals("New property was splitted", "test1,test2,test3", parent
219 .getString("tables.table(0).newProp"));
220 parent.setDelimiterParsingDisabled(true);
221 config.setDelimiterParsingDisabled(false);
222 assertTrue("Delimiter parsing flag was reset on parent", parent
223 .isDelimiterParsingDisabled());
224 }
225
226 /***
227 * Tests manipulating the list delimiter. This piece of data is derived from
228 * the parent.
229 */
230 public void testSetListDelimiter()
231 {
232 parent.setListDelimiter('/');
233 setUpSubnodeConfig();
234 parent.setListDelimiter(';');
235 assertEquals("List delimiter not obtained from parent", '/', config
236 .getListDelimiter());
237 config.addProperty("newProp", "test1,test2/test3");
238 assertEquals("List was incorrectly splitted", "test1,test2", parent
239 .getString("tables.table(0).newProp"));
240 config.setListDelimiter(',');
241 assertEquals("List delimiter changed on parent", ';', parent
242 .getListDelimiter());
243 }
244
245 /***
246 * Tests changing the expression engine.
247 */
248 public void testSetExpressionEngine()
249 {
250 parent.setExpressionEngine(new XPathExpressionEngine());
251 setUpSubnodeConfig();
252 assertEquals("Wrong field name", TABLE_FIELDS[0][1], config
253 .getString("fields/field[2]/name"));
254 Set keys = new HashSet();
255 CollectionUtils.addAll(keys, config.getKeys());
256 assertEquals("Wrong number of keys", 2, keys.size());
257 assertTrue("Key 1 not contained", keys.contains("name"));
258 assertTrue("Key 2 not contained", keys.contains("fields/field/name"));
259 config.setExpressionEngine(null);
260 assertTrue("Expression engine reset on parent", parent
261 .getExpressionEngine() instanceof XPathExpressionEngine);
262 }
263
264 /***
265 * Tests the configurationAt() method.
266 */
267 public void testConfiguarationAt()
268 {
269 setUpSubnodeConfig();
270 SubnodeConfiguration sub2 = (SubnodeConfiguration) config
271 .configurationAt("fields.field(1)");
272 assertEquals("Wrong value of property", TABLE_FIELDS[0][1], sub2
273 .getString("name"));
274 assertEquals("Wrong parent", config.getParent(), sub2.getParent());
275 }
276
277 /***
278 * Tests interpolation features. The subnode config should use its parent
279 * for interpolation.
280 */
281 public void testInterpolation()
282 {
283 parent.addProperty("tablespaces.tablespace.name", "default");
284 parent.addProperty("tablespaces.tablespace(-1).name", "test");
285 parent.addProperty("tables.table(0).tablespace",
286 "${tablespaces.tablespace(0).name}");
287 assertEquals("Wrong interpolated tablespace", "default", parent
288 .getString("tables.table(0).tablespace"));
289
290 setUpSubnodeConfig();
291 assertEquals("Wrong interpolated tablespace in subnode", "default",
292 config.getString("tablespace"));
293 }
294
295 /***
296 * Initializes the parent configuration. This method creates the typical
297 * structure of tables and fields nodes.
298 *
299 * @return the parent configuration
300 */
301 protected HierarchicalConfiguration setUpParentConfig()
302 {
303 HierarchicalConfiguration conf = new HierarchicalConfiguration()
304 {
305
306
307 protected Node createNode(String name)
308 {
309 nodeCounter++;
310 return super.createNode(name);
311 }
312 };
313 for (int i = 0; i < TABLE_NAMES.length; i++)
314 {
315 conf.addProperty("tables.table(-1).name", TABLE_NAMES[i]);
316 for (int j = 0; j < TABLE_FIELDS[i].length; j++)
317 {
318 conf.addProperty("tables.table.fields.field(-1).name",
319 TABLE_FIELDS[i][j]);
320 }
321 }
322 return conf;
323 }
324
325 /***
326 * Returns the root node for the subnode config. This method returns the
327 * first table node.
328 *
329 * @param conf the parent config
330 * @return the root node for the subnode config
331 */
332 protected ConfigurationNode getSubnodeRoot(HierarchicalConfiguration conf)
333 {
334 ConfigurationNode root = conf.getRoot();
335 return root.getChild(0).getChild(0);
336 }
337
338 /***
339 * Performs a standard initialization of the subnode config to test.
340 */
341 protected void setUpSubnodeConfig()
342 {
343 config = new SubnodeConfiguration(parent, getSubnodeRoot(parent));
344 }
345 }