Author: oheger
Date: Fri Feb 7 20:37:26 2014
New Revision: 1565800
URL: http://svn.apache.org/r1565800
Log:
ConfigurationNodePointerFactory now supports arbitrary nodes with a handler.
A specialized node wrapper instance is created to detect configuration nodes
and to associate them with the correct node handler.
Modified:
commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodePointerFactory.java
Modified:
commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodePointerFactory.java
URL:
http://svn.apache.org/viewvc/commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodePointerFactory.java?rev=1565800&r1=1565799&r2=1565800&view=diff
==============================================================================
---
commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodePointerFactory.java
(original)
+++
commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodePointerFactory.java
Fri Feb 7 20:37:26 2014
@@ -18,19 +18,29 @@ package org.apache.commons.configuration
import java.util.Locale;
-import org.apache.commons.configuration.tree.ConfigurationNode;
+import org.apache.commons.configuration.tree.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} interface for
- * configuration nodes.
+ * <p>
+ * Implementation of the {@code NodePointerFactory} interface for configuration
+ * nodes.
+ * </p>
+ * <p>
+ * This class is able to create {@code NodePointer}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()} method has to be called with the node
+ * object and its corresponding {@code NodeHandler}. 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
- * @author <a
- * href="http://commons.apache.org/configuration/team-list.html">Commons
- * Configuration team</a>
* @version $Id$
*/
public class ConfigurationNodePointerFactory implements NodePointerFactory
@@ -50,19 +60,25 @@ public class ConfigurationNodePointerFac
/**
* Creates a node pointer for the specified bean. If the bean is a
- * configuration node, a corresponding pointer is returned.
+ * configuration node (indicated by a wrapper object), 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
*/
+ @SuppressWarnings("unchecked")
+ /* Type casts are safe here; because of the way the NodeWrapper was
+ constructed the node handler must be compatible with the node.
+ */
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(),
+ locale, wrapper.getNodeHandler());
}
return null;
}
@@ -76,14 +92,81 @@ public class ConfigurationNodePointerFac
* @param bean the bean
* @return a pointer for a configuration node if the bean is such a node
*/
+ @SuppressWarnings("unchecked")
+ /* Type casts are safe here, see above. Also, the hierarchy of node
+ pointers is consistent, so a parent is compatible to a child.
+ */
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.
+ *
+ * @param <T> the type of the nodes this class deals with
+ */
+ static class NodeWrapper<T>
+ {
+ /** Stores the node. */
+ private final T node;
+
+ /** Stores the corresponding node handler. */
+ private final NodeHandler<T> nodeHandler;
+
+ /**
+ * Creates a new instance of {@code NodeWrapper} 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;
+ }
+ }
}