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/15 21:11:34 UTC
svn commit: r637458 - in
/commons/proper/configuration/branches/configuration2_experimental/src:
main/java/org/apache/commons/configuration2/expr/xpath/
test/java/org/apache/commons/configuration2/expr/xpath/
Author: oheger
Date: Sat Mar 15 13:11:31 2008
New Revision: 637458
URL: http://svn.apache.org/viewvc?rev=637458&view=rev
Log:
Ported XPathExpressionEngine to support hierarchical configurations based on the NodeHandler approach
Added:
commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/expr/xpath/XPathExpressionEngine.java
- copied, changed from r635335, commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/tree/xpath/XPathExpressionEngine.java
commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/expr/xpath/package.html
- copied unchanged from r635335, commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/tree/xpath/package.html
commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/expr/xpath/TestXPathExpressionEngine.java
- copied, changed from r636104, commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/tree/xpath/TestXPathExpressionEngine.java
Copied: commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/expr/xpath/XPathExpressionEngine.java (from r635335, commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/tree/xpath/XPathExpressionEngine.java)
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/expr/xpath/XPathExpressionEngine.java?p2=commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/expr/xpath/XPathExpressionEngine.java&p1=commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/tree/xpath/XPathExpressionEngine.java&r1=635335&r2=637458&rev=637458&view=diff
==============================================================================
--- commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/tree/xpath/XPathExpressionEngine.java (original)
+++ commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/expr/xpath/XPathExpressionEngine.java Sat Mar 15 13:11:31 2008
@@ -15,16 +15,15 @@
* limitations under the License.
*/
-package org.apache.commons.configuration2.tree.xpath;
+package org.apache.commons.configuration2.expr.xpath;
-import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
import java.util.StringTokenizer;
-import org.apache.commons.configuration2.tree.ConfigurationNode;
-import org.apache.commons.configuration2.tree.ExpressionEngine;
-import org.apache.commons.configuration2.tree.NodeAddData;
+import org.apache.commons.configuration2.expr.ExpressionEngine;
+import org.apache.commons.configuration2.expr.NodeAddData;
+import org.apache.commons.configuration2.expr.NodeHandler;
+import org.apache.commons.configuration2.expr.NodeList;
import org.apache.commons.jxpath.JXPathContext;
import org.apache.commons.jxpath.ri.JXPathContextReferenceImpl;
import org.apache.commons.lang.StringUtils;
@@ -37,7 +36,7 @@
* <p>
* This class makes use of <a href="http://commons.apache.org/jxpath/">
* Commons JXPath</a> for handling XPath expressions and mapping them to the
- * nodes of a hierarchical configuration. This makes the rich and powerfull
+ * nodes of a hierarchical configuration. This makes the rich and powerful
* XPATH syntax available for accessing properties from a configuration object.
* </p>
* <p>
@@ -98,7 +97,7 @@
* <code>name</code> will be added.
* </p>
*
- * @since 1.3
+ * @since 2.0
* @author Oliver Heger
* @version $Id$
*/
@@ -119,52 +118,69 @@
*
* @param root the configuration root node
* @param key the query to be executed
+ * @param handler the node handler
* @return a list with the nodes that are selected by the query
*/
- public List<ConfigurationNode> query(ConfigurationNode root, String key)
+ @SuppressWarnings("unchecked")
+ public <T> NodeList<T> query(T root, String key, NodeHandler<T> handler)
{
+ NodeList<T> result = new NodeList<T>();
+
if (StringUtils.isEmpty(key))
{
- List<ConfigurationNode> result = new ArrayList<ConfigurationNode>(1);
- result.add(root);
- return result;
+ result.addNode(root);
}
+
else
{
- JXPathContext context = createContext(root, key);
- List<ConfigurationNode> result = context.selectNodes(key);
- if (result != null)
- {
- return result;
- }
- else
+ JXPathContext context = createContext(root, key, handler);
+ List<?> nodes = context.selectNodes(key);
+ if (nodes != null)
{
- return Collections.emptyList();
+ for (Object o : nodes)
+ {
+ if (o instanceof ConfigurationAttributePointer.AttributeNodeProxy)
+ {
+ ConfigurationAttributePointer<T>.AttributeNodeProxy anp =
+ (ConfigurationAttributePointer.AttributeNodeProxy) o;
+ result.addAttribute(anp.getParentNode(), anp
+ .getAttributeName());
+ }
+ else
+ {
+ result.addNode((T) o);
+ }
+ }
}
}
+
+ return result;
}
/**
- * Returns a (canonic) key for the given node based on the parent's key.
+ * Returns a (canonical) 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.configuration2.tree.DefaultExpressionEngine DefaultExpressionEngine}</code>
+ * <code>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.
+ * given parent with 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
+ * @param handler the node handler
* @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)
{
// name of the root node
return StringUtils.EMPTY;
}
- else if (node.getName() == null)
+
+ String nodeName = handler.nodeName(node);
+ if (nodeName == null)
{
// paranoia check for undefined node names
return parentKey;
@@ -172,31 +188,50 @@
else
{
- StringBuilder buf = new StringBuilder(parentKey.length() + node.getName().length() + PATH_DELIMITER.length());
+ StringBuilder buf = new StringBuilder(parentKey.length() + nodeName.length() + PATH_DELIMITER.length());
if (parentKey.length() > 0)
{
buf.append(parentKey);
buf.append(PATH_DELIMITER);
}
- if (node.isAttribute())
- {
- buf.append(ATTR_DELIMITER);
- }
- buf.append(node.getName());
+ buf.append(nodeName);
return buf.toString();
}
}
/**
+ * Returns a key for the specified attribute. This method works similar to
+ * <code>nodeKey()</code>, but deals with attributes.
+ *
+ * @param parentNode the parent node
+ * @param parentKey the key of the parent
+ * @param attrName the name of the attribute
+ * @param handler the node handler
+ * @return the key for this attribute
+ */
+ public <T> String attributeKey(T parentNode, String parentKey,
+ String attrName, NodeHandler<T> handler)
+ {
+ StringBuilder buf = new StringBuilder();
+ if (parentKey != null && parentKey.length() > 0)
+ {
+ buf.append(parentKey).append(PATH_DELIMITER);
+ }
+ buf.append(ATTR_DELIMITER).append(attrName);
+ 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
+ * @param handler the node handler
* @return a data object to be evaluated by the calling configuration object
*/
- public NodeAddData prepareAdd(ConfigurationNode root, String key)
+ public <T> NodeAddData<T> prepareAdd(T root, String key, NodeHandler<T> handler)
{
if (key == null)
{
@@ -214,14 +249,14 @@
throw new IllegalArgumentException("prepareAdd: Passed in key must contain a whitespace!");
}
- List<ConfigurationNode> nodes = query(root, key.substring(0, index).trim());
+ NodeList<T> nodes = query(root, key.substring(0, index).trim(), handler);
if (nodes.size() != 1)
{
throw new IllegalArgumentException("prepareAdd: key must select exactly one target node!");
}
- NodeAddData data = new NodeAddData();
- data.setParent(nodes.get(0));
+ NodeAddData<T> data = new NodeAddData<T>();
+ data.setParent(nodes.getNode(0));
initNodeAddData(data, key.substring(index).trim());
return data;
}
@@ -233,11 +268,14 @@
*
* @param root the configuration root node
* @param key the key to be queried
+ * @param handler the node handler
* @return the new context
*/
- protected JXPathContext createContext(ConfigurationNode root, String key)
+ protected <T> JXPathContext createContext(T root, String key, NodeHandler<T> handler)
{
- JXPathContext context = JXPathContext.newContext(root);
+ JXPathContext context = JXPathContext
+ .newContext(ConfigurationNodePointerFactory.wrapNode(root,
+ handler));
context.setLenient(true);
return context;
}
@@ -245,12 +283,12 @@
/**
* 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.
+ * been found. Its task is to interpret 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)
+ protected <T> void initNodeAddData(NodeAddData<T> data, String path)
{
String lastComponent = null;
boolean attr = false;
Copied: commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/expr/xpath/TestXPathExpressionEngine.java (from r636104, commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/tree/xpath/TestXPathExpressionEngine.java)
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/expr/xpath/TestXPathExpressionEngine.java?p2=commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/expr/xpath/TestXPathExpressionEngine.java&p1=commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/tree/xpath/TestXPathExpressionEngine.java&r1=636104&r2=637458&rev=637458&view=diff
==============================================================================
--- commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/tree/xpath/TestXPathExpressionEngine.java (original)
+++ commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/expr/xpath/TestXPathExpressionEngine.java Sat Mar 15 13:11:31 2008
@@ -14,17 +14,18 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.commons.configuration2.tree.xpath;
+package org.apache.commons.configuration2.expr.xpath;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import org.apache.commons.configuration2.expr.ConfigurationNodeHandler;
+import org.apache.commons.configuration2.expr.NodeAddData;
+import org.apache.commons.configuration2.expr.NodeHandler;
+import org.apache.commons.configuration2.expr.NodeList;
import org.apache.commons.configuration2.tree.ConfigurationNode;
import org.apache.commons.configuration2.tree.DefaultConfigurationNode;
-import org.apache.commons.configuration2.tree.NodeAddData;
-import org.apache.commons.configuration2.tree.xpath.ConfigurationNodePointerFactory;
-import org.apache.commons.configuration2.tree.xpath.XPathExpressionEngine;
import org.apache.commons.jxpath.JXPathContext;
import org.apache.commons.jxpath.ri.JXPathContextReferenceImpl;
import org.apache.commons.jxpath.ri.model.NodePointerFactory;
@@ -39,19 +40,24 @@
*/
public class TestXPathExpressionEngine extends TestCase
{
- /** Constant for the test root node. */
- static final ConfigurationNode ROOT = new DefaultConfigurationNode(
- "testRoot");
-
/** Constant for the valid test key. */
- static final String TEST_KEY = "TESTKEY";
+ private static final String TEST_KEY = "TESTKEY";
+
+ /** The test root node. */
+ private ConfigurationNode root;
+
+ /** The node handler.*/
+ private ConfigurationNodeHandler handler;
/** The expression engine to be tested. */
- XPathExpressionEngine engine;
+ private MockJXPathContextExpressionEngine engine;
+ @Override
protected void setUp() throws Exception
{
super.setUp();
+ root = new DefaultConfigurationNode("testRoot");
+ handler = new ConfigurationNodeHandler();
engine = new MockJXPathContextExpressionEngine();
}
@@ -60,19 +66,40 @@
*/
public void testQueryExpression()
{
- List nodes = engine.query(ROOT, TEST_KEY);
+ NodeList<ConfigurationNode> nodes = engine.query(root, TEST_KEY, handler);
assertEquals("Incorrect number of results", 1, nodes.size());
- assertSame("Wrong result node", ROOT, nodes.get(0));
+ assertSame("Wrong result node", root, nodes.getNode(0));
checkSelectCalls(1);
}
/**
+ * Tests a query that returns attribute nodes.
+ */
+ public void testQueryAttributes()
+ {
+ final int attrCount = 5;
+ for(int i = 0; i < attrCount; i++)
+ {
+ root.addAttribute(new DefaultConfigurationNode("attr" + i, "value" + i));
+ }
+ engine.useMockContext = false;
+ NodeList<ConfigurationNode> nodes = engine.query(root, "/@*", handler);
+ assertEquals("Wrong number of attribute results", attrCount, nodes.size());
+ for(int i = 0; i < attrCount; i++)
+ {
+ assertTrue("No attribute node", nodes.isAttribute(i));
+ assertEquals("Wrong attribute name", "attr" + i, nodes.getName(i, handler));
+ assertEquals("Wrong parent node", root, nodes.getAttributeParent(i));
+ }
+ }
+
+ /**
* Tests a query that has no results. This should return an empty list.
*/
public void testQueryWithoutResult()
{
- List nodes = engine.query(ROOT, "a non existing key");
- assertTrue("Result list is not empty", nodes.isEmpty());
+ NodeList<ConfigurationNode> nodes = engine.query(root, "a non existing key", handler);
+ assertTrue("Result list is not empty", nodes.size() == 0);
checkSelectCalls(1);
}
@@ -100,9 +127,9 @@
*/
private void checkEmptyKey(String key)
{
- List nodes = engine.query(ROOT, key);
+ NodeList<ConfigurationNode> nodes = engine.query(root, key, handler);
assertEquals("Incorrect number of results", 1, nodes.size());
- assertSame("Wrong result node", ROOT, nodes.get(0));
+ assertSame("Wrong result node", root, nodes.getNode(0));
checkSelectCalls(0);
}
@@ -111,11 +138,10 @@
*/
public void testCreateContext()
{
- JXPathContext ctx = new XPathExpressionEngine().createContext(ROOT,
- TEST_KEY);
+ JXPathContext ctx = new XPathExpressionEngine().createContext(root,
+ TEST_KEY, handler);
assertNotNull("Context is null", ctx);
assertTrue("Lenient mode is not set", ctx.isLenient());
- assertSame("Incorrect context bean set", ROOT, ctx.getContextBean());
NodePointerFactory[] factories = JXPathContextReferenceImpl
.getNodePointerFactories();
@@ -136,18 +162,19 @@
public void testNodeKeyNormal()
{
assertEquals("Wrong node key", "parent/child", engine.nodeKey(
- new DefaultConfigurationNode("child"), "parent"));
+ new DefaultConfigurationNode("child"), "parent", handler));
}
/**
- * Tests nodeKey() for an attribute node.
+ * Tests querying the key of an attribute node.
*/
- public void testNodeKeyAttribute()
+ public void testAttributeKey()
{
+ ConfigurationNode parent = new DefaultConfigurationNode("node");
ConfigurationNode node = new DefaultConfigurationNode("attr");
- node.setAttribute(true);
- assertEquals("Wrong attribute key", "node/@attr", engine.nodeKey(node,
- "node"));
+ parent.addAttribute(node);
+ assertEquals("Wrong attribute key", "node/@attr", engine.attributeKey(
+ parent, parent.getName(), node.getName(), handler));
}
/**
@@ -155,22 +182,51 @@
*/
public void testNodeKeyForRootNode()
{
- assertEquals("Wrong key for root node", "", engine.nodeKey(ROOT, null));
+ assertEquals("Wrong key for root node", "", engine.nodeKey(root, null, handler));
assertEquals("Null name not detected", "test", engine.nodeKey(
- new DefaultConfigurationNode(), "test"));
+ new DefaultConfigurationNode(), "test", handler));
}
/**
- * Tests node key() for direct children of the root node.
+ * Tests nodeKey() for direct children of the root node.
*/
public void testNodeKeyForRootChild()
{
ConfigurationNode node = new DefaultConfigurationNode("child");
assertEquals("Wrong key for root child node", "child", engine.nodeKey(
- node, ""));
- node.setAttribute(true);
- assertEquals("Wrong key for root attribute", "@child", engine.nodeKey(
- node, ""));
+ node, "", handler));
+ }
+
+ /**
+ * Tests querying the key of an attribute that belongs to the root node when
+ * the empty string is passed as parent name.
+ */
+ public void testAttributeKeyForRootEmpty()
+ {
+ checkAttributeKeyForRoot("");
+ }
+
+ /**
+ * Tests querying the key of an attribute that belongs to the root node when
+ * null is passed as parent name.
+ */
+ public void testAttributeKeyForRootNull()
+ {
+ checkAttributeKeyForRoot(null);
+ }
+
+ /**
+ * Helper method for checking the keys of attributes that belong to the root
+ * node.
+ * @param rootName the key of the root node (null or empty)
+ */
+ private void checkAttributeKeyForRoot(String rootName)
+ {
+ ConfigurationNode parent = new DefaultConfigurationNode();
+ ConfigurationNode attr = new DefaultConfigurationNode("attr");
+ parent.addAttribute(attr);
+ assertEquals("Wrong key of root attribute", "@attr", engine
+ .attributeKey(parent, rootName, attr.getName(), handler));
}
/**
@@ -178,9 +234,8 @@
*/
public void testPrepareAddNode()
{
- NodeAddData data = engine.prepareAdd(ROOT, TEST_KEY + " newNode");
- checkAddPath(data, new String[]
- { "newNode" }, false);
+ NodeAddData<ConfigurationNode> data = engine.prepareAdd(root, TEST_KEY + " newNode", handler);
+ checkAddPath(data, new String[] { "newNode" }, false);
checkSelectCalls(1);
}
@@ -189,9 +244,8 @@
*/
public void testPrepareAddAttribute()
{
- NodeAddData data = engine.prepareAdd(ROOT, TEST_KEY + "\t@newAttr");
- checkAddPath(data, new String[]
- { "newAttr" }, true);
+ NodeAddData<ConfigurationNode> data = engine.prepareAdd(root, TEST_KEY + "\t@newAttr", handler);
+ checkAddPath(data, new String[] { "newAttr" }, true);
checkSelectCalls(1);
}
@@ -200,8 +254,8 @@
*/
public void testPrepareAddPath()
{
- NodeAddData data = engine.prepareAdd(ROOT, TEST_KEY
- + " \t a/full/path/node");
+ NodeAddData<ConfigurationNode> data = engine.prepareAdd(root, TEST_KEY
+ + " \t a/full/path/node", handler);
checkAddPath(data, new String[]
{ "a", "full", "path", "node" }, false);
checkSelectCalls(1);
@@ -212,8 +266,8 @@
*/
public void testPrepareAddAttributePath()
{
- NodeAddData data = engine.prepareAdd(ROOT, TEST_KEY
- + " a/full/path@attr");
+ NodeAddData<ConfigurationNode> data = engine.prepareAdd(root, TEST_KEY
+ + " a/full/path@attr", handler);
checkAddPath(data, new String[]
{ "a", "full", "path", "attr" }, true);
checkSelectCalls(1);
@@ -224,9 +278,8 @@
*/
public void testPrepareAddRootChild()
{
- NodeAddData data = engine.prepareAdd(ROOT, " newNode");
- checkAddPath(data, new String[]
- { "newNode" }, false);
+ NodeAddData<ConfigurationNode> data = engine.prepareAdd(root, " newNode", handler);
+ checkAddPath(data, new String[] { "newNode" }, false);
checkSelectCalls(0);
}
@@ -235,9 +288,8 @@
*/
public void testPrepareAddRootAttribute()
{
- NodeAddData data = engine.prepareAdd(ROOT, " @attr");
- checkAddPath(data, new String[]
- { "attr" }, true);
+ NodeAddData<ConfigurationNode> data = engine.prepareAdd(root, " @attr", handler);
+ checkAddPath(data, new String[] { "attr" }, true);
checkSelectCalls(0);
}
@@ -248,7 +300,7 @@
{
try
{
- engine.prepareAdd(ROOT, "invalidKey newNode");
+ engine.prepareAdd(root, "invalidKey newNode", handler);
fail("Could add to invalid parent!");
}
catch (IllegalArgumentException iex)
@@ -259,13 +311,13 @@
/**
* Tests an add operation where the passed in key has an invalid format: it
- * does not contain a whitspace. This will cause an error.
+ * does not contain a whitespace. This will cause an error.
*/
public void testPrepareAddInvalidFormat()
{
try
{
- engine.prepareAdd(ROOT, "anInvalidKey");
+ engine.prepareAdd(root, "anInvalidKey", handler);
fail("Could add an invalid key!");
}
catch (IllegalArgumentException iex)
@@ -281,7 +333,7 @@
{
try
{
- engine.prepareAdd(ROOT, TEST_KEY + " ");
+ engine.prepareAdd(root, TEST_KEY + " ", handler);
fail("Could add empty path!");
}
catch (IllegalArgumentException iex)
@@ -297,7 +349,7 @@
{
try
{
- engine.prepareAdd(ROOT, null);
+ engine.prepareAdd(root, null, handler);
fail("Could add null path!");
}
catch (IllegalArgumentException iex)
@@ -307,13 +359,13 @@
}
/**
- * Tests an add operation where the key is null.
+ * Tests an add operation where the key is empty.
*/
public void testPrepareAddEmptyKey()
{
try
{
- engine.prepareAdd(ROOT, "");
+ engine.prepareAdd(root, "", handler);
fail("Could add empty path!");
}
catch (IllegalArgumentException iex)
@@ -329,7 +381,7 @@
{
try
{
- engine.prepareAdd(ROOT, TEST_KEY + " an/invalid//path");
+ engine.prepareAdd(root, TEST_KEY + " an/invalid//path", handler);
fail("Could add invalid path!");
}
catch (IllegalArgumentException iex)
@@ -346,7 +398,7 @@
{
try
{
- engine.prepareAdd(ROOT, TEST_KEY + " a/path/with@an/attribute");
+ engine.prepareAdd(root, TEST_KEY + " a/path/with@an/attribute", handler);
fail("Could add invalid attribute path!");
}
catch (IllegalArgumentException iex)
@@ -363,7 +415,7 @@
{
try
{
- engine.prepareAdd(ROOT, TEST_KEY + " a/path/with/@attribute");
+ engine.prepareAdd(root, TEST_KEY + " a/path/with/@attribute", handler);
fail("Could add invalid attribute path!");
}
catch (IllegalArgumentException iex)
@@ -379,7 +431,7 @@
{
try
{
- engine.prepareAdd(ROOT, TEST_KEY + " /a/path/node");
+ engine.prepareAdd(root, TEST_KEY + " /a/path/node", handler);
fail("Could add path starting with a slash!");
}
catch (IllegalArgumentException iex)
@@ -396,7 +448,7 @@
{
try
{
- engine.prepareAdd(ROOT, TEST_KEY + " an@attribute@path");
+ engine.prepareAdd(root, TEST_KEY + " an@attribute@path", handler);
fail("Could add path with multiple attributes!");
}
catch (IllegalArgumentException iex)
@@ -406,19 +458,38 @@
}
/**
+ * Tries to add a node to an attribute. This should cause an exception.
+ */
+ public void testPrepareAddToAttribute()
+ {
+ ConfigurationNode attr = new DefaultConfigurationNode("attr");
+ root.addAttribute(attr);
+ engine.useMockContext = false;
+ try
+ {
+ engine.prepareAdd(root, "/@attr newNode", handler);
+ fail("Could add a node to an attribute!");
+ }
+ catch (IllegalArgumentException iex)
+ {
+ // ok
+ }
+ }
+
+ /**
* Helper method for testing the path nodes in the given add data object.
*
* @param data the data object to check
* @param expected an array with the expected path elements
* @param attr a flag if the new node is an attribute
*/
- private void checkAddPath(NodeAddData data, String[] expected, boolean attr)
+ private void checkAddPath(NodeAddData<ConfigurationNode> data, String[] expected, boolean attr)
{
- assertSame("Wrong parent node", ROOT, data.getParent());
- List path = data.getPathNodes();
+ assertSame("Wrong parent node", root, data.getParent());
+ List<String> path = data.getPathNodes();
assertEquals("Incorrect number of path nodes", expected.length - 1,
path.size());
- Iterator it = path.iterator();
+ Iterator<String> it = path.iterator();
for (int idx = 0; idx < expected.length - 1; idx++)
{
assertEquals("Wrong node at position " + idx, expected[idx], it
@@ -448,7 +519,7 @@
* <code>XPathExpressionEngine</code> to count the invocations of this
* method.
*/
- static class MockJXPathContext extends JXPathContextReferenceImpl
+ class MockJXPathContext extends JXPathContextReferenceImpl
{
int selectInvocations;
@@ -462,13 +533,14 @@
* test key, the root node will be returned in the list. Otherwise the
* return value is <b>null</b>.
*/
- public List selectNodes(String xpath)
+ @Override
+ public List<Object> selectNodes(String xpath)
{
selectInvocations++;
if (TEST_KEY.equals(xpath))
{
- List result = new ArrayList(1);
- result.add(ROOT);
+ List<Object> result = new ArrayList<Object>(1);
+ result.add(root);
return result;
}
else
@@ -480,18 +552,29 @@
/**
* A special implementation of XPathExpressionEngine that overrides
- * createContext() to return a mock context object.
+ * createContext() to optionally return a mock context object.
*/
- static class MockJXPathContextExpressionEngine extends
+ class MockJXPathContextExpressionEngine extends
XPathExpressionEngine
{
/** Stores the context instance. */
private MockJXPathContext context;
- protected JXPathContext createContext(ConfigurationNode root, String key)
+ /** A flag whether a mock context is to be created.*/
+ boolean useMockContext = true;
+
+ @Override
+ protected <T> JXPathContext createContext(T root, String key, NodeHandler<T> handler)
{
- context = new MockJXPathContext(root);
- return context;
+ if(useMockContext)
+ {
+ context = new MockJXPathContext(root);
+ return context;
+ }
+ else
+ {
+ return super.createContext(root, key, handler);
+ }
}
/**