Author: oheger Date: Wed Mar 12 14:27:01 2008 New Revision: 636515 URL: http://svn.apache.org/viewvc?rev=636515&view=rev Log: Implementation of the NodePointerFactory for configuration nodes based on the NodeHandler approach
Added: commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/expr/xpath/ConfigurationNodePointerFactory.java - copied, changed from r635335, commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/tree/xpath/ConfigurationNodePointerFactory.java commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/expr/xpath/TestConfigurationNodePointerFactory.java - copied, changed from r636104, commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/tree/xpath/TestConfigurationNodePointerFactory.java Copied: commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/expr/xpath/ConfigurationNodePointerFactory.java (from r635335, commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/tree/xpath/ConfigurationNodePointerFactory.java) URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/expr/xpath/ConfigurationNodePointerFactory.java?p2=commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/expr/xpath/ConfigurationNodePointerFactory.java&p1=commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/tree/xpath/ConfigurationNodePointerFactory.java&r1=635335&r2=636515&rev=636515&view=diff ============================================================================== --- commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/tree/xpath/ConfigurationNodePointerFactory.java (original) +++ commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/expr/xpath/ConfigurationNodePointerFactory.java Wed Mar 12 14:27:01 2008 @@ -14,21 +14,29 @@ * 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.Locale; -import org.apache.commons.configuration2.tree.ConfigurationNode; +import org.apache.commons.configuration2.expr.NodeHandler; 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. + * <p>Implementation of the <code>NodePointerFactory</code> interface for + * configuration nodes.</p> + * <p>This class is able to create <code>NodePointer</code>s for the nodes of + * hierarchical configurations. Because there is no common base class for + * configuration nodes (any specific configuration implementation can use its + * own node class) a trick is needed for activating this factory for a concrete + * JXPath query: The <code>wrapNode()</code> method has to be called with the + * node object and its corresponding <code>NodeHandler</code>. This creates a + * wrapper object containing all information required by the factory for processing + * a query. Then this wrapper object has to be passed to the query methods of + * the JXPath context.</p> * - * @since 1.3 + * @since 2.0 * @author Oliver Heger * @version $Id$ */ @@ -56,11 +64,14 @@ * @param locale the locale * @return a pointer for a configuration node if the bean is such a node */ + @SuppressWarnings("unchecked") public NodePointer createNodePointer(QName name, Object bean, Locale locale) { - if (bean instanceof ConfigurationNode) + if (bean instanceof NodeWrapper) { - return new ConfigurationNodePointer((ConfigurationNode) bean, locale); + NodeWrapper<?> wrapper = (NodeWrapper<?>) bean; + return new ConfigurationNodePointer(wrapper.getNode(), wrapper + .getNodeHandler(), locale); } return null; } @@ -74,12 +85,78 @@ * @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) + @SuppressWarnings("unchecked") + public NodePointer createNodePointer(NodePointer parent, QName name, + Object bean) { - if (bean instanceof ConfigurationNode) + if (bean instanceof NodeWrapper) { - return new ConfigurationNodePointer(parent, (ConfigurationNode) bean); + NodeWrapper<?> wrapper = (NodeWrapper<?>) bean; + return new ConfigurationNodePointer( + (ConfigurationNodePointer) parent, wrapper.getNode(), + wrapper.getNodeHandler()); } return null; + } + + /** + * Creates a node wrapper for the specified node and its handler. This + * wrapper has to be passed to the JXPath context instead of the original + * node. + * + * @param <T> the type of the node + * @param node the node + * @param handler the corresponding node handler + * @return a wrapper for this node + */ + public static <T> Object wrapNode(T node, NodeHandler<T> handler) + { + return new NodeWrapper<T>(node, handler); + } + + /** + * An internally used wrapper class that holds all information for + * processing a query for a specific node. + */ + private static class NodeWrapper<T> + { + /** Stores the node. */ + private T node; + + /** Stores the corresponding node handler. */ + private NodeHandler<T> nodeHandler; + + /** + * Creates a new instance of <code>NodeWrapper</code> and initializes + * it. + * + * @param nd the node + * @param handler the node handler + */ + public NodeWrapper(T nd, NodeHandler<T> handler) + { + node = nd; + nodeHandler = handler; + } + + /** + * Returns the wrapped node. + * + * @return the node + */ + public T getNode() + { + return node; + } + + /** + * Returns the node handler for the wrapped node. + * + * @return the node handler + */ + public NodeHandler<T> getNodeHandler() + { + return nodeHandler; + } } } Copied: commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/expr/xpath/TestConfigurationNodePointerFactory.java (from r636104, commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/tree/xpath/TestConfigurationNodePointerFactory.java) URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/expr/xpath/TestConfigurationNodePointerFactory.java?p2=commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/expr/xpath/TestConfigurationNodePointerFactory.java&p1=commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/tree/xpath/TestConfigurationNodePointerFactory.java&r1=636104&r2=636515&rev=636515&view=diff ============================================================================== --- commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/tree/xpath/TestConfigurationNodePointerFactory.java (original) +++ commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/expr/xpath/TestConfigurationNodePointerFactory.java Wed Mar 12 14:27:01 2008 @@ -14,14 +14,14 @@ * 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.Iterator; import java.util.List; +import org.apache.commons.configuration2.expr.ConfigurationNodeHandler; import org.apache.commons.configuration2.tree.ConfigurationNode; import org.apache.commons.configuration2.tree.DefaultConfigurationNode; -import org.apache.commons.configuration2.tree.xpath.ConfigurationNodePointerFactory; import org.apache.commons.jxpath.JXPathContext; import org.apache.commons.jxpath.ri.JXPathContextReferenceImpl; @@ -36,14 +36,16 @@ public class TestConfigurationNodePointerFactory extends AbstractXPathTest { /** Stores the JXPathContext used for testing. */ - JXPathContext context; + private JXPathContext context; + @Override protected void setUp() throws Exception { super.setUp(); JXPathContextReferenceImpl .addNodePointerFactory(new ConfigurationNodePointerFactory()); - context = JXPathContext.newContext(root); + context = JXPathContext.newContext(ConfigurationNodePointerFactory + .wrapNode(root, new ConfigurationNodeHandler())); context.setLenient(true); } @@ -52,9 +54,9 @@ */ public void testSimpleXPath() { - List nodes = context.selectNodes(CHILD_NAME1); + List<?> nodes = context.selectNodes(CHILD_NAME1); assertEquals("Incorrect number of results", 2, nodes.size()); - for (Iterator it = nodes.iterator(); it.hasNext();) + for (Iterator<?> it = nodes.iterator(); it.hasNext();) { ConfigurationNode node = (ConfigurationNode) it.next(); assertEquals("Incorrect node name", CHILD_NAME1, node.getName()); @@ -81,10 +83,10 @@ .valueOf(CHILD_COUNT), context.getValue(CHILD_NAME2 + "[last()]")); - List nodes = context.selectNodes("/" + CHILD_NAME1 + "[1]/*"); + 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++) + for (Iterator<?> it = nodes.iterator(); it.hasNext(); index++) { ConfigurationNode node = (ConfigurationNode) it.next(); assertEquals("Wrong node value for child " + index, "2." + index, @@ -108,7 +110,7 @@ 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 + "[EMAIL PROTECTED]"); + List<?> nodes = context.selectNodes("//" + CHILD_NAME2 + "[EMAIL PROTECTED]"); assertEquals("Name attribute not found", 1, nodes.size()); assertEquals("Wrong node returned", node, nodes.get(0)); } @@ -118,7 +120,7 @@ */ public void testText() { - List nodes = context.selectNodes("//" + CHILD_NAME2 + List<?> nodes = context.selectNodes("//" + CHILD_NAME2 + "[text()='1.1.1']"); assertEquals("Incorrect number of result nodes", 1, nodes.size()); } @@ -128,7 +130,7 @@ */ public void testParentAxis() { - List nodes = context.selectNodes("/" + CHILD_NAME2 + "/parent::*"); + List<?> nodes = context.selectNodes("/" + CHILD_NAME2 + "/parent::*"); assertEquals("Wrong number of parent nodes", 1, nodes.size()); } @@ -137,7 +139,7 @@ */ public void testFollowingSiblingAxis() { - List nodes = context.selectNodes("/" + CHILD_NAME1 + List<?> nodes = context.selectNodes("/" + CHILD_NAME1 + "[2]/following-sibling::*"); assertEquals("Wrong number of following siblings", 1, nodes.size()); ConfigurationNode node = (ConfigurationNode) nodes.get(0); @@ -151,7 +153,7 @@ */ public void testPrecedingSiblingAxis() { - List nodes = context.selectNodes("/" + CHILD_NAME1 + 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--)