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
9
* http://www.apache.org/licenses/LICENSE-2.0
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.
17
package org.apache.commons.configuration.tree;
19
import static org.junit.Assert.assertEquals;
20
import static org.junit.Assert.assertFalse;
21
import static org.junit.Assert.assertSame;
22
import static org.junit.Assert.assertTrue;
24
import java.util.Iterator;
25
import java.util.List;
27
import org.junit.Before;
28
import org.junit.Test;
31
* Test class for DefaultExpressionEngine.
34
* href="http://commons.apache.org/configuration/team-list.html">Commons
35
* Configuration team</a>
36
* @version $Id: TestDefaultExpressionEngine.java 1225918 2011-12-30 20:54:47Z oheger $
38
public class TestDefaultExpressionEngine
40
/** Stores the names of the test nodes representing tables. */
41
private static String[] tables =
42
{ "users", "documents"};
44
/** Stores the types of the test table nodes. */
45
private static String[] tabTypes =
46
{ "system", "application"};
48
/** Test data fields for the node hierarchy. */
49
private static String[][] fields =
51
{ "uid", "uname", "firstName", "lastName", "email"},
52
{ "docid", "name", "creationDate", "authorID", "version"}};
54
/** The object to be tested. */
55
DefaultExpressionEngine engine;
57
/** The root of a hierarchy with configuration nodes. */
58
ConfigurationNode root;
61
public void setUp() throws Exception
64
engine = new DefaultExpressionEngine();
68
* Tests some simple queries.
71
public void testQueryKeys()
73
checkKey("tables.table.name", "name", 2);
74
checkKey("tables.table.fields.field.name", "name", 10);
75
checkKey("tables.table[@type]", "type", 2);
76
checkKey("tables.table(0).fields.field.name", "name", 5);
77
checkKey("tables.table(1).fields.field.name", "name", 5);
78
checkKey("tables.table.fields.field(1).name", "name", 2);
82
* Performs some queries and evaluates the values of the result nodes.
85
public void testQueryNodes()
87
for (int i = 0; i < tables.length; i++)
89
checkKeyValue("tables.table(" + i + ").name", "name", tables[i]);
90
checkKeyValue("tables.table(" + i + ")[@type]", "type", tabTypes[i]);
92
for (int j = 0; j < fields[i].length; j++)
94
checkKeyValue("tables.table(" + i + ").fields.field(" + j
95
+ ").name", "name", fields[i][j]);
101
* Tests querying keys that do not exist.
104
public void testQueryNonExistingKeys()
106
checkKey("tables.tablespace.name", null, 0);
107
checkKey("tables.table(2).name", null, 0);
108
checkKey("a complete unknown key", null, 0);
109
checkKey("tables.table(0).fields.field(-1).name", null, 0);
110
checkKey("tables.table(0).fields.field(28).name", null, 0);
111
checkKey("tables.table(0).fields.field().name", null, 0);
112
checkKey("connection.settings.usr.name", null, 0);
116
* Tests querying nodes whose names contain a delimiter.
119
public void testQueryEscapedKeys()
121
checkKeyValue("connection..settings.usr..name", "usr.name", "scott");
122
checkKeyValue("connection..settings.usr..pwd", "usr.pwd", "tiger");
126
* Tests some queries when the same delimiter is used for properties and
130
public void testQueryAttributeEmulation()
132
engine.setAttributeEnd(null);
133
engine.setAttributeStart(engine.getPropertyDelimiter());
134
checkKeyValue("tables.table(0).name", "name", tables[0]);
135
checkKeyValue("tables.table(0).type", "type", tabTypes[0]);
136
checkKey("tables.table.type", "type", 2);
140
* Tests accessing the root node.
143
public void testQueryRootNode()
145
List<ConfigurationNode> nodes = checkKey(null, null, 1);
146
assertSame("Root node not found", root, nodes.get(0));
147
nodes = checkKey("", null, 1);
148
assertSame("Root node not found", root, nodes.get(0));
149
checkKeyValue("[@test]", "test", "true");
153
* Tests a different query syntax. Sets other strings for the typical tokens
154
* used by the expression engine.
157
public void testQueryAlternativeSyntax()
159
setUpAlternativeSyntax();
160
checkKeyValue("tables/table[1]/name", "name", tables[1]);
161
checkKeyValue("tables/table[0]@type", "type", tabTypes[0]);
162
checkKeyValue("@test", "test", "true");
163
checkKeyValue("connection.settings/usr.name", "usr.name", "scott");
167
* Tests obtaining keys for nodes.
170
public void testNodeKey()
172
ConfigurationNode node = root.getChild(0);
173
assertEquals("Invalid name for descendant of root", "tables", engine
175
assertEquals("Parent key not respected", "test.tables", engine.nodeKey(
177
assertEquals("Full parent key not taken into account",
178
"a.full.parent.key.tables", engine.nodeKey(node,
179
"a.full.parent.key"));
183
* Tests obtaining keys when the root node is involved.
186
public void testNodeKeyWithRoot()
188
assertEquals("Wrong name for root noot", "", engine.nodeKey(root, null));
189
assertEquals("Null name not detected", "test", engine.nodeKey(root,
194
* Tests obtaining keys for attribute nodes.
197
public void testNodeKeyWithAttribute()
199
ConfigurationNode node = root.getChild(0).getChild(0).getAttribute(0);
200
assertEquals("Wrong attribute node", "type", node.getName());
201
assertEquals("Wrong attribute key", "tables.table[@type]", engine
202
.nodeKey(node, "tables.table"));
203
assertEquals("Wrong key for root attribute", "[@test]", engine.nodeKey(
204
root.getAttribute(0), ""));
208
* Tests obtaining keys for nodes that contain the delimiter character.
211
public void testNodeKeyWithEscapedDelimiters()
213
ConfigurationNode node = root.getChild(1);
214
assertEquals("Wrong escaped key", "connection..settings", engine
216
assertEquals("Wrong complex escaped key",
217
"connection..settings.usr..name", engine.nodeKey(node
218
.getChild(0), engine.nodeKey(node, "")));
222
* Tests obtaining node keys when a different syntax is set.
225
public void testNodeKeyWithAlternativeSyntax()
227
setUpAlternativeSyntax();
228
assertEquals("Wrong child key", "tables/table", engine.nodeKey(root
229
.getChild(0).getChild(0), "tables"));
230
assertEquals("Wrong attribute key", "@test", engine.nodeKey(root
231
.getAttribute(0), ""));
233
engine.setAttributeStart(engine.getPropertyDelimiter());
234
assertEquals("Wrong attribute key", "/test", engine.nodeKey(root
235
.getAttribute(0), ""));
239
* Tests adding direct child nodes to the existing hierarchy.
242
public void testPrepareAddDirectly()
244
NodeAddData data = engine.prepareAdd(root, "newNode");
245
assertSame("Wrong parent node", root, data.getParent());
246
assertTrue("Path nodes available", data.getPathNodes().isEmpty());
247
assertEquals("Wrong name of new node", "newNode", data.getNewNodeName());
248
assertFalse("New node is an attribute", data.isAttribute());
250
data = engine.prepareAdd(root, "tables.table.fields.field.name");
251
assertEquals("Wrong name of new node", "name", data.getNewNodeName());
252
assertTrue("Path nodes available", data.getPathNodes().isEmpty());
253
assertEquals("Wrong parent node", "field", data.getParent().getName());
254
ConfigurationNode nd = data.getParent().getChild(0);
255
assertEquals("Field has no name node", "name", nd.getName());
256
assertEquals("Incorrect name", "version", nd.getValue());
260
* Tests adding when indices are involved.
263
public void testPrepareAddWithIndex()
265
NodeAddData data = engine
266
.prepareAdd(root, "tables.table(0).tableSpace");
267
assertEquals("Wrong name of new node", "tableSpace", data
269
assertTrue("Path nodes available", data.getPathNodes().isEmpty());
270
assertEquals("Wrong type of parent node", "table", data.getParent()
272
ConfigurationNode node = data.getParent().getChild(0);
273
assertEquals("Wrong table", tables[0], node.getValue());
275
data = engine.prepareAdd(root, "tables.table(1).fields.field(2).alias");
276
assertEquals("Wrong name of new node", "alias", data.getNewNodeName());
277
assertEquals("Wrong type of parent node", "field", data.getParent()
279
assertEquals("Wrong field node", "creationDate", data.getParent()
280
.getChild(0).getValue());
284
* Tests adding new attributes.
287
public void testPrepareAddAttribute()
289
NodeAddData data = engine.prepareAdd(root,
290
"tables.table(0)[@tableSpace]");
291
assertEquals("Wrong table node", tables[0], data.getParent()
292
.getChild(0).getValue());
293
assertEquals("Wrong name of new node", "tableSpace", data
295
assertTrue("Attribute not detected", data.isAttribute());
296
assertTrue("Path nodes available", data.getPathNodes().isEmpty());
298
data = engine.prepareAdd(root, "[@newAttr]");
299
assertSame("Root node is not parent", root, data.getParent());
300
assertEquals("Wrong name of new node", "newAttr", data.getNewNodeName());
301
assertTrue("Attribute not detected", data.isAttribute());
305
* Tests add operations where complete paths are added.
308
public void testPrepareAddWithPath()
310
NodeAddData data = engine.prepareAdd(root,
311
"tables.table(1).fields.field(-1).name");
312
assertEquals("Wrong name of new node", "name", data.getNewNodeName());
313
checkNodePath(data, new String[]
315
assertEquals("Wrong type of parent node", "fields", data.getParent()
318
data = engine.prepareAdd(root, "tables.table(-1).name");
319
assertEquals("Wrong name of new node", "name", data.getNewNodeName());
320
checkNodePath(data, new String[]
322
assertEquals("Wrong type of parent node", "tables", data.getParent()
325
data = engine.prepareAdd(root, "a.complete.new.path");
326
assertEquals("Wrong name of new node", "path", data.getNewNodeName());
327
checkNodePath(data, new String[]
328
{ "a", "complete", "new"});
329
assertSame("Root is not parent", root, data.getParent());
333
* Tests add operations when property and attribute delimiters are equal.
334
* Then it is not possible to add new attribute nodes.
337
public void testPrepareAddWithSameAttributeDelimiter()
339
engine.setAttributeEnd(null);
340
engine.setAttributeStart(engine.getPropertyDelimiter());
342
NodeAddData data = engine.prepareAdd(root, "tables.table(0).test");
343
assertEquals("Wrong name of new node", "test", data.getNewNodeName());
344
assertFalse("New node is an attribute", data.isAttribute());
345
assertEquals("Wrong type of parent node", "table", data.getParent()
348
data = engine.prepareAdd(root, "a.complete.new.path");
349
assertFalse("New node is an attribute", data.isAttribute());
350
checkNodePath(data, new String[]
351
{ "a", "complete", "new"});
355
* Tests add operations when an alternative syntax is set.
358
public void testPrepareAddWithAlternativeSyntax()
360
setUpAlternativeSyntax();
361
NodeAddData data = engine.prepareAdd(root, "tables/table[0]/test");
362
assertEquals("Wrong name of new node", "test", data.getNewNodeName());
363
assertFalse("New node is attribute", data.isAttribute());
364
assertEquals("Wrong parent node", tables[0], data.getParent().getChild(
367
data = engine.prepareAdd(root, "a/complete/new/path@attr");
368
assertEquals("Wrong name of new attribute", "attr", data
370
checkNodePath(data, new String[]
371
{ "a", "complete", "new", "path"});
372
assertSame("Root is not parent", root, data.getParent());
376
* Tests using invalid keys, e.g. if something should be added to
379
@Test(expected = IllegalArgumentException.class)
380
public void testPrepareAddInvalidKey()
382
engine.prepareAdd(root, "tables.table(0)[@type].new");
385
@Test(expected = IllegalArgumentException.class)
386
public void testPrepareAddInvalidKeyAttribute()
390
"a.complete.new.path.with.an[@attribute].at.a.non.allowed[@position]");
393
@Test(expected = IllegalArgumentException.class)
394
public void testPrepareAddNullKey()
396
engine.prepareAdd(root, null);
399
@Test(expected = IllegalArgumentException.class)
400
public void testPrepareAddEmptyKey()
402
engine.prepareAdd(root, "");
406
* Creates a node hierarchy for testing that consists of tables, their
407
* fields, and some additional data:
420
* @return the root of the test node hierarchy
422
protected ConfigurationNode setUpNodes()
424
DefaultConfigurationNode rootNode = new DefaultConfigurationNode();
426
DefaultConfigurationNode nodeTables = new DefaultConfigurationNode(
428
rootNode.addChild(nodeTables);
429
for (int i = 0; i < tables.length; i++)
431
DefaultConfigurationNode nodeTable = new DefaultConfigurationNode(
433
nodeTables.addChild(nodeTable);
434
nodeTable.addChild(new DefaultConfigurationNode("name", tables[i]));
435
nodeTable.addAttribute(new DefaultConfigurationNode("type",
437
DefaultConfigurationNode nodeFields = new DefaultConfigurationNode(
439
nodeTable.addChild(nodeFields);
441
for (int j = 0; j < fields[i].length; j++)
443
nodeFields.addChild(createFieldNode(fields[i][j]));
447
DefaultConfigurationNode nodeConn = new DefaultConfigurationNode(
448
"connection.settings");
449
rootNode.addChild(nodeConn);
450
nodeConn.addChild(new DefaultConfigurationNode("usr.name", "scott"));
451
nodeConn.addChild(new DefaultConfigurationNode("usr.pwd", "tiger"));
452
rootNode.addAttribute(new DefaultConfigurationNode("test", "true"));
458
* Configures the expression engine to use a different syntax.
460
private void setUpAlternativeSyntax()
462
engine.setAttributeEnd(null);
463
engine.setAttributeStart("@");
464
engine.setPropertyDelimiter("/");
465
engine.setEscapedDelimiter(null);
466
engine.setIndexStart("[");
467
engine.setIndexEnd("]");
471
* Helper method for checking the evaluation of a key. Queries the
472
* expression engine and tests if the expected results are returned.
475
* @param name the name of the nodes to be returned
476
* @param count the number of expected result nodes
477
* @return the list with the results of the query
479
private List<ConfigurationNode> checkKey(String key, String name, int count)
481
List<ConfigurationNode> nodes = engine.query(root, key);
482
assertEquals("Wrong number of result nodes for key " + key, count,
484
for (Iterator<ConfigurationNode> it = nodes.iterator(); it.hasNext();)
486
assertEquals("Wrong result node for key " + key, name,
487
it.next().getName());
493
* Helper method for checking the value of a node specified by the given
494
* key. This method evaluates the key and checks whether the resulting node
495
* has the expected value.
498
* @param name the expected name of the result node
499
* @param value the expected value of the result node
501
private void checkKeyValue(String key, String name, String value)
503
List<ConfigurationNode> nodes = checkKey(key, name, 1);
504
assertEquals("Wrong value for key " + key, value,
505
nodes.get(0).getValue());
509
* Helper method for checking the path of an add operation.
511
* @param data the add data object
512
* @param expected the expected path nodes
514
private void checkNodePath(NodeAddData data, String[] expected)
516
assertEquals("Wrong number of path nodes", expected.length, data
517
.getPathNodes().size());
518
Iterator<String> it = data.getPathNodes().iterator();
519
for (int i = 0; i < expected.length; i++)
521
assertEquals("Wrong path node " + i, expected[i], it.next());
526
* Helper method for creating a field node with its children for the test
529
* @param name the name of the field
530
* @return the field node
532
private static ConfigurationNode createFieldNode(String name)
534
DefaultConfigurationNode nodeField = new DefaultConfigurationNode(
536
nodeField.addChild(new DefaultConfigurationNode("name", name));