You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by oh...@apache.org on 2006/01/15 19:27:21 UTC

svn commit: r369247 [1/2] - in /jakarta/commons/proper/configuration/trunk: ./ src/java/org/apache/commons/configuration/tree/xpath/ src/test/org/apache/commons/configuration/tree/xpath/

Author: oheger
Date: Sun Jan 15 10:26:46 2006
New Revision: 369247

URL: http://svn.apache.org/viewcvs?rev=369247&view=rev
Log:
Initial implementation of an XPATH expression engine with helper classes required by JXPath

Added:
    jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/
    jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodeIteratorAttribute.java   (with props)
    jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodeIteratorBase.java   (with props)
    jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodeIteratorChildren.java   (with props)
    jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodePointer.java   (with props)
    jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodePointerFactory.java   (with props)
    jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/XPathExpressionEngine.java   (with props)
    jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/
    jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestConfigurationIteratorAttributes.java   (with props)
    jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestConfigurationNodeIteratorChildren.java   (with props)
    jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestConfigurationNodePointer.java   (with props)
    jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestConfigurationNodePointerFactory.java   (with props)
    jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestXPathExpressionEngine.java   (with props)
    jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/XPathTest.java   (with props)
Modified:
    jakarta/commons/proper/configuration/trunk/project.xml

Modified: jakarta/commons/proper/configuration/trunk/project.xml
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/configuration/trunk/project.xml?rev=369247&r1=369246&r2=369247&view=diff
==============================================================================
--- jakarta/commons/proper/configuration/trunk/project.xml (original)
+++ jakarta/commons/proper/configuration/trunk/project.xml Sun Jan 15 10:26:46 2006
@@ -267,6 +267,15 @@
     </dependency>
 
     <dependency>
+      <groupId>commons-jxpath</groupId>
+      <artifactId>commons-jxpath</artifactId>
+      <version>1.2</version>
+      <properties>
+        <war.bundle>true</war.bundle>
+      </properties>
+    </dependency>
+
+    <dependency>
       <groupId>xerces</groupId>
       <artifactId>xerces</artifactId>
       <version>2.2.1</version>
@@ -418,6 +427,7 @@
         <exclude>**/TestBasePropertiesConfiguration.java</exclude>
         <exclude>**/NonStringTestHolder.java</exclude>
         <exclude>**/TestAbstractConfiguration.java</exclude>
+        <exclude>**/XPathTest.java</exclude>
       </excludes>
       <resources>
         <resource>

Added: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodeIteratorAttribute.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodeIteratorAttribute.java?rev=369247&view=auto
==============================================================================
--- jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodeIteratorAttribute.java (added)
+++ jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodeIteratorAttribute.java Sun Jan 15 10:26:46 2006
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.configuration.tree.xpath;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.commons.configuration.tree.ConfigurationNode;
+import org.apache.commons.jxpath.ri.QName;
+import org.apache.commons.jxpath.ri.model.NodePointer;
+
+/**
+ * A specialized node iterator implementation that deals with attribute nodes.
+ * 
+ * @author Oliver Heger
+ * @version $Id$
+ */
+class ConfigurationNodeIteratorAttribute extends
+        ConfigurationNodeIteratorBase
+{
+    /** Constant for the wildcard node name.*/
+    private static final String WILDCARD = "*";
+    
+    /**
+     * Creates a new instance of <code>ConfigurationNodeIteratorAttribute</code>.
+     * @param parent the parent node pointer
+     * @param name the name of the selected attribute
+     */
+    public ConfigurationNodeIteratorAttribute(NodePointer parent, QName name)
+    {
+        super(parent, false);
+        initSubNodeList(createSubNodeList((ConfigurationNode) parent.getNode(), name));
+    }
+    
+    /**
+     * Determines which attributes are selected based on the passed in node
+     * name.
+     * @param node the current node
+     * @param name the name of the selected attribute
+     * @return a list with the selected attributes
+     */
+    protected List createSubNodeList(ConfigurationNode node, QName name)
+    {
+        if(name.getPrefix() != null)
+        {
+            // namespace prefixes are not supported
+            return Collections.EMPTY_LIST;
+        }
+        
+        List result = new ArrayList();
+        if(!WILDCARD.equals(name.getName()))
+        {
+            result.addAll(node.getAttributes(name.getName()));
+        }
+        else
+        {
+            result.addAll(node.getAttributes());
+        }
+        
+        return result;
+    }
+}

Propchange: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodeIteratorAttribute.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodeIteratorAttribute.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodeIteratorAttribute.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodeIteratorBase.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodeIteratorBase.java?rev=369247&view=auto
==============================================================================
--- jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodeIteratorBase.java (added)
+++ jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodeIteratorBase.java Sun Jan 15 10:26:46 2006
@@ -0,0 +1,195 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.configuration.tree.xpath;
+
+import java.util.List;
+
+import org.apache.commons.configuration.tree.ConfigurationNode;
+import org.apache.commons.jxpath.ri.model.NodeIterator;
+import org.apache.commons.jxpath.ri.model.NodePointer;
+
+/**
+ * <p>
+ * A base class for implementing iterators over configuration nodes.
+ * </p>
+ * <p>
+ * This class already provides common functionality for implementing the
+ * iteration process. Derived classes will implement specific behavior based on
+ * the concrete node type (child node or attribute node).
+ * </p>
+ *
+ * @since 1.3
+ * @author Oliver Heger
+ * @version $Id$
+ */
+abstract class ConfigurationNodeIteratorBase implements NodeIterator
+{
+    /** Stores the parent node pointer. */
+    private NodePointer parent;
+
+    /** Stores the list with the sub nodes. */
+    private List subNodes;
+
+    /** Stores the current position. */
+    private int position;
+
+    /** Stores the start offset of the iterator. */
+    private int startOffset;
+
+    /** Stores the reverse flag. */
+    private boolean reverse;
+
+    /**
+     * Creates a new instance of <code>ConfigurationNodeIteratorBase</code>
+     * and initializes it.
+     *
+     * @param parent the parent pointer
+     * @param reverse the reverse flag
+     */
+    protected ConfigurationNodeIteratorBase(NodePointer parent, boolean reverse)
+    {
+        this.parent = parent;
+        this.reverse = reverse;
+    }
+
+    /**
+     * Returns the position of the iteration.
+     *
+     * @return the position
+     */
+    public int getPosition()
+    {
+        return position;
+    }
+
+    /**
+     * Sets the position of the iteration.
+     *
+     * @param pos the new position
+     * @return a flag if this is a valid position
+     */
+    public boolean setPosition(int pos)
+    {
+        position = pos;
+        return pos >= 1 && pos <= getMaxPosition();
+    }
+
+    /**
+     * Returns the current node pointer.
+     *
+     * @return the current pointer in this iteration
+     */
+    public NodePointer getNodePointer()
+    {
+        if (getPosition() < 1 && !setPosition(1))
+        {
+            return null;
+        }
+
+        return createNodePointer((ConfigurationNode) subNodes
+                .get(positionToIndex(getPosition())));
+    }
+
+    /**
+     * Returns the parent node pointer.
+     *
+     * @return the parent node pointer
+     */
+    protected NodePointer getParent()
+    {
+        return parent;
+    }
+
+    /**
+     * Returns the start offset of the iteration.
+     *
+     * @return the start offset
+     */
+    protected int getStartOffset()
+    {
+        return startOffset;
+    }
+
+    /**
+     * Sets the start offset of the iteration. This is used when a start element
+     * was set.
+     *
+     * @param startOffset the start offset
+     */
+    protected void setStartOffset(int startOffset)
+    {
+        this.startOffset = startOffset;
+        if (reverse)
+        {
+            this.startOffset--;
+        }
+        else
+        {
+            this.startOffset++;
+        }
+    }
+
+    /**
+     * Initializes the list of sub nodes for the iteration. This method must be
+     * called during initialization phase.
+     *
+     * @param nodes the list with the sub nodes
+     */
+    protected void initSubNodeList(List nodes)
+    {
+        subNodes = nodes;
+        if (reverse)
+        {
+            setStartOffset(subNodes.size());
+        }
+    }
+
+    /**
+     * Returns the maximum position for this iterator.
+     *
+     * @return the maximum allowed position
+     */
+    protected int getMaxPosition()
+    {
+        return reverse ? getStartOffset() + 1 : subNodes.size()
+                - getStartOffset();
+    }
+
+    /**
+     * Creates the configuration node pointer for the current position. This
+     * method is called by <code>getNodePointer()</code>. Derived classes
+     * must create the correct pointer object.
+     *
+     * @param node the current configuration node
+     * @return the node pointer
+     */
+    protected NodePointer createNodePointer(ConfigurationNode node)
+    {
+        return new ConfigurationNodePointer(getParent(), node);
+    }
+
+    /**
+     * Returns the index in the data list for the given position. This method
+     * also checks the reverse flag.
+     *
+     * @param pos the position (1-based)
+     * @return the corresponding list index
+     */
+    protected int positionToIndex(int pos)
+    {
+        return (reverse ? 1 - pos : pos - 1) + getStartOffset();
+    }
+}

Propchange: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodeIteratorBase.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodeIteratorBase.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodeIteratorBase.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodeIteratorChildren.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodeIteratorChildren.java?rev=369247&view=auto
==============================================================================
--- jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodeIteratorChildren.java (added)
+++ jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodeIteratorChildren.java Sun Jan 15 10:26:46 2006
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.configuration.tree.xpath;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.commons.configuration.tree.ConfigurationNode;
+import org.apache.commons.jxpath.ri.Compiler;
+import org.apache.commons.jxpath.ri.QName;
+import org.apache.commons.jxpath.ri.compiler.NodeNameTest;
+import org.apache.commons.jxpath.ri.compiler.NodeTest;
+import org.apache.commons.jxpath.ri.compiler.NodeTypeTest;
+import org.apache.commons.jxpath.ri.model.NodePointer;
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * A specialized iterator implementation for the child nodes of a configuration
+ * node.
+ *
+ * @since 1.3
+ * @author Oliver Heger
+ * @version $Id$
+ */
+class ConfigurationNodeIteratorChildren extends ConfigurationNodeIteratorBase
+{
+    /**
+     * Creates a new instance of <code>ConfigurationNodeIteratorChildren</code>
+     * and initializes it.
+     *
+     * @param parent the parent pointer
+     * @param nodeTest the test selecting the sub nodes
+     * @param reverse the reverse flag
+     * @param startsWith the first element of the iteration
+     */
+    public ConfigurationNodeIteratorChildren(NodePointer parent,
+            NodeTest nodeTest, boolean reverse, NodePointer startsWith)
+    {
+        super(parent, reverse);
+        ConfigurationNode root = (ConfigurationNode) parent.getNode();
+        List childNodes = createSubNodeList(root, nodeTest);
+        initSubNodeList(childNodes);
+        if (startsWith != null)
+        {
+            setStartOffset(findStartIndex(root,
+                    (ConfigurationNode) startsWith.getNode()));
+        }
+    }
+
+    /**
+     * Creates the list with sub nodes. This method gets called during
+     * initialization phase. It finds out, based on the given test, which nodes
+     * must be iterated over.
+     *
+     * @param node the current node
+     * @param test the test object
+     * @return a list with the matching nodes
+     */
+    protected List createSubNodeList(ConfigurationNode node, NodeTest test)
+    {
+        List children = node.getChildren();
+
+        if (test == null)
+        {
+            return children;
+        }
+        else
+        {
+            if (test instanceof NodeNameTest)
+            {
+                NodeNameTest nameTest = (NodeNameTest) test;
+                QName name = nameTest.getNodeName();
+                if (name.getPrefix() == null)
+                {
+                    if (nameTest.isWildcard())
+                    {
+                        return children;
+                    }
+
+                    List result = new ArrayList();
+                    for (Iterator it = children.iterator(); it.hasNext();)
+                    {
+                        ConfigurationNode child = (ConfigurationNode) it.next();
+                        if (StringUtils.equals(name.getName(), child.getName()))
+                        {
+                            result.add(child);
+                        }
+                    }
+                    return result;
+                }
+            }
+
+            else if (test instanceof NodeTypeTest)
+            {
+                NodeTypeTest typeTest = (NodeTypeTest) test;
+                if (typeTest.getNodeType() == Compiler.NODE_TYPE_NODE
+                        || typeTest.getNodeType() == Compiler.NODE_TYPE_TEXT)
+                {
+                    return children;
+                }
+            }
+        }
+
+        return Collections.EMPTY_LIST;
+    }
+
+    /**
+     * Determines the start position of the iteration. Finds the index of the
+     * given start node in the children of the root node.
+     *
+     * @param node the root node
+     * @param startNode the start node
+     * @return the start node's index
+     */
+    protected int findStartIndex(ConfigurationNode node,
+            ConfigurationNode startNode)
+    {
+        for (int index = 0; index < node.getChildrenCount(); index++)
+        {
+            if (node.getChild(index) == startNode)
+            {
+                return index;
+            }
+        }
+
+        return -1;
+    }
+}

Propchange: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodeIteratorChildren.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodeIteratorChildren.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodeIteratorChildren.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodePointer.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodePointer.java?rev=369247&view=auto
==============================================================================
--- jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodePointer.java (added)
+++ jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodePointer.java Sun Jan 15 10:26:46 2006
@@ -0,0 +1,251 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.configuration.tree.xpath;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+
+import org.apache.commons.configuration.tree.ConfigurationNode;
+import org.apache.commons.jxpath.ri.Compiler;
+import org.apache.commons.jxpath.ri.QName;
+import org.apache.commons.jxpath.ri.compiler.NodeTest;
+import org.apache.commons.jxpath.ri.compiler.NodeTypeTest;
+import org.apache.commons.jxpath.ri.model.NodeIterator;
+import org.apache.commons.jxpath.ri.model.NodePointer;
+
+/**
+ * <p>
+ * A specific <code>NodePointer</code> implementation for configuration nodes.
+ * </p>
+ * <p>
+ * This is needed for queries using JXPath.
+ * </p>
+ *
+ * @since 1.3
+ * @author Oliver Heger
+ * @version $Id$
+ */
+class ConfigurationNodePointer extends NodePointer
+{
+    /** Stores the associated configuration node. */
+    private ConfigurationNode node;
+
+    /**
+     * Creates a new instance of <code>ConfigurationNodePointer</code>.
+     *
+     * @param node the node
+     * @param locale the locale
+     */
+    public ConfigurationNodePointer(ConfigurationNode node, Locale locale)
+    {
+        super(null, locale);
+        this.node = node;
+    }
+
+    /**
+     * Creates a new instance of <code>ConfigurationNodePointer</code> and
+     * initializes it with its parent pointer.
+     *
+     * @param parent the parent pointer
+     * @param node the associated node
+     */
+    public ConfigurationNodePointer(NodePointer parent, ConfigurationNode node)
+    {
+        super(parent);
+        this.node = node;
+    }
+
+    /**
+     * Returns a flag whether this node is a leaf. This is the case if there are
+     * no child nodes.
+     *
+     * @return a flag if this node is a leaf
+     */
+    public boolean isLeaf()
+    {
+        return node.getChildrenCount() < 1;
+    }
+
+    /**
+     * Returns a flag if this node is a collection. This is not the case.
+     *
+     * @return the collection flag
+     */
+    public boolean isCollection()
+    {
+        return false;
+    }
+
+    /**
+     * Returns this node's length. This is always 1.
+     *
+     * @return the node's length
+     */
+    public int getLength()
+    {
+        return 1;
+    }
+
+    /**
+     * Checks whether this node pointer refers to an attribute node. This method
+     * checks the attribute flag of the associated configuration node.
+     *
+     * @return the attribute flag
+     */
+    public boolean isAttribute()
+    {
+        return node.isAttribute();
+    }
+
+    /**
+     * Returns this node's name.
+     *
+     * @return the name
+     */
+    public QName getName()
+    {
+        return new QName(null, node.getName());
+    }
+
+    /**
+     * Returns this node's base value. This is the associated configuration
+     * node.
+     *
+     * @return the base value
+     */
+    public Object getBaseValue()
+    {
+        return node;
+    }
+
+    /**
+     * Returns the immediate node. This is the associated configuration node.
+     *
+     * @return the immediate node
+     */
+    public Object getImmediateNode()
+    {
+        return node;
+    }
+
+    /**
+     * Returns the value of this node.
+     *
+     * @return the represented node's value
+     */
+    public Object getValue()
+    {
+        return node.getValue();
+    }
+
+    /**
+     * Sets the value of this node.
+     *
+     * @param value the new value
+     */
+    public void setValue(Object value)
+    {
+        node.setValue(value);
+    }
+
+    /**
+     * Compares two child node pointers.
+     *
+     * @param pointer1 one pointer
+     * @param pointer2 another pointer
+     * @return a flag, which pointer should be sorted first
+     */
+    public int compareChildNodePointers(NodePointer pointer1,
+            NodePointer pointer2)
+    {
+        ConfigurationNode node1 = (ConfigurationNode) pointer1.getBaseValue();
+        ConfigurationNode node2 = (ConfigurationNode) pointer2.getBaseValue();
+
+        // attributes will be sorted before child nodes
+        if (node1.isAttribute() && !node2.isAttribute())
+        {
+            return -1;
+        }
+        else if (node2.isAttribute() && !node1.isAttribute())
+        {
+            return 1;
+        }
+
+        else
+        {
+            // sort based on the occurrence in the sub node list
+            List subNodes = node1.isAttribute() ? node.getAttributes() : node
+                    .getChildren();
+            for (Iterator it = subNodes.iterator(); it.hasNext();)
+            {
+                ConfigurationNode child = (ConfigurationNode) it.next();
+                if (child == node1)
+                {
+                    return -1;
+                }
+                else if (child == node2)
+                {
+                    return 1;
+                }
+            }
+            return 0; // should not happen
+        }
+    }
+
+    /**
+     * Returns an iterator for the attributes that match the given name.
+     *
+     * @param name the attribute name
+     * @return the iterator for the attributes
+     */
+    public NodeIterator attributeIterator(QName name)
+    {
+        return new ConfigurationNodeIteratorAttribute(this, name);
+    }
+
+    /**
+     * Returns an iterator for the children of this pointer that match the given
+     * test object.
+     *
+     * @param test the test object
+     * @param reverse the reverse flag
+     * @param startWith the start value of the iteration
+     */
+    public NodeIterator childIterator(NodeTest test, boolean reverse,
+            NodePointer startWith)
+    {
+        return new ConfigurationNodeIteratorChildren(this, test, reverse,
+                startWith);
+    }
+
+    /**
+     * Tests if this node matches the given test. Configuration nodes are text
+     * nodes, too because they can contain a value.
+     *
+     * @param test the test object
+     * @return a flag if this node corresponds to the test
+     */
+    public boolean testNode(NodeTest test)
+    {
+        if (test instanceof NodeTypeTest
+                && ((NodeTypeTest) test).getNodeType() == Compiler.NODE_TYPE_TEXT)
+        {
+            return true;
+        }
+        return super.testNode(test);
+    }
+}

Propchange: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodePointer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodePointer.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodePointer.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodePointerFactory.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodePointerFactory.java?rev=369247&view=auto
==============================================================================
--- jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodePointerFactory.java (added)
+++ jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodePointerFactory.java Sun Jan 15 10:26:46 2006
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.configuration.tree.xpath;
+
+import java.util.Locale;
+
+import org.apache.commons.configuration.tree.ConfigurationNode;
+import org.apache.commons.jxpath.ri.QName;
+import org.apache.commons.jxpath.ri.model.NodePointer;
+import org.apache.commons.jxpath.ri.model.NodePointerFactory;
+
+/**
+ * Implementation of the <code>NodePointerFactory</code> interface for
+ * configuration nodes.
+ *
+ * @since 1.3
+ * @author Oliver Heger
+ * @version $Id$
+ */
+public class ConfigurationNodePointerFactory implements NodePointerFactory
+{
+    /** Constant for the order of this factory. */
+    public static final int CONFIGURATION_NODE_POINTER_FACTORY_ORDER = 200;
+
+    /**
+     * Returns the order of this factory between other factories.
+     *
+     * @return this order's factory
+     */
+    public int getOrder()
+    {
+        return CONFIGURATION_NODE_POINTER_FACTORY_ORDER;
+    }
+
+    /**
+     * Creates a node pointer for the specified bean. If the bean is a
+     * configuration node, a corresponding pointer is returned.
+     *
+     * @param name the name of the node
+     * @param bean the bean
+     * @param locale the locale
+     * @return a pointer for a configuration node if the bean is such a node
+     */
+    public NodePointer createNodePointer(QName name, Object bean, Locale locale)
+    {
+        if (bean instanceof ConfigurationNode)
+        {
+            return new ConfigurationNodePointer((ConfigurationNode) bean,
+                    locale);
+        }
+        return null;
+    }
+
+    /**
+     * Creates a node pointer for the specified bean. If the bean is a
+     * configuration node, a corresponding pointer is returned.
+     *
+     * @param parent the parent node
+     * @param name the name
+     * @param bean the bean
+     * @return a pointer for a configuration node if the bean is such a node
+     */
+    public NodePointer createNodePointer(NodePointer parent, QName name,
+            Object bean)
+    {
+        if (bean instanceof ConfigurationNode)
+        {
+            return new ConfigurationNodePointer(parent,
+                    (ConfigurationNode) bean);
+        }
+        return null;
+    }
+}

Propchange: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodePointerFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodePointerFactory.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodePointerFactory.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/XPathExpressionEngine.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/XPathExpressionEngine.java?rev=369247&view=auto
==============================================================================
--- jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/XPathExpressionEngine.java (added)
+++ jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/XPathExpressionEngine.java Sun Jan 15 10:26:46 2006
@@ -0,0 +1,330 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.configuration.tree.xpath;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.apache.commons.configuration.tree.ConfigurationNode;
+import org.apache.commons.configuration.tree.ExpressionEngine;
+import org.apache.commons.configuration.tree.NodeAddData;
+import org.apache.commons.jxpath.JXPathContext;
+import org.apache.commons.jxpath.ri.JXPathContextReferenceImpl;
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * <p>
+ * A specialized implementation of the <code>ExpressionEngine</code> interface
+ * that is able to evaluate XPATH expressions.
+ * </p>
+ * <p>
+ * This class makes use of <a href="http://jakarta.apache.org/commons/jxpath/">
+ * Commons JXPath</a> for handling XPath expressions and mapping them to the
+ * nodes of a hierarchical configuration. This makes the rich and powerfull
+ * XPATH syntax available for accessing properties from a configuration object.
+ * </p>
+ * <p>
+ * For selecting properties arbitrary XPATH expressions can be used, which
+ * select single or multiple configuration nodes. The associated
+ * <code>Configuration</code> instance will directly pass the specified
+ * property keys into this engine. If a key is not syntactically correct, an
+ * exception will be thrown.
+ * </p>
+ * <p>
+ * For adding new properties, this expression engine uses a specific syntax: the
+ * &quot;key&quot; of a new property must consist of two parts that are
+ * separated by whitespace:
+ * <ol>
+ * <li>An XPATH expression selecting a single node, to which the new element(s)
+ * are to be added. This can be an arbitrary complex expression, but it must
+ * select exactly one node, otherwise an exception will be thrown.</li>
+ * <li>The name of the new element(s) to be added below this parent node. Here
+ * either a single node name or a complete path of nodes (separated by the
+ * &quot;/&quot; character) can be specified.</li>
+ * </ol>
+ * Some examples for valid keys that can be passed into the configuration's
+ * <code>addProperty()</code> method follow:
+ * </p>
+ * <p>
+ *
+ * <pre>
+ * &quot;/tables/table[1] type&quot;
+ * </pre>
+ *
+ * </p>
+ * <p>
+ * This will add a new <code>type</code> node as a child of the first
+ * <code>table</code> element.
+ * </p>
+ * <p>
+ *
+ * <pre>
+ * &quot;/tables/table[1] @type&quot;
+ * </pre>
+ *
+ * </p>
+ * <p>
+ * Similar to the example above, but this time a new attribute named
+ * <code>type</code> will be added to the first <code>table</code> element.
+ * </p>
+ * <p>
+ *
+ * <pre>
+ * &quot;/tables table/fields/field/name&quot;
+ * </pre>
+ *
+ * </p>
+ * <p>
+ * This example shows how a complex path can be added. Parent node is the
+ * <code>tables</code> element. Here a new branch consisting of the nodes
+ * <code>table</code>, <code>fields</code>, <code>field</code>, and
+ * <code>name</code> will be added.
+ * </p>
+ *
+ * @since 1.3
+ * @author Oliver Heger
+ * @version $Id$
+ */
+public class XPathExpressionEngine implements ExpressionEngine
+{
+    /** Constant for the path delimiter. */
+    static final String PATH_DELIMITER = "/";
+
+    /** Constant for the attribute delimiter. */
+    static final String ATTR_DELIMITER = "@";
+
+    /** Constant for the delimiters for splitting node paths. */
+    private static final String NODE_PATH_DELIMITERS = PATH_DELIMITER
+            + ATTR_DELIMITER;
+
+    /**
+     * Executes a query. The passed in property key is directly passed to a
+     * JXPath context.
+     *
+     * @param root the configuration root node
+     * @param key the query to be executed
+     * @return a list with the nodes that are selected by the query
+     */
+    public List query(ConfigurationNode root, String key)
+    {
+        if (StringUtils.isEmpty(key))
+        {
+            List result = new ArrayList(1);
+            result.add(root);
+            return result;
+        }
+        else
+        {
+            JXPathContext context = createContext(root, key);
+            List result = context.selectNodes(key);
+            return (result != null) ? result : Collections.EMPTY_LIST;
+        }
+    }
+
+    /**
+     * Returns a (canonic) key for the given node based on the parent's key.
+     * This implementation will create an XPATH expression that selects the
+     * given node (under the assumption that the passed in parent key is valid).
+     * As the <code>nodeKey()</code> implementation of
+     * <code>{@link org.apache.commons.configuration.tree.DefaultExpressionEngine DefaultExpressionEngine}</code>
+     * this method will not return indices for nodes. So all child nodes of a
+     * given parent whith the same name will have the same key.
+     *
+     * @param node the node for which a key is to be constructed
+     * @param parentKey the key of the parent node
+     * @return the key for the given node
+     */
+    public String nodeKey(ConfigurationNode node, String parentKey)
+    {
+        if (parentKey == null)
+        {
+            // name of the root node
+            return StringUtils.EMPTY;
+        }
+        else if (node.getName() == null)
+        {
+            // paranoia check for undefined node names
+            return parentKey;
+        }
+
+        else
+        {
+            StringBuffer buf = new StringBuffer(parentKey.length()
+                    + node.getName().length() + PATH_DELIMITER.length());
+            if (parentKey.length() > 0)
+            {
+                buf.append(parentKey);
+                if (!node.isAttribute())
+                {
+                    buf.append(PATH_DELIMITER);
+                }
+            }
+            if (node.isAttribute())
+            {
+                buf.append(ATTR_DELIMITER);
+            }
+            buf.append(node.getName());
+            return buf.toString();
+        }
+    }
+
+    /**
+     * Prepares an add operation for a configuration property. The expected
+     * format of the passed in key is explained in the class comment.
+     *
+     * @param root the configuration's root node
+     * @param key the key describing the target of the add operation and the
+     * path of the new node
+     * @return a data object to be evaluated by the calling configuration object
+     */
+    public NodeAddData prepareAdd(ConfigurationNode root, String key)
+    {
+        if (key == null)
+        {
+            throw new IllegalArgumentException(
+                    "prepareAdd: key must not be null!");
+        }
+
+        int index = key.length() - 1;
+        while (index >= 0 && !Character.isWhitespace(key.charAt(index)))
+        {
+            index--;
+        }
+        if (index < 0)
+        {
+            throw new IllegalArgumentException(
+                    "prepareAdd: Passed in key must contain a whitespace!");
+        }
+
+        List nodes = query(root, key.substring(0, index).trim());
+        if (nodes.size() != 1)
+        {
+            throw new IllegalArgumentException(
+                    "prepareAdd: key must select exactly one target node!");
+        }
+
+        NodeAddData data = new NodeAddData();
+        data.setParent((ConfigurationNode) nodes.get(0));
+        initNodeAddData(data, key.substring(index).trim());
+        return data;
+    }
+
+    /**
+     * Creates the <code>JXPathContext</code> used for executing a query. This
+     * method will create a new context and ensure that it is correctly
+     * initialized.
+     *
+     * @param root the configuration root node
+     * @param key the key to be queried
+     * @return the new context
+     */
+    protected JXPathContext createContext(ConfigurationNode root, String key)
+    {
+        JXPathContext context = JXPathContext.newContext(root);
+        context.setLenient(true);
+        return context;
+    }
+
+    /**
+     * Initializes most properties of a <code>NodeAddData</code> object. This
+     * method is called by <code>prepareAdd()</code> after the parent node has
+     * been found. Its task is to interprete the passed in path of the new node.
+     *
+     * @param data the data object to initialize
+     * @param path the path of the new node
+     */
+    protected void initNodeAddData(NodeAddData data, String path)
+    {
+        String lastComponent = null;
+        boolean attr = false, first = true;
+
+        StringTokenizer tok = new StringTokenizer(path, NODE_PATH_DELIMITERS,
+                true);
+        while (tok.hasMoreTokens())
+        {
+            String token = tok.nextToken();
+            if (PATH_DELIMITER.equals(token))
+            {
+                if (attr)
+                {
+                    invalidPath(path, " contains an attribute"
+                            + " delimiter at an unallowed position.");
+                }
+                if (lastComponent == null)
+                {
+                    invalidPath(path,
+                            " contains a '/' at an unallowed position.");
+                }
+                data.addPathNode(lastComponent);
+                lastComponent = null;
+            }
+
+            else if (ATTR_DELIMITER.equals(token))
+            {
+                if (attr)
+                {
+                    invalidPath(path,
+                            " contains multiple attribute delimiters.");
+                }
+                if (lastComponent == null && !first)
+                {
+                    invalidPath(path,
+                            " contains an attribute delimiter at an unallowed position.");
+                }
+                if (lastComponent != null)
+                {
+                    data.addPathNode(lastComponent);
+                }
+                attr = true;
+                lastComponent = null;
+            }
+
+            else
+            {
+                lastComponent = token;
+            }
+            first = false;
+        }
+
+        if (lastComponent == null)
+        {
+            invalidPath(path, "contains no components.");
+        }
+        data.setNewNodeName(lastComponent);
+        data.setAttribute(attr);
+    }
+
+    /**
+     * Helper method for throwing an exception about an invalid path.
+     *
+     * @param path the invalid path
+     * @param msg the exception message
+     */
+    private void invalidPath(String path, String msg)
+    {
+        throw new IllegalArgumentException("Invalid node path: \"" + path
+                + "\" " + msg);
+    }
+
+    // static initializer: registers the configuration node pointer factory
+    static
+    {
+        JXPathContextReferenceImpl
+                .addNodePointerFactory(new ConfigurationNodePointerFactory());
+    }
+}

Propchange: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/XPathExpressionEngine.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/XPathExpressionEngine.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/XPathExpressionEngine.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestConfigurationIteratorAttributes.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestConfigurationIteratorAttributes.java?rev=369247&view=auto
==============================================================================
--- jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestConfigurationIteratorAttributes.java (added)
+++ jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestConfigurationIteratorAttributes.java Sun Jan 15 10:26:46 2006
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.configuration.tree.xpath;
+
+import java.util.List;
+import java.util.Locale;
+
+import org.apache.commons.configuration.tree.ConfigurationNode;
+import org.apache.commons.configuration.tree.DefaultConfigurationNode;
+import org.apache.commons.jxpath.ri.QName;
+import org.apache.commons.jxpath.ri.model.NodePointer;
+
+/**
+ * Test class for ConfigurationIteratorAttributes.
+ * 
+ * @author Oliver Heger
+ * @version $Id$
+ */
+public class TestConfigurationIteratorAttributes extends XPathTest
+{
+    /** Constant for the name of another test attribute.*/
+    private static final String TEST_ATTR = "test";
+    
+    /** Stores the node pointer of the test node.*/
+    NodePointer pointer;
+    
+    protected void setUp() throws Exception
+    {
+        super.setUp();
+        
+        // Adds further attributes to the test node
+        ConfigurationNode testNode = root.getChild(1);
+        testNode.addAttribute(new DefaultConfigurationNode(TEST_ATTR, "yes"));
+        pointer = new ConfigurationNodePointer(testNode, Locale.getDefault());
+    }
+
+    /**
+     * Tests to iterate over all attributes.
+     */
+    public void testIterateAllAttributes()
+    {
+        ConfigurationNodeIteratorAttribute it = new ConfigurationNodeIteratorAttribute(pointer, new QName(null, "*"));
+        assertEquals("Wrong number of attributes", 2, iteratorSize(it));
+        List attrs = iterationElements(it);
+        assertEquals("Wrong first attribute", ATTR_NAME, ((ConfigurationNode) attrs.get(0)).getName());
+        assertEquals("Wrong first attribute", TEST_ATTR, ((ConfigurationNode) attrs.get(1)).getName());
+    }
+    
+    /**
+     * Tests to iterate over attributes with a specific name.
+     */
+    public void testIterateSpecificAttribute()
+    {
+        ConfigurationNodeIteratorAttribute it = new ConfigurationNodeIteratorAttribute(pointer, new QName(null, TEST_ATTR));
+        assertEquals("Wrong number of attributes", 1, iteratorSize(it));
+        assertEquals("Wrong attribute", TEST_ATTR, ((ConfigurationNode) iterationElements(it).get(0)).getName());
+    }
+    
+    /**
+     * Tests to iterate over non existing attributes.
+     */
+    public void testIterateUnknownAttribute()
+    {
+        ConfigurationNodeIteratorAttribute it = new ConfigurationNodeIteratorAttribute(pointer, new QName(null, "unknown"));
+        assertEquals("Found attributes", 0, iteratorSize(it));
+    }
+    
+    /**
+     * Tests iteration when a namespace is specified. This is not supported, so
+     * the iteration should be empty.
+     */
+    public void testIterateNamespace()
+    {
+        ConfigurationNodeIteratorAttribute it = new ConfigurationNodeIteratorAttribute(pointer, new QName("test", "*"));
+        assertEquals("Found attributes", 0, iteratorSize(it));
+    }
+}

Propchange: jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestConfigurationIteratorAttributes.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestConfigurationIteratorAttributes.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestConfigurationIteratorAttributes.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestConfigurationNodeIteratorChildren.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestConfigurationNodeIteratorChildren.java?rev=369247&view=auto
==============================================================================
--- jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestConfigurationNodeIteratorChildren.java (added)
+++ jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestConfigurationNodeIteratorChildren.java Sun Jan 15 10:26:46 2006
@@ -0,0 +1,227 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.configuration.tree.xpath;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+
+import org.apache.commons.configuration.tree.ConfigurationNode;
+import org.apache.commons.configuration.tree.DefaultConfigurationNode;
+import org.apache.commons.jxpath.ri.Compiler;
+import org.apache.commons.jxpath.ri.QName;
+import org.apache.commons.jxpath.ri.compiler.NodeNameTest;
+import org.apache.commons.jxpath.ri.compiler.NodeTest;
+import org.apache.commons.jxpath.ri.compiler.NodeTypeTest;
+import org.apache.commons.jxpath.ri.compiler.ProcessingInstructionTest;
+import org.apache.commons.jxpath.ri.model.NodeIterator;
+import org.apache.commons.jxpath.ri.model.NodePointer;
+
+/**
+ * Test class for ConfigurationNodeIteratorChildren.
+ *
+ * @author Oliver Heger
+ * @version $Id$
+ */
+public class TestConfigurationNodeIteratorChildren extends XPathTest
+{
+    /** Stores the node pointer to the root node. */
+    NodePointer rootPointer;
+
+    protected void setUp() throws Exception
+    {
+        super.setUp();
+        rootPointer = new ConfigurationNodePointer(root, Locale.getDefault());
+    }
+
+    /**
+     * Tests to iterate over all children of the root node.
+     */
+    public void testIterateAllChildren()
+    {
+        ConfigurationNodeIteratorChildren it = new ConfigurationNodeIteratorChildren(
+                rootPointer, null, false, null);
+        assertEquals("Wrong number of elements", CHILD_COUNT, iteratorSize(it));
+        checkValues(it, new int[]
+        { 1, 2, 3, 4, 5 });
+    }
+
+    /**
+     * Tests a reverse iteration.
+     */
+    public void testIterateReverse()
+    {
+        ConfigurationNodeIteratorChildren it = new ConfigurationNodeIteratorChildren(
+                rootPointer, null, true, null);
+        assertEquals("Wrong number of elements", CHILD_COUNT, iteratorSize(it));
+        checkValues(it, new int[]
+        { 5, 4, 3, 2, 1 });
+    }
+
+    /**
+     * Tests using a node test with a wildcard name.
+     */
+    public void testIterateWithWildcardTest()
+    {
+        NodeNameTest test = new NodeNameTest(new QName(null, "*"));
+        ConfigurationNodeIteratorChildren it = new ConfigurationNodeIteratorChildren(
+                rootPointer, test, false, null);
+        assertEquals("Wrong number of elements", CHILD_COUNT, iteratorSize(it));
+    }
+
+    /**
+     * Tests using a node test that defines a namespace prefix. Because
+     * namespaces are not supported, no elements should be in the iteration.
+     */
+    public void testIterateWithPrefixTest()
+    {
+        NodeNameTest test = new NodeNameTest(new QName("prefix", "*"));
+        ConfigurationNodeIteratorChildren it = new ConfigurationNodeIteratorChildren(
+                rootPointer, test, false, null);
+        assertNull("Undefined node pointer not returned", it.getNodePointer());
+        assertEquals("Prefix was not evaluated", 0, iteratorSize(it));
+    }
+
+    /**
+     * Tests using a node test that selects a certain sub node name.
+     */
+    public void testIterateWithNameTest()
+    {
+        NodeNameTest test = new NodeNameTest(new QName(null, CHILD_NAME2));
+        ConfigurationNodeIteratorChildren it = new ConfigurationNodeIteratorChildren(
+                rootPointer, test, false, null);
+        assertTrue("No children found", iteratorSize(it) > 0);
+        for (Iterator elemIt = iterationElements(it).iterator(); elemIt
+                .hasNext();)
+        {
+            assertEquals("Wrong child element", CHILD_NAME2,
+                    ((ConfigurationNode) elemIt.next()).getName());
+        }
+    }
+
+    /**
+     * Tests using a not supported test class. This should yield an empty
+     * iteration.
+     */
+    public void testIterateWithUnknownTest()
+    {
+        NodeTest test = new ProcessingInstructionTest("test");
+        ConfigurationNodeIteratorChildren it = new ConfigurationNodeIteratorChildren(
+                rootPointer, test, false, null);
+        assertEquals("Unknown test was not evaluated", 0, iteratorSize(it));
+    }
+
+    /**
+     * Tests using a type test for nodes. This should return all nodes.
+     */
+    public void testIterateWithNodeType()
+    {
+        NodeTypeTest test = new NodeTypeTest(Compiler.NODE_TYPE_NODE);
+        ConfigurationNodeIteratorChildren it = new ConfigurationNodeIteratorChildren(
+                rootPointer, test, false, null);
+        assertEquals("Node type not evaluated", CHILD_COUNT, iteratorSize(it));
+    }
+
+    /**
+     * Tests using a type test for a non supported type. This should return an
+     * empty iteration.
+     */
+    public void testIterateWithUnknownType()
+    {
+        NodeTypeTest test = new NodeTypeTest(Compiler.NODE_TYPE_COMMENT);
+        ConfigurationNodeIteratorChildren it = new ConfigurationNodeIteratorChildren(
+                rootPointer, test, false, null);
+        assertEquals("Unknown node type not evaluated", 0, iteratorSize(it));
+    }
+
+    /**
+     * Tests defining a start node for the iteration.
+     */
+    public void testIterateStartsWith()
+    {
+        NodePointer childPointer = new ConfigurationNodePointer(rootPointer,
+                root.getChild(2));
+        ConfigurationNodeIteratorChildren it = new ConfigurationNodeIteratorChildren(
+                rootPointer, null, false, childPointer);
+        assertEquals("Wrong start position", 0, it.getPosition());
+        List nodes = iterationElements(it);
+        assertEquals("Wrong size of iteration", CHILD_COUNT - 3, nodes.size());
+        int index = 4;
+        for (Iterator it2 = nodes.iterator(); it2.hasNext(); index++)
+        {
+            ConfigurationNode node = (ConfigurationNode) it2.next();
+            assertEquals("Wrong node value", String.valueOf(index), node
+                    .getValue());
+        }
+    }
+
+    /**
+     * Tests defining a start node for a reverse iteration.
+     */
+    public void testIterateStartsWithReverse()
+    {
+        NodePointer childPointer = new ConfigurationNodePointer(rootPointer,
+                root.getChild(3));
+        ConfigurationNodeIteratorChildren it = new ConfigurationNodeIteratorChildren(
+                rootPointer, null, true, childPointer);
+        int value = 3;
+        for (int index = 1; it.setPosition(index); index++, value--)
+        {
+            ConfigurationNode node = (ConfigurationNode) it.getNodePointer()
+                    .getNode();
+            assertEquals("Incorrect value at index " + index, String
+                    .valueOf(value), node.getValue());
+        }
+        assertEquals("Iteration ended not at end node", 0, value);
+    }
+
+    /**
+     * Tests iteration with an invalid start node. This should cause the
+     * iteration to start at the first position.
+     */
+    public void testIterateStartsWithInvalid()
+    {
+        NodePointer childPointer = new ConfigurationNodePointer(rootPointer,
+                new DefaultConfigurationNode("newNode"));
+        ConfigurationNodeIteratorChildren it = new ConfigurationNodeIteratorChildren(
+                rootPointer, null, false, childPointer);
+        assertEquals("Wrong size of iteration", CHILD_COUNT, iteratorSize(it));
+        it.setPosition(1);
+        ConfigurationNode node = (ConfigurationNode) it.getNodePointer()
+                .getNode();
+        assertEquals("Wrong start node", "1", node.getValue());
+    }
+
+    /**
+     * Helper method for checking the values of the nodes returned by an
+     * iterator. Because the values indicate the order of the child nodes with
+     * this test it can be checked whether the nodes were returned in the
+     * correct order.
+     *
+     * @param iterator the iterator
+     * @param expectedIndices an array with the expected indices
+     */
+    private void checkValues(NodeIterator iterator, int[] expectedIndices)
+    {
+        List nodes = iterationElements(iterator);
+        for (int i = 0; i < expectedIndices.length; i++)
+        {
+            ConfigurationNode child = (ConfigurationNode) nodes.get(i);
+            assertTrue("Wrong index value for child " + i, child.getValue()
+                    .toString().endsWith(String.valueOf(expectedIndices[i])));
+        }
+    }
+}

Propchange: jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestConfigurationNodeIteratorChildren.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestConfigurationNodeIteratorChildren.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestConfigurationNodeIteratorChildren.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestConfigurationNodePointer.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestConfigurationNodePointer.java?rev=369247&view=auto
==============================================================================
--- jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestConfigurationNodePointer.java (added)
+++ jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestConfigurationNodePointer.java Sun Jan 15 10:26:46 2006
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.configuration.tree.xpath;
+
+import java.util.Locale;
+
+import org.apache.commons.configuration.tree.ConfigurationNode;
+import org.apache.commons.configuration.tree.DefaultConfigurationNode;
+import org.apache.commons.jxpath.ri.QName;
+import org.apache.commons.jxpath.ri.model.NodeIterator;
+import org.apache.commons.jxpath.ri.model.NodePointer;
+
+/**
+ * Test class for ConfigurationNodePointer.
+ *
+ * @author Oliver Heger
+ * @version $Id$
+ */
+public class TestConfigurationNodePointer extends XPathTest
+{
+    /** Stores the node pointer to be tested. */
+    NodePointer pointer;
+
+    protected void setUp() throws Exception
+    {
+        super.setUp();
+        pointer = new ConfigurationNodePointer(root, Locale.getDefault());
+    }
+
+    /**
+     * Tests comparing child node pointers for child nodes.
+     */
+    public void testCompareChildNodePointersChildren()
+    {
+        NodePointer p1 = new ConfigurationNodePointer(pointer, root.getChild(1));
+        NodePointer p2 = new ConfigurationNodePointer(pointer, root.getChild(3));
+        assertEquals("Incorrect order", -1, pointer.compareChildNodePointers(
+                p1, p2));
+        assertEquals("Incorrect symmetric order", 1, pointer
+                .compareChildNodePointers(p2, p1));
+    }
+
+    /**
+     * Tests comparing child node pointers for attribute nodes.
+     */
+    public void testCompareChildNodePointersAttributes()
+    {
+        root.addAttribute(new DefaultConfigurationNode("attr1", "test1"));
+        root.addAttribute(new DefaultConfigurationNode("attr2", "test2"));
+        NodePointer p1 = new ConfigurationNodePointer(pointer, root
+                .getAttribute(0));
+        NodePointer p2 = new ConfigurationNodePointer(pointer, root
+                .getAttribute(1));
+        assertEquals("Incorrect order", -1, pointer.compareChildNodePointers(
+                p1, p2));
+        assertEquals("Incorrect symmetric order", 1, pointer
+                .compareChildNodePointers(p2, p1));
+    }
+
+    /**
+     * tests comparing child node pointers for both child and attribute nodes.
+     */
+    public void testCompareChildNodePointersChildAndAttribute()
+    {
+        root.addAttribute(new DefaultConfigurationNode("attr1", "test1"));
+        NodePointer p1 = new ConfigurationNodePointer(pointer, root.getChild(2));
+        NodePointer p2 = new ConfigurationNodePointer(pointer, root
+                .getAttribute(0));
+        assertEquals("Incorrect order for attributes", 1, pointer
+                .compareChildNodePointers(p1, p2));
+        assertEquals("Incorrect symmetric order for attributes", -1, pointer
+                .compareChildNodePointers(p2, p1));
+    }
+
+    /**
+     * Tests comparing child node pointers for child nodes that do not belong to
+     * the parent node.
+     */
+    public void testCompareChildNodePointersInvalidChildren()
+    {
+        ConfigurationNode node = root.getChild(1);
+        NodePointer p1 = new ConfigurationNodePointer(pointer, node.getChild(1));
+        NodePointer p2 = new ConfigurationNodePointer(pointer, node.getChild(3));
+        assertEquals("Non child nodes could be sorted", 0, pointer
+                .compareChildNodePointers(p1, p2));
+        assertEquals("Non child nodes could be sorted symmetrically", 0,
+                pointer.compareChildNodePointers(p2, p1));
+    }
+
+    /**
+     * Tests the attribute flag.
+     */
+    public void testIsAttribute()
+    {
+        ConfigurationNode node = new DefaultConfigurationNode("test", "testval");
+        NodePointer p = new ConfigurationNodePointer(pointer, node);
+        assertFalse("Node is an attribute", p.isAttribute());
+        node.setAttribute(true);
+        assertTrue("Node is no attribute", p.isAttribute());
+    }
+
+    /**
+     * Tests if leaves in the tree are correctly detected.
+     */
+    public void testIsLeave()
+    {
+        assertFalse("Root node is leaf", pointer.isLeaf());
+
+        NodePointer p = pointer;
+        while (!p.isLeaf())
+        {
+            ConfigurationNode node = (ConfigurationNode) p.getNode();
+            assertTrue("Node has no children", node.getChildrenCount() > 0);
+            p = new ConfigurationNodePointer(p, node.getChild(0));
+        }
+        assertTrue("Node has children", ((ConfigurationNode) p.getNode())
+                .getChildrenCount() == 0);
+    }
+
+    /**
+     * Tests the iterators returned by the node pointer.
+     */
+    public void testIterators()
+    {
+        checkIterators(pointer);
+    }
+
+    /**
+     * Recursive helper method for testing the returned iterators.
+     *
+     * @param p the node pointer to test
+     */
+    private void checkIterators(NodePointer p)
+    {
+        ConfigurationNode node = (ConfigurationNode) p.getNode();
+        NodeIterator it = p.childIterator(null, false, null);
+        assertEquals("Iterator count differs from children count", node
+                .getChildrenCount(), iteratorSize(it));
+
+        for (int index = 1; it.setPosition(index); index++)
+        {
+            NodePointer pchild = it.getNodePointer();
+            assertEquals("Wrong child", node.getChild(index - 1), pchild
+                    .getNode());
+            checkIterators(pchild);
+        }
+
+        it = p.attributeIterator(new QName(null, "*"));
+        assertEquals("Iterator count differs from attribute count", node
+                .getAttributeCount(), iteratorSize(it));
+        for (int index = 1; it.setPosition(index); index++)
+        {
+            NodePointer pattr = it.getNodePointer();
+            assertTrue("Node pointer is no attribute", pattr.isAttribute());
+            assertEquals("Wrong attribute", node.getAttribute(index - 1), pattr
+                    .getNode());
+            checkIterators(pattr);
+        }
+    }
+}

Propchange: jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestConfigurationNodePointer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestConfigurationNodePointer.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestConfigurationNodePointer.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestConfigurationNodePointerFactory.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestConfigurationNodePointerFactory.java?rev=369247&view=auto
==============================================================================
--- jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestConfigurationNodePointerFactory.java (added)
+++ jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestConfigurationNodePointerFactory.java Sun Jan 15 10:26:46 2006
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.configuration.tree.xpath;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.commons.configuration.tree.ConfigurationNode;
+import org.apache.commons.configuration.tree.DefaultConfigurationNode;
+import org.apache.commons.jxpath.JXPathContext;
+import org.apache.commons.jxpath.ri.JXPathContextReferenceImpl;
+
+/**
+ * Test class for ConfigurationNodePointerFactory. This class does not directly
+ * call the factory's methods, but rather checks if it can be installed in a
+ * <code>JXPathContext</code> and if XPath expressions can be evaluated.
+ *
+ * @author Oliver Heger
+ * @version $Id$
+ */
+public class TestConfigurationNodePointerFactory extends XPathTest
+{
+    /** Stores the JXPathContext used for testing. */
+    JXPathContext context;
+
+    protected void setUp() throws Exception
+    {
+        super.setUp();
+        JXPathContextReferenceImpl
+                .addNodePointerFactory(new ConfigurationNodePointerFactory());
+        context = JXPathContext.newContext(root);
+        context.setLenient(true);
+    }
+
+    /**
+     * Tests simple XPath expressions.
+     */
+    public void testSimpleXPath()
+    {
+        List nodes = context.selectNodes(CHILD_NAME1);
+        assertEquals("Incorrect number of results", 2, nodes.size());
+        for (Iterator it = nodes.iterator(); it.hasNext();)
+        {
+            ConfigurationNode node = (ConfigurationNode) it.next();
+            assertEquals("Incorrect node name", CHILD_NAME1, node.getName());
+            assertEquals("Incorrect parent node", root, node.getParentNode());
+        }
+
+        nodes = context.selectNodes("/" + CHILD_NAME1);
+        assertEquals("Incorrect number of results", 2, nodes.size());
+
+        nodes = context.selectNodes(CHILD_NAME2 + "/" + CHILD_NAME1 + "/"
+                + CHILD_NAME2);
+        assertEquals("Incorrect number of results", 18, nodes.size());
+    }
+
+    /**
+     * Tests using indices to specify elements.
+     */
+    public void testIndices()
+    {
+        assertEquals("Incorrect value", "1.2.3", context.getValue("/"
+                + CHILD_NAME2 + "[1]/" + CHILD_NAME1 + "[1]/" + CHILD_NAME2
+                + "[2]"));
+        assertEquals("Incorrect value of last node", String
+                .valueOf(CHILD_COUNT), context.getValue(CHILD_NAME2
+                + "[last()]"));
+
+        List nodes = context.selectNodes("/" + CHILD_NAME1 + "[1]/*");
+        assertEquals("Wrong number of children", CHILD_COUNT, nodes.size());
+        int index = 1;
+        for (Iterator it = nodes.iterator(); it.hasNext(); index++)
+        {
+            ConfigurationNode node = (ConfigurationNode) it.next();
+            assertEquals("Wrong node value for child " + index, "2." + index,
+                    node.getValue());
+        }
+    }
+
+    /**
+     * Tests accessing attributes.
+     */
+    public void testAttributes()
+    {
+        root.addAttribute(new DefaultConfigurationNode("testAttr", "true"));
+        assertEquals("Did not find attribute of root node", "true", context
+                .getValue("@testAttr"));
+        assertEquals("Incorrect attribute value", "1", context.getValue("/"
+                + CHILD_NAME2 + "[1]/@" + ATTR_NAME));
+
+        assertTrue("Found elements with name attribute", context.selectNodes(
+                "//" + CHILD_NAME2 + "[@name]").isEmpty());
+        ConfigurationNode node = (ConfigurationNode) root.getChild(2).getChild(
+                1).getChildren(CHILD_NAME2).get(1);
+        node.addAttribute(new DefaultConfigurationNode("name", "testValue"));
+        List nodes = context.selectNodes("//" + CHILD_NAME2 + "[@name]");
+        assertEquals("Name attribute not found", 1, nodes.size());
+        assertEquals("Wrong node returned", node, nodes.get(0));
+    }
+
+    /**
+     * Tests accessing a node's text.
+     */
+    public void testText()
+    {
+        List nodes = context.selectNodes("//" + CHILD_NAME2
+                + "[text()='1.1.1']");
+        assertEquals("Incorrect number of result nodes", 1, nodes.size());
+    }
+
+    /**
+     * Tests accessing the parent axis.
+     */
+    public void testParentAxis()
+    {
+        List nodes = context.selectNodes("/" + CHILD_NAME2 + "/parent::*");
+        assertEquals("Wrong number of parent nodes", 1, nodes.size());
+    }
+
+    /**
+     * Tests accessing the following sibling axis.
+     */
+    public void testFollowingSiblingAxis()
+    {
+        List nodes = context.selectNodes("/" + CHILD_NAME1
+                + "[2]/following-sibling::*");
+        assertEquals("Wrong number of following siblings", 1, nodes.size());
+        ConfigurationNode node = (ConfigurationNode) nodes.get(0);
+        assertEquals("Wrong node type", CHILD_NAME2, node.getName());
+        assertEquals("Wrong index", String.valueOf(CHILD_COUNT), node
+                .getValue());
+    }
+
+    /**
+     * Tests accessing the preceding sibling axis.
+     */
+    public void testPrecedingSiblingAxis()
+    {
+        List nodes = context.selectNodes("/" + CHILD_NAME1
+                + "[2]/preceding-sibling::*");
+        assertEquals("Wrong number of preceding siblings", 3, nodes.size());
+        for (int index = 0, value = 3; index < nodes.size(); index++, value--)
+        {
+            assertEquals("Wrong node index", String.valueOf(value),
+                    ((ConfigurationNode) nodes.get(index)).getValue());
+        }
+    }
+}

Propchange: jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestConfigurationNodePointerFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestConfigurationNodePointerFactory.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestConfigurationNodePointerFactory.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org