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: package org.apache.commons.configuration.tree;
018:
019: import java.util.Iterator;
020: import java.util.List;
021: import java.util.StringTokenizer;
022:
023: import junit.framework.TestCase;
024:
025: /**
026: * Test class for DefaultConfigurationNode.
027: *
028: * @author Oliver Heger
029: */
030: public class TestDefaultConfigurationNode extends TestCase {
031: /** Constant array for the field names. */
032: private static final String[] FIELD_NAMES = { "UID", "NAME",
033: "FIRSTNAME", "LASTLOGIN" };
034:
035: /** Constant array for the field data types. */
036: private static final String[] FIELD_TYPES = { "long", "string",
037: "string", "date" };
038:
039: /** Constant array for additional field attributes. */
040: private static final String[] FIELD_ATTRS = { "primarykey,unique",
041: "notnull", "notnull", null };
042:
043: /** The node to be tested. */
044: DefaultConfigurationNode node;
045:
046: protected void setUp() throws Exception {
047: super .setUp();
048: node = new DefaultConfigurationNode();
049: node.setName("table");
050: node.setReference("TestReference");
051: node
052: .addAttribute(new DefaultConfigurationNode("type",
053: "system"));
054: node.addChild(new DefaultConfigurationNode("name", "users"));
055:
056: // Add nodes for the table's fields
057: for (int i = 0; i < FIELD_NAMES.length; i++) {
058: DefaultConfigurationNode field = new DefaultConfigurationNode(
059: "field");
060: field.addChild(new DefaultConfigurationNode("name",
061: FIELD_NAMES[i]));
062: field.addAttribute(new DefaultConfigurationNode("type",
063: FIELD_TYPES[i]));
064: if (FIELD_ATTRS[i] != null) {
065: StringTokenizer tok = new StringTokenizer(
066: FIELD_ATTRS[i], ", ");
067: while (tok.hasMoreTokens()) {
068: field.addAttribute(new DefaultConfigurationNode(
069: "attribute", tok.nextToken()));
070: }
071: }
072: node.addChild(field);
073: }
074: }
075:
076: /**
077: * Tests a newly created, uninitialized node.
078: */
079: public void testNewNode() {
080: node = new DefaultConfigurationNode();
081: assertNull("name is not null", node.getName());
082: assertNull("value is not null", node.getValue());
083: assertNull("reference is not null", node.getReference());
084: assertTrue("Children are not empty", node.getChildren()
085: .isEmpty());
086: assertTrue("Named children are not empty", node.getChildren(
087: "test").isEmpty());
088: assertEquals("Children cound is not 0", 0, node
089: .getChildrenCount());
090: assertEquals("Named children count is not 0", 0, node
091: .getChildrenCount("test"));
092: assertTrue("Attributes are not empty", node.getAttributes()
093: .isEmpty());
094: assertTrue("Named attributes are not empty", node
095: .getAttributes("test").isEmpty());
096: assertNull("Node has a parent", node.getParentNode());
097: assertFalse("Node is defined", node.isDefined());
098: try {
099: node.getAttribute(0);
100: fail("Could access non existing attribute!");
101: } catch (IndexOutOfBoundsException iex) {
102: // ok
103: }
104: }
105:
106: /**
107: * Tests accessing a node's reference.
108: */
109: public void testGetReference() {
110: assertEquals("Reference was not stored", "TestReference", node
111: .getReference());
112: }
113:
114: /**
115: * Tests accessing the node's children.
116: */
117: public void testGetChildren() {
118: assertEquals("Number of children incorrect",
119: FIELD_NAMES.length + 1, node.getChildrenCount());
120: List children = node.getChildren();
121: Iterator it = children.iterator();
122: DefaultConfigurationNode child = (DefaultConfigurationNode) it
123: .next();
124: assertEquals("Wrong node", "name", child.getName());
125: checkFieldNodes(it);
126: }
127:
128: /**
129: * Tests accessing the node's children by name.
130: */
131: public void testGetChildrenByName() {
132: List children = node.getChildren("field");
133: assertEquals("Incorrect number of child nodes",
134: FIELD_NAMES.length, children.size());
135: assertEquals("Incorrect result of getChildrenCount()",
136: FIELD_NAMES.length, node.getChildrenCount("field"));
137: checkFieldNodes(children.iterator());
138: assertTrue("Found non existing nodes", node.getChildren("test")
139: .isEmpty());
140: assertEquals("Wrong children list for null",
141: node.getChildren(), node.getChildren(null));
142: }
143:
144: /**
145: * Tests adding a new child node.
146: */
147: public void testAddChild() {
148: int cnt = node.getChildrenCount();
149: DefaultConfigurationNode ndNew = new DefaultConfigurationNode(
150: "test", "xyz");
151: node.addChild(ndNew);
152: assertEquals("New node was not added", cnt + 1, node
153: .getChildrenCount());
154: List children = node.getChildren();
155: assertEquals("Incorrect number of children", node
156: .getChildrenCount(), children.size());
157: assertSame("Node was not added to end", ndNew, children
158: .get(cnt));
159: assertEquals("Incorrect number of named children", 1, node
160: .getChildrenCount(ndNew.getName()));
161: assertFalse("Child is an attribute", ndNew.isAttribute());
162: assertSame("Parent was not set", node, ndNew.getParentNode());
163: }
164:
165: /**
166: * Tests adding invalid child nodes.
167: */
168: public void testAddUndefinedChild() {
169: try {
170: node.addChild(null);
171: fail("null node could be added!");
172: } catch (IllegalArgumentException iex) {
173: // ok
174: }
175:
176: try {
177: node.addChild(new DefaultConfigurationNode());
178: fail("Node without name could be added!");
179: } catch (IllegalArgumentException iex) {
180: // ok
181: }
182: }
183:
184: /**
185: * Tests removing a child node.
186: */
187: public void testRemoveChild() {
188: DefaultConfigurationNode child = (DefaultConfigurationNode) node
189: .getChildren().get(3);
190: int cnt = node.getChildrenCount();
191: node.removeChild(child);
192: assertEquals("Child was not removed", cnt - 1, node
193: .getChildrenCount());
194: for (Iterator it = node.getChildren().iterator(); it.hasNext();) {
195: assertNotSame("Found removed node", child, it.next());
196: }
197: assertNull("Parent reference was not removed", child
198: .getParentNode());
199: }
200:
201: /**
202: * Tests removing a child node that does not belong to this node.
203: */
204: public void testRemoveNonExistingChild() {
205: int cnt = node.getChildrenCount();
206: node.removeChild(new DefaultConfigurationNode("test"));
207: node.removeChild(new DefaultConfigurationNode());
208: node.removeChild((ConfigurationNode) null);
209: node.removeChild("non existing child node");
210: node.removeChild((String) null);
211: assertEquals("Children were changed", cnt, node
212: .getChildrenCount());
213: }
214:
215: /**
216: * Tests removing children by their name.
217: */
218: public void testRemoveChildByName() {
219: int cnt = node.getChildrenCount();
220: node.removeChild("name");
221: assertEquals("Child was not removed", cnt - 1, node
222: .getChildrenCount());
223: assertEquals("Still found name child", 0, node
224: .getChildrenCount("name"));
225: node.removeChild("field");
226: assertEquals("Still remaining nodes", 0, node
227: .getChildrenCount());
228: }
229:
230: /**
231: * Tests removing all children at once.
232: */
233: public void testRemoveChildren() {
234: node.removeChildren();
235: assertEquals("Children count is not 0", 0, node
236: .getChildrenCount());
237: assertTrue("Children are not empty", node.getChildren()
238: .isEmpty());
239: }
240:
241: /**
242: * Tests accessing a child by its index.
243: */
244: public void testGetChild() {
245: ConfigurationNode child = node.getChild(2);
246: assertEquals("Wrong child returned", child, node.getChildren()
247: .get(2));
248: }
249:
250: /**
251: * Tests accessing child nodes with invalid indices.
252: */
253: public void testGetChildInvalidIndex() {
254: try {
255: node.getChild(4724);
256: fail("Could access invalid index!");
257: } catch (IndexOutOfBoundsException iex) {
258: // ok
259: }
260: }
261:
262: /**
263: * Tests accessing the node's attributes.
264: */
265: public void testGetAttributes() {
266: assertEquals("Number of attributes incorrect", 1, node
267: .getAttributeCount());
268: List attributes = node.getAttributes();
269: Iterator it = attributes.iterator();
270: DefaultConfigurationNode attr = (DefaultConfigurationNode) it
271: .next();
272: assertEquals("Wrong node", "type", attr.getName());
273: assertFalse("More attributes", it.hasNext());
274: }
275:
276: /**
277: * Tests accessing the node's attributes by name.
278: */
279: public void testGetAttributesByName() {
280: assertEquals("Incorrect number of attributes", 1, node
281: .getAttributeCount("type"));
282: DefaultConfigurationNode field = (DefaultConfigurationNode) node
283: .getChildren().get(1);
284: assertEquals("Incorrect number of attributes", 2, field
285: .getAttributeCount("attribute"));
286: List attrs = field.getAttributes("attribute");
287: assertEquals("Wrong value", "primarykey",
288: ((DefaultConfigurationNode) attrs.get(0)).getValue());
289: assertEquals("Wrong value", "unique",
290: ((DefaultConfigurationNode) attrs.get(1)).getValue());
291: }
292:
293: /**
294: * Tests adding a new attribute node.
295: */
296: public void testAddAttribute() {
297: int cnt = node.getAttributeCount();
298: DefaultConfigurationNode ndNew = new DefaultConfigurationNode(
299: "test", "xyz");
300: node.addAttribute(ndNew);
301: assertEquals("New node was not added", cnt + 1, node
302: .getAttributeCount());
303: List attrs = node.getAttributes();
304: assertEquals("Incorrect number of attributes", node
305: .getAttributeCount(), attrs.size());
306: assertSame("Node was not added to end", ndNew, attrs.get(cnt));
307: assertEquals("Incorrect number of named attributes", 1, node
308: .getAttributeCount(ndNew.getName()));
309: assertTrue("Child is no attribute", ndNew.isAttribute());
310: assertSame("Parent was not set", node, ndNew.getParentNode());
311: }
312:
313: /**
314: * Tests removing an attribute node.
315: */
316: public void testRemoveAttribute() {
317: DefaultConfigurationNode attr = (DefaultConfigurationNode) node
318: .getAttributes().get(0);
319: int cnt = node.getAttributeCount();
320: node.removeAttribute(attr);
321: assertEquals("Attribute was not removed", cnt - 1, node
322: .getAttributeCount());
323: for (Iterator it = node.getAttributes().iterator(); it
324: .hasNext();) {
325: assertNotSame("Found removed node", attr, it.next());
326: }
327: assertNull("Parent reference was not removed", attr
328: .getParentNode());
329: }
330:
331: /**
332: * Tests removing attributes by their names.
333: */
334: public void testRemoveAttributeByName() {
335: ConfigurationNode field = node.getChild(1);
336: assertEquals("Incorrect number of attributes", 3, field
337: .getAttributeCount());
338: field.removeAttribute("attribute");
339: assertEquals("Not all nodes removed", 1, field
340: .getAttributeCount());
341: assertTrue("Remaining attributes", field.getAttributes(
342: "attribute").isEmpty());
343: field.removeAttribute("type");
344: assertEquals("Remaining attributes", 0, field
345: .getAttributeCount());
346: }
347:
348: /**
349: * Tests removing all attributes.
350: */
351: public void testRemoveAttributes() {
352: node.removeAttributes();
353: assertEquals("Not all attributes removed", 0, node
354: .getAttributeCount());
355: assertTrue("Attributes not empty", node.getAttributes()
356: .isEmpty());
357: }
358:
359: /**
360: * Tests changing a node's attribute state.
361: */
362: public void testChangeAttributeState() {
363: ConfigurationNode attr = node.getAttribute(0);
364: try {
365: attr.setAttribute(false);
366: fail("Could change node's attribute state!");
367: } catch (IllegalStateException iex) {
368: // ok
369: }
370: }
371:
372: /**
373: * Tests the visit() method using a simple visitor.
374: */
375: public void testVisit() {
376: CountNodeVisitor visitor = new CountNodeVisitor();
377: node.visit(visitor);
378: assertEquals("Not all nodes visited", 19, visitor.beforeCalls);
379: assertEquals("Different number of before and after calls",
380: visitor.beforeCalls, visitor.afterCalls);
381: }
382:
383: /**
384: * Tests the visit() method with a visitor that terminates the visit
385: * process.
386: */
387: public void testVisitWithTerminate() {
388: CountNodeVisitor visitor = new CountNodeVisitor(10);
389: node.visit(visitor);
390: assertEquals("Incorrect number of nodes visited",
391: visitor.maxCalls, visitor.beforeCalls);
392: assertEquals("Different number of before and after calls",
393: visitor.beforeCalls, visitor.afterCalls);
394: }
395:
396: /**
397: * Tests the visit() method when null is passed in. This should throw an
398: * exception.
399: */
400: public void testVisitWithNullVisitor() {
401: try {
402: node.visit(null);
403: fail("Could pass in null visitor!");
404: } catch (IllegalArgumentException iex) {
405: // ok
406: }
407: }
408:
409: /**
410: * Tests cloning a node.
411: */
412: public void testClone() {
413: node.setValue("TestValue");
414: DefaultConfigurationNode clone = (DefaultConfigurationNode) node
415: .clone();
416: assertEquals("Value not cloned", "TestValue", clone.getValue());
417: assertEquals("Name not cloned", "table", clone.getName());
418: assertEquals("Reference not cloned", "TestReference", clone
419: .getReference());
420: assertEquals("Children were cloned", 0, clone
421: .getChildrenCount());
422: assertEquals("Attributes were cloned", 0, clone
423: .getAttributeCount());
424: }
425:
426: /**
427: * Helper method for checking the child nodes of type "field".
428: *
429: * @param itFields the iterator with the child nodes
430: */
431: private void checkFieldNodes(Iterator itFields) {
432: for (int i = 0; i < FIELD_NAMES.length; i++) {
433: DefaultConfigurationNode child = (DefaultConfigurationNode) itFields
434: .next();
435: assertEquals("Wrong node", "field", child.getName());
436: List nameNodes = child.getChildren("name");
437: assertEquals("Wrong number of name nodes", 1, nameNodes
438: .size());
439: DefaultConfigurationNode nameNode = (DefaultConfigurationNode) nameNodes
440: .get(0);
441: assertEquals("Wrong field name", FIELD_NAMES[i], nameNode
442: .getValue());
443: }
444: }
445:
446: /**
447: * A test visitor implementation that is able to count the number of visits.
448: * It also supports a maximum number of visits to be set; if this number is
449: * reached, the <code>terminate()</code> method returns <b>true</b>.
450: */
451: static class CountNodeVisitor implements ConfigurationNodeVisitor {
452: public int beforeCalls;
453:
454: public int afterCalls;
455:
456: public int maxCalls;
457:
458: public CountNodeVisitor() {
459: this (Integer.MAX_VALUE);
460: }
461:
462: public CountNodeVisitor(int maxNumberOfVisits) {
463: maxCalls = maxNumberOfVisits;
464: }
465:
466: public void visitBeforeChildren(ConfigurationNode node) {
467: beforeCalls++;
468: }
469:
470: public void visitAfterChildren(ConfigurationNode node) {
471: afterCalls++;
472: }
473:
474: public boolean terminate() {
475: return beforeCalls >= maxCalls;
476: }
477: }
478: }
|