You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by oh...@apache.org on 2008/03/01 22:16:38 UTC

svn commit: r632662 - in /commons/proper/configuration/branches/configuration2_experimental/src: main/java/org/apache/commons/configuration2/expr/ test/java/org/apache/commons/configuration2/expr/

Author: oheger
Date: Sat Mar  1 13:16:38 2008
New Revision: 632662

URL: http://svn.apache.org/viewvc?rev=632662&view=rev
Log:
Initial implementation of DefaultExpressionEngine based on the NodeHandler approach

Added:
    commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/expr/DefaultConfigurationKey.java
      - copied, changed from r630471, commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/tree/DefaultConfigurationKey.java
    commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/expr/DefaultExpressionEngine.java
      - copied, changed from r630471, commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/tree/DefaultExpressionEngine.java
    commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/expr/TestDefaultExpressionEngine.java
      - copied, changed from r630471, commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/tree/TestDefaultExpressionEngine.java

Copied: commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/expr/DefaultConfigurationKey.java (from r630471, commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/tree/DefaultConfigurationKey.java)
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/expr/DefaultConfigurationKey.java?p2=commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/expr/DefaultConfigurationKey.java&p1=commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/tree/DefaultConfigurationKey.java&r1=630471&r2=632662&rev=632662&view=diff
==============================================================================
--- commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/tree/DefaultConfigurationKey.java (original)
+++ commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/expr/DefaultConfigurationKey.java Sat Mar  1 13:16:38 2008
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.commons.configuration2.tree;
+package org.apache.commons.configuration2.expr;
 
 import java.util.Iterator;
 import java.util.NoSuchElementException;
@@ -455,7 +455,7 @@
      * class implements the normal iterator interface. In addition it provides
      * some specific methods for configuration keys.
      */
-    public class KeyIterator implements Iterator, Cloneable
+    public class KeyIterator implements Iterator<String>, Cloneable
     {
         /** Stores the current key name. */
         private String current;
@@ -529,7 +529,7 @@
          *
          * @return the next object
          */
-        public Object next()
+        public String next()
         {
             return nextKey();
         }

Copied: commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/expr/DefaultExpressionEngine.java (from r630471, commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/tree/DefaultExpressionEngine.java)
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/expr/DefaultExpressionEngine.java?p2=commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/expr/DefaultExpressionEngine.java&p1=commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/tree/DefaultExpressionEngine.java&r1=630471&r2=632662&rev=632662&view=diff
==============================================================================
--- commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/tree/DefaultExpressionEngine.java (original)
+++ commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/expr/DefaultExpressionEngine.java Sat Mar  1 13:16:38 2008
@@ -15,10 +15,8 @@
  * limitations under the License.
  */
 
-package org.apache.commons.configuration2.tree;
+package org.apache.commons.configuration2.expr;
 
-import java.util.Collection;
-import java.util.LinkedList;
 import java.util.List;
 
 import org.apache.commons.lang.StringUtils;
@@ -43,7 +41,7 @@
  * <code>[@&lt;attributeName&gt;]</code>.</li>
  * <li>If there are multiple child or attribute nodes with the same name, a
  * specific node can be selected using a numerical index. By default indices are
- * written in paranthesis.</li>
+ * written in parenthesis.</li>
  * </ul>
  * </p>
  * <p>
@@ -158,7 +156,7 @@
      * Sets the attribute end marker.
      *
      * @param attributeEnd the attribute end marker; can be <b>null</b> if no
-     * end marker is needed
+     *        end marker is needed
      */
     public void setAttributeEnd(String attributeEnd)
     {
@@ -278,27 +276,28 @@
      *
      * @param root the root node
      * @param key the key
+     * @param handler the node handler
      * @return a list with the matching nodes
      */
-    public List<ConfigurationNode> query(ConfigurationNode root, String key)
+    public <T> NodeList<T> query(T root, String key, NodeHandler<T> handler)
     {
-        List<ConfigurationNode> nodes = new LinkedList<ConfigurationNode>();
-        findNodesForKey(new DefaultConfigurationKey(this, key).iterator(), root, nodes);
+        NodeList<T> nodes = new NodeList<T>();
+        findNodesForKey(new DefaultConfigurationKey(this, key).iterator(),
+                root, nodes, handler);
         return nodes;
     }
 
     /**
      * Determines the key of the passed in node. This implementation takes the
      * given parent key, adds a property delimiter, and then adds the node's
-     * name. (For attribute nodes the attribute delimiters are used instead.)
-     * The name of the root node is a blanc string. Note that no indices will be
-     * returned.
+     * name. The name of the root node is an empty string. Note that no indices
+     * will be returned.
      *
      * @param node the node whose key is to be determined
      * @param parentKey the key of this node's parent
      * @return the key for the given node
      */
-    public String nodeKey(ConfigurationNode node, String parentKey)
+    public <T> String nodeKey(T node, String parentKey, NodeHandler<T> handler)
     {
         if (parentKey == null)
         {
@@ -310,19 +309,34 @@
         {
             DefaultConfigurationKey key = new DefaultConfigurationKey(this,
                     parentKey);
-            if (node.isAttribute())
-            {
-                key.appendAttribute(node.getName());
-            }
-            else
-            {
-                key.append(node.getName(), true);
-            }
+            key.append(handler.nodeName(node), true);
             return key.toString();
         }
     }
 
     /**
+     * Determines the key of the specified attribute. This implementation
+     * appends the name of the attribute to the parent key using the attribute
+     * marker as separator.
+     *
+     * @param parentNode the parent node
+     * @param parentKey the key of the parent node
+     * @param attrName the name of the attribute
+     * @param handler the node handler
+     */
+    public <T> String attributeKey(T parentNode, String parentKey,
+            String attrName, NodeHandler<T> handler)
+    {
+        DefaultConfigurationKey key = new DefaultConfigurationKey(this);
+        if (parentKey != null)
+        {
+            key.append(parentKey, false);
+        }
+        key.appendAttribute(attrName);
+        return key.toString();
+    }
+
+    /**
      * <p>
      * Prepares Adding the property with the specified key.
      * </p>
@@ -330,10 +344,10 @@
      * To be able to deal with the structure supported by hierarchical
      * configuration implementations the passed in key is of importance,
      * especially the indices it might contain. The following example should
-     * clearify this: Suppose the actual node structure looks like the
-     * following:
+     * clarify this: Suppose the actual node structure looks like the following:
      * </p>
      * <p>
+     *
      * <pre>
      *  tables
      *     +-- table
@@ -349,6 +363,7 @@
      *             +-- fields
      *                    ...
      * </pre>
+     *
      * </p>
      * <p>
      * In this example a database structure is defined, e.g. all fields of the
@@ -359,9 +374,11 @@
      * to a table it is not enough to say just
      * </p>
      * <p>
+     *
      * <pre>
      * config.addProperty(&quot;tables.table.fields.field.name&quot;, &quot;newField&quot;);
      * </pre>
+     *
      * </p>
      * <p>
      * The statement given above contains some ambiguity. For instance it is not
@@ -370,7 +387,7 @@
      * this would be the last table. The same is true for the <code>field</code>;
      * because there are multiple fields and no explicit index is provided, a
      * new <code>name</code> property would be added to the last field - which
-     * is propably not what was desired.
+     * is probably not what was desired.
      * </p>
      * <p>
      * To make things clear explicit indices should be provided whenever
@@ -385,9 +402,11 @@
      * a new branch should be created. Given this our example would run:
      * </p>
      * <p>
+     *
      * <pre>
      * config.addProperty(&quot;tables.table(1).fields.field(-1).name&quot;, &quot;newField&quot;);
      * </pre>
+     *
      * </p>
      * <p>
      * With this notation it is possible to add new branches everywhere. We
@@ -395,9 +414,11 @@
      * specifying
      * </p>
      * <p>
+     *
      * <pre>
      * config.addProperty(&quot;tables.table(-1).fields.field.name&quot;, &quot;newField2&quot;);
      * </pre>
+     *
      * </p>
      * <p>
      * (Note that because after the <code>table</code> element a new branch is
@@ -409,7 +430,8 @@
      * @param key the key of the new property
      * @return a data object with information needed for the add operation
      */
-    public NodeAddData prepareAdd(ConfigurationNode root, String key)
+    public <T> NodeAddData<T> prepareAdd(T root, String key,
+            NodeHandler<T> handler)
     {
         DefaultConfigurationKey.KeyIterator it = new DefaultConfigurationKey(
                 this, key).iterator();
@@ -419,8 +441,8 @@
                     "Key for add operation must be defined!");
         }
 
-        NodeAddData result = new NodeAddData();
-        result.setParent(findLastPathNode(it, root));
+        NodeAddData<T> result = new NodeAddData<T>();
+        result.setParent(findLastPathNode(it, root, handler));
 
         while (it.hasNext())
         {
@@ -442,17 +464,20 @@
     /**
      * Recursive helper method for evaluating a key. This method processes all
      * facets of a configuration key, traverses the tree of properties and
-     * fetches the the nodes of all matching properties.
+     * fetches the nodes of all matching properties.
      *
      * @param keyPart the configuration key iterator
      * @param node the actual node
      * @param nodes here the found nodes are stored
+     * @param handler the node handler
      */
-    protected void findNodesForKey(DefaultConfigurationKey.KeyIterator keyPart, ConfigurationNode node, Collection<ConfigurationNode> nodes)
+    protected <T> void findNodesForKey(
+            DefaultConfigurationKey.KeyIterator keyPart, T node,
+            NodeList<T> nodes, NodeHandler<T> handler)
     {
         if (!keyPart.hasNext())
         {
-            nodes.add(node);
+            nodes.addNode(node);
         }
 
         else
@@ -460,11 +485,16 @@
             String key = keyPart.nextKey(false);
             if (keyPart.isPropertyKey())
             {
-                processSubNodes(keyPart, node.getChildren(key), nodes);
+                processSubNodes(keyPart, handler.getChildren(node, key), nodes,
+                        handler);
             }
+
             if (keyPart.isAttribute())
             {
-                processSubNodes(keyPart, node.getAttributes(key), nodes);
+                if (handler.getAttributeValue(node, key) != null)
+                {
+                    nodes.addAttribute(node, key);
+                }
             }
         }
     }
@@ -476,10 +506,11 @@
      *
      * @param keyIt the key iterator
      * @param node the actual node
+     * @param handler the node handler
      * @return the last existing node on the given path
      */
-    protected ConfigurationNode findLastPathNode(
-            DefaultConfigurationKey.KeyIterator keyIt, ConfigurationNode node)
+    protected <T> T findLastPathNode(DefaultConfigurationKey.KeyIterator keyIt,
+            T node, NodeHandler<T> handler)
     {
         String keyPart = keyIt.nextKey(false);
 
@@ -488,16 +519,19 @@
             if (!keyIt.isPropertyKey())
             {
                 // Attribute keys can only appear as last elements of the path
-                throw new IllegalArgumentException("Invalid path for add operation: Attribute key in the middle!");
+                throw new IllegalArgumentException(
+                        "Invalid path for add operation: Attribute key in the middle!");
             }
-            int idx = keyIt.hasIndex() ? keyIt.getIndex() : node.getChildrenCount(keyPart) - 1;
-            if (idx < 0 || idx >= node.getChildrenCount(keyPart))
+
+            List<T> children = handler.getChildren(node, keyPart);
+            int idx = keyIt.hasIndex() ? keyIt.getIndex() : children.size() - 1;
+            if (idx < 0 || idx >= children.size())
             {
                 return node;
             }
             else
             {
-                return findLastPathNode(keyIt, node.getChildren(keyPart).get(idx));
+                return findLastPathNode(keyIt, children.get(idx), handler);
             }
         }
 
@@ -515,21 +549,25 @@
      * @param keyPart the key part
      * @param subNodes a list with the sub nodes to process
      * @param nodes the target collection
+     * @param handler the node handler
      */
-    private void processSubNodes(DefaultConfigurationKey.KeyIterator keyPart, List<ConfigurationNode> subNodes, Collection<ConfigurationNode> nodes)
+    private <T> void processSubNodes(
+            DefaultConfigurationKey.KeyIterator keyPart, List<T> subNodes,
+            NodeList<T> nodes, NodeHandler<T> handler)
     {
         if (keyPart.hasIndex())
         {
             if (keyPart.getIndex() >= 0 && keyPart.getIndex() < subNodes.size())
             {
-                findNodesForKey(keyPart.clone(), subNodes.get(keyPart.getIndex()), nodes);
+                findNodesForKey(keyPart.clone(), subNodes.get(keyPart
+                        .getIndex()), nodes, handler);
             }
         }
         else
         {
-            for (ConfigurationNode subNode : subNodes)
+            for (T subNode : subNodes)
             {
-                findNodesForKey(keyPart.clone(), subNode, nodes);
+                findNodesForKey(keyPart.clone(), subNode, nodes, handler);
             }
         }
     }

Copied: commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/expr/TestDefaultExpressionEngine.java (from r630471, commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/tree/TestDefaultExpressionEngine.java)
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/expr/TestDefaultExpressionEngine.java?p2=commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/expr/TestDefaultExpressionEngine.java&p1=commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/tree/TestDefaultExpressionEngine.java&r1=630471&r2=632662&rev=632662&view=diff
==============================================================================
--- commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/tree/TestDefaultExpressionEngine.java (original)
+++ commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/expr/TestDefaultExpressionEngine.java Sat Mar  1 13:16:38 2008
@@ -14,50 +14,58 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.commons.configuration2.tree;
+package org.apache.commons.configuration2.expr;
 
 import java.util.Iterator;
-import java.util.List;
+
+import junit.framework.TestCase;
 
 import org.apache.commons.configuration2.tree.ConfigurationNode;
 import org.apache.commons.configuration2.tree.DefaultConfigurationNode;
-import org.apache.commons.configuration2.tree.DefaultExpressionEngine;
-import org.apache.commons.configuration2.tree.NodeAddData;
-
-import junit.framework.TestCase;
 
 /**
  * Test class for DefaultExpressionEngine.
  *
  * @author Oliver Heger
+ * @version $Id$
  */
 public class TestDefaultExpressionEngine extends TestCase
 {
     /** Stores the names of the test nodes representing tables. */
-    private static String[] tables =
-    { "users", "documents"};
+    private static String[] tables = {
+            "users", "documents"
+    };
 
     /** Stores the types of the test table nodes. */
-    private static String[] tabTypes =
-    { "system", "application"};
+    private static String[] tabTypes = {
+            "system", "application"
+    };
 
     /** Test data fields for the node hierarchy. */
-    private static String[][] fields =
-    {
-    { "uid", "uname", "firstName", "lastName", "email"},
-    { "docid", "name", "creationDate", "authorID", "version"}};
+    private static String[][] fields = {
+            {
+                    "uid", "uname", "firstName", "lastName", "email"
+            }, {
+                    "docid", "name", "creationDate", "authorID", "version"
+            }
+    };
 
     /** The object to be tested. */
-    DefaultExpressionEngine engine;
+    private DefaultExpressionEngine engine;
 
     /** The root of a hierarchy with configuration nodes. */
-    ConfigurationNode root;
+    private ConfigurationNode root;
+
+    /** The node handler for the used test nodes. */
+    private ConfigurationNodeHandler handler;
 
+    @Override
     protected void setUp() throws Exception
     {
         super.setUp();
         root = setUpNodes();
         engine = new DefaultExpressionEngine();
+        handler = new ConfigurationNodeHandler();
     }
 
     /**
@@ -132,15 +140,15 @@
      */
     public void testQueryRootNode()
     {
-        List nodes = checkKey(null, null, 1);
-        assertSame("Root node not found", root, nodes.get(0));
+        NodeList<ConfigurationNode> nodes = checkKey(null, null, 1);
+        assertSame("Root node not found", root, nodes.getNode(0));
         nodes = checkKey("", null, 1);
-        assertSame("Root node not found", root, nodes.get(0));
+        assertSame("Root node not found", root, nodes.getNode(0));
         checkKeyValue("[@test]", "test", "true");
     }
 
     /**
-     * Tests a different query snytax. Sets other strings for the typical tokens
+     * Tests a different query syntax. Sets other strings for the typical tokens
      * used by the expression engine.
      */
     public void testQueryAlternativeSyntax()
@@ -159,12 +167,12 @@
     {
         ConfigurationNode node = root.getChild(0);
         assertEquals("Invalid name for descendant of root", "tables", engine
-                .nodeKey(node, ""));
+                .nodeKey(node, "", handler));
         assertEquals("Parent key not respected", "test.tables", engine.nodeKey(
-                node, "test"));
+                node, "test", handler));
         assertEquals("Full parent key not taken into account",
                 "a.full.parent.key.tables", engine.nodeKey(node,
-                        "a.full.parent.key"));
+                        "a.full.parent.key", handler));
     }
 
     /**
@@ -172,9 +180,10 @@
      */
     public void testNodeKeyWithRoot()
     {
-        assertEquals("Wrong name for root noot", "", engine.nodeKey(root, null));
+        assertEquals("Wrong name for root node", "", engine.nodeKey(root, null,
+                handler));
         assertEquals("Null name not detected", "test", engine.nodeKey(root,
-                "test"));
+                "test", handler));
     }
 
     /**
@@ -185,9 +194,11 @@
         ConfigurationNode node = root.getChild(0).getChild(0).getAttribute(0);
         assertEquals("Wrong attribute node", "type", node.getName());
         assertEquals("Wrong attribute key", "tables.table[@type]", engine
-                .nodeKey(node, "tables.table"));
-        assertEquals("Wrong key for root attribute", "[@test]", engine.nodeKey(
-                root.getAttribute(0), ""));
+                .attributeKey(node.getParentNode(), "tables.table", node
+                        .getName(), handler));
+        assertEquals("Wrong key for root attribute", "[@test]",
+                engine.attributeKey(root, "", root.getAttribute(0).getName(),
+                        handler));
     }
 
     /**
@@ -197,10 +208,11 @@
     {
         ConfigurationNode node = root.getChild(1);
         assertEquals("Wrong escaped key", "connection..settings", engine
-                .nodeKey(node, ""));
+                .nodeKey(node, "", handler));
         assertEquals("Wrong complex escaped key",
                 "connection..settings.usr..name", engine.nodeKey(node
-                        .getChild(0), engine.nodeKey(node, "")));
+                        .getChild(0), engine.nodeKey(node, "", handler),
+                        handler));
     }
 
     /**
@@ -210,13 +222,13 @@
     {
         setUpAlternativeSyntax();
         assertEquals("Wrong child key", "tables/table", engine.nodeKey(root
-                .getChild(0).getChild(0), "tables"));
-        assertEquals("Wrong attribute key", "@test", engine.nodeKey(root
-                .getAttribute(0), ""));
+                .getChild(0).getChild(0), "tables", handler));
+        assertEquals("Wrong attribute key", "@test", engine.attributeKey(root,
+                null, root.getAttribute(0).getName(), handler));
 
         engine.setAttributeStart(engine.getPropertyDelimiter());
-        assertEquals("Wrong attribute key", "/test", engine.nodeKey(root
-                .getAttribute(0), ""));
+        assertEquals("Wrong attribute key", "/test", engine.attributeKey(root,
+                null, root.getAttribute(0).getName(), handler));
     }
 
     /**
@@ -224,13 +236,15 @@
      */
     public void testPrepareAddDirectly()
     {
-        NodeAddData data = engine.prepareAdd(root, "newNode");
+        NodeAddData<ConfigurationNode> data = engine.prepareAdd(root,
+                "newNode", handler);
         assertSame("Wrong parent node", root, data.getParent());
         assertTrue("Path nodes available", data.getPathNodes().isEmpty());
         assertEquals("Wrong name of new node", "newNode", data.getNewNodeName());
         assertFalse("New node is an attribute", data.isAttribute());
 
-        data = engine.prepareAdd(root, "tables.table.fields.field.name");
+        data = engine.prepareAdd(root, "tables.table.fields.field.name",
+                handler);
         assertEquals("Wrong name of new node", "name", data.getNewNodeName());
         assertTrue("Path nodes available", data.getPathNodes().isEmpty());
         assertEquals("Wrong parent node", "field", data.getParent().getName());
@@ -244,8 +258,8 @@
      */
     public void testPrepareAddWithIndex()
     {
-        NodeAddData data = engine
-                .prepareAdd(root, "tables.table(0).tableSpace");
+        NodeAddData<ConfigurationNode> data = engine.prepareAdd(root,
+                "tables.table(0).tableSpace", handler);
         assertEquals("Wrong name of new node", "tableSpace", data
                 .getNewNodeName());
         assertTrue("Path nodes available", data.getPathNodes().isEmpty());
@@ -254,7 +268,8 @@
         ConfigurationNode node = data.getParent().getChild(0);
         assertEquals("Wrong table", tables[0], node.getValue());
 
-        data = engine.prepareAdd(root, "tables.table(1).fields.field(2).alias");
+        data = engine.prepareAdd(root, "tables.table(1).fields.field(2).alias",
+                handler);
         assertEquals("Wrong name of new node", "alias", data.getNewNodeName());
         assertEquals("Wrong type of parent node", "field", data.getParent()
                 .getName());
@@ -267,8 +282,8 @@
      */
     public void testPrepareAddAttribute()
     {
-        NodeAddData data = engine.prepareAdd(root,
-                "tables.table(0)[@tableSpace]");
+        NodeAddData<ConfigurationNode> data = engine.prepareAdd(root,
+                "tables.table(0)[@tableSpace]", handler);
         assertEquals("Wrong table node", tables[0], data.getParent()
                 .getChild(0).getValue());
         assertEquals("Wrong name of new node", "tableSpace", data
@@ -276,36 +291,39 @@
         assertTrue("Attribute not detected", data.isAttribute());
         assertTrue("Path nodes available", data.getPathNodes().isEmpty());
 
-        data = engine.prepareAdd(root, "[@newAttr]");
+        data = engine.prepareAdd(root, "[@newAttr]", handler);
         assertSame("Root node is not parent", root, data.getParent());
         assertEquals("Wrong name of new node", "newAttr", data.getNewNodeName());
         assertTrue("Attribute not detected", data.isAttribute());
     }
 
     /**
-     * Tests add operations where complete pathes are added.
+     * Tests add operations where complete paths are added.
      */
     public void testPrepareAddWithPath()
     {
-        NodeAddData data = engine.prepareAdd(root,
-                "tables.table(1).fields.field(-1).name");
+        NodeAddData<ConfigurationNode> data = engine.prepareAdd(root,
+                "tables.table(1).fields.field(-1).name", handler);
         assertEquals("Wrong name of new node", "name", data.getNewNodeName());
-        checkNodePath(data, new String[]
-        { "field"});
+        checkNodePath(data, new String[] {
+            "field"
+        });
         assertEquals("Wrong type of parent node", "fields", data.getParent()
                 .getName());
 
-        data = engine.prepareAdd(root, "tables.table(-1).name");
+        data = engine.prepareAdd(root, "tables.table(-1).name", handler);
         assertEquals("Wrong name of new node", "name", data.getNewNodeName());
-        checkNodePath(data, new String[]
-        { "table"});
+        checkNodePath(data, new String[] {
+            "table"
+        });
         assertEquals("Wrong type of parent node", "tables", data.getParent()
                 .getName());
 
-        data = engine.prepareAdd(root, "a.complete.new.path");
+        data = engine.prepareAdd(root, "a.complete.new.path", handler);
         assertEquals("Wrong name of new node", "path", data.getNewNodeName());
-        checkNodePath(data, new String[]
-        { "a", "complete", "new"});
+        checkNodePath(data, new String[] {
+                "a", "complete", "new"
+        });
         assertSame("Root is not parent", root, data.getParent());
     }
 
@@ -318,16 +336,18 @@
         engine.setAttributeEnd(null);
         engine.setAttributeStart(engine.getPropertyDelimiter());
 
-        NodeAddData data = engine.prepareAdd(root, "tables.table(0).test");
+        NodeAddData<ConfigurationNode> data = engine.prepareAdd(root,
+                "tables.table(0).test", handler);
         assertEquals("Wrong name of new node", "test", data.getNewNodeName());
         assertFalse("New node is an attribute", data.isAttribute());
         assertEquals("Wrong type of parent node", "table", data.getParent()
                 .getName());
 
-        data = engine.prepareAdd(root, "a.complete.new.path");
+        data = engine.prepareAdd(root, "a.complete.new.path", handler);
         assertFalse("New node is an attribute", data.isAttribute());
-        checkNodePath(data, new String[]
-        { "a", "complete", "new"});
+        checkNodePath(data, new String[] {
+                "a", "complete", "new"
+        });
     }
 
     /**
@@ -336,17 +356,19 @@
     public void testPrepareAddWithAlternativeSyntax()
     {
         setUpAlternativeSyntax();
-        NodeAddData data = engine.prepareAdd(root, "tables/table[0]/test");
+        NodeAddData<ConfigurationNode> data = engine.prepareAdd(root,
+                "tables/table[0]/test", handler);
         assertEquals("Wrong name of new node", "test", data.getNewNodeName());
         assertFalse("New node is attribute", data.isAttribute());
         assertEquals("Wrong parent node", tables[0], data.getParent().getChild(
                 0).getValue());
 
-        data = engine.prepareAdd(root, "a/complete/new/path@attr");
+        data = engine.prepareAdd(root, "a/complete/new/path@attr", handler);
         assertEquals("Wrong name of new attribute", "attr", data
                 .getNewNodeName());
-        checkNodePath(data, new String[]
-        { "a", "complete", "new", "path"});
+        checkNodePath(data, new String[] {
+                "a", "complete", "new", "path"
+        });
         assertSame("Root is not parent", root, data.getParent());
     }
 
@@ -358,7 +380,7 @@
     {
         try
         {
-            engine.prepareAdd(root, "tables.table(0)[@type].new");
+            engine.prepareAdd(root, "tables.table(0)[@type].new", handler);
             fail("Could add node to existing attribute!");
         }
         catch (IllegalArgumentException iex)
@@ -369,8 +391,10 @@
         try
         {
             engine
-                    .prepareAdd(root,
-                            "a.complete.new.path.with.an[@attribute].at.a.non.allowed[@position]");
+                    .prepareAdd(
+                            root,
+                            "a.complete.new.path.with.an[@attribute].at.a.non.allowed[@position]",
+                            handler);
             fail("Could add invalid path!");
         }
         catch (IllegalArgumentException iex)
@@ -380,7 +404,7 @@
 
         try
         {
-            engine.prepareAdd(root, null);
+            engine.prepareAdd(root, null, handler);
             fail("Could add null key!");
         }
         catch (IllegalArgumentException iex)
@@ -390,7 +414,7 @@
 
         try
         {
-            engine.prepareAdd(root, "");
+            engine.prepareAdd(root, "", handler);
             fail("Could add undefined key!");
         }
         catch (IllegalArgumentException iex)
@@ -473,15 +497,16 @@
      * @param count the number of expected result nodes
      * @return the list with the results of the query
      */
-    private List checkKey(String key, String name, int count)
+    private NodeList<ConfigurationNode> checkKey(String key, String name,
+            int count)
     {
-        List nodes = engine.query(root, key);
+        NodeList<ConfigurationNode> nodes = engine.query(root, key, handler);
         assertEquals("Wrong number of result nodes for key " + key, count,
                 nodes.size());
-        for (Iterator it = nodes.iterator(); it.hasNext();)
+        for (int i = 0; i < nodes.size(); i++)
         {
-            assertEquals("Wrong result node for key " + key, name,
-                    ((ConfigurationNode) it.next()).getName());
+            assertEquals("Wrong result node for key " + key, name, nodes
+                    .getName(i, handler));
         }
         return nodes;
     }
@@ -497,9 +522,9 @@
      */
     private void checkKeyValue(String key, String name, String value)
     {
-        List nodes = checkKey(key, name, 1);
-        assertEquals("Wrong value for key " + key, value,
-                ((ConfigurationNode) nodes.get(0)).getValue());
+        NodeList<ConfigurationNode> nodes = checkKey(key, name, 1);
+        assertEquals("Wrong value for key " + key, value, nodes.getValue(0,
+                handler));
     }
 
     /**
@@ -508,11 +533,12 @@
      * @param data the add data object
      * @param expected the expected path nodes
      */
-    private void checkNodePath(NodeAddData data, String[] expected)
+    private void checkNodePath(NodeAddData<ConfigurationNode> data,
+            String[] expected)
     {
         assertEquals("Wrong number of path nodes", expected.length, data
                 .getPathNodes().size());
-        Iterator it = data.getPathNodes().iterator();
+        Iterator<String> it = data.getPathNodes().iterator();
         for (int i = 0; i < expected.length; i++)
         {
             assertEquals("Wrong path node " + i, expected[i], it.next());