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 2014/04/20 21:32:10 UTC
svn commit: r1588831 [6/11] - in /commons/proper/configuration/trunk: ./
src/main/java/org/apache/commons/configuration/
src/main/java/org/apache/commons/configuration/beanutils/
src/main/java/org/apache/commons/configuration/builder/combined/ src/main...
Modified: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/DefaultExpressionEngine.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/DefaultExpressionEngine.java?rev=1588831&r1=1588830&r2=1588831&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/DefaultExpressionEngine.java (original)
+++ commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/DefaultExpressionEngine.java Sun Apr 20 19:32:08 2014
@@ -158,35 +158,26 @@ public class DefaultExpressionEngine imp
}
/**
- * Evaluates the given key and returns all matching nodes. This method
- * supports the syntax as described in the class comment.
- *
- * @param root the root node
- * @param key the key
- * @return a list with the matching nodes
+ * {@inheritDoc} This method supports the syntax as described in the class
+ * comment.
*/
- @Override
- public List<ConfigurationNode> query(ConfigurationNode root, String key)
+ public <T> List<QueryResult<T>> query(T root, String key,
+ NodeHandler<T> handler)
{
- List<ConfigurationNode> nodes = new LinkedList<ConfigurationNode>();
+ List<QueryResult<T>> results = new LinkedList<QueryResult<T>>();
findNodesForKey(new DefaultConfigurationKey(this, key).iterator(),
- root, nodes);
- return nodes;
+ root, results, handler);
+ return results;
}
/**
- * Determines the key of the passed in node. This implementation takes the
+ * {@inheritDoc} This implementation takes the
* given parent key, adds a property delimiter, and then adds the node's
- * name. (For attribute nodes the attribute delimiters are used instead.)
- * The name of the root node is a blanc string. Note that no indices will be
+ * name.
+ * The name of the root node is a blank string. Note that no indices are
* returned.
- *
- * @param node the node whose key is to be determined
- * @param parentKey the key of this node's parent
- * @return the key for the given node
*/
- @Override
- public String nodeKey(ConfigurationNode node, String parentKey)
+ public <T> String nodeKey(T node, String parentKey, NodeHandler<T> handler)
{
if (parentKey == null)
{
@@ -198,18 +189,43 @@ public class DefaultExpressionEngine imp
{
DefaultConfigurationKey key = new DefaultConfigurationKey(this,
parentKey);
- if (node.isAttribute())
- {
- key.appendAttribute(node.getName());
- }
- else
- {
- key.append(node.getName(), true);
- }
+ key.append(handler.nodeName(node), true);
return key.toString();
}
}
+ public String attributeKey(String parentKey, String attributeName)
+ {
+ DefaultConfigurationKey key =
+ new DefaultConfigurationKey(this, parentKey);
+ key.appendAttribute(attributeName);
+ return key.toString();
+ }
+
+ /**
+ * {@inheritDoc} This implementation works similar to {@code nodeKey()};
+ * however, each key returned by this method has an index (except for the
+ * root node). The parent key is prepended to the name of the current node
+ * in any case and without further checks. If it is <b>null</b>, only the
+ * name of the current node with its index is returned.
+ */
+ public <T> String canonicalKey(T node, String parentKey,
+ NodeHandler<T> handler)
+ {
+ String nodeName = handler.nodeName(node);
+ T parent = handler.getParent(node);
+ DefaultConfigurationKey key =
+ new DefaultConfigurationKey(this, parentKey);
+ key.append(StringUtils.defaultString(nodeName));
+
+ if (parent != null)
+ {
+ // this is not the root key
+ key.appendIndex(determineIndex(node, parent, nodeName, handler));
+ }
+ return key.toString();
+ }
+
/**
* <p>
* Prepares Adding the property with the specified key.
@@ -218,7 +234,7 @@ public class DefaultExpressionEngine imp
* To be able to deal with the structure supported by hierarchical
* configuration implementations the passed in key is of importance,
* especially the indices it might contain. The following example should
- * clarify this: Suppose the actual node structure looks like the
+ * clarify this: Suppose the current node structure looks like the
* following:
* </p>
* <p>
@@ -293,12 +309,13 @@ public class DefaultExpressionEngine imp
* so there cannot be any ambiguities.)
* </p>
*
+ * @param <T> the type of the nodes to be dealt with
* @param root the root node of the nodes hierarchy
* @param key the key of the new property
+ * @param handler the node handler
* @return a data object with information needed for the add operation
*/
- @Override
- public NodeAddData prepareAdd(ConfigurationNode root, String key)
+ public <T> NodeAddData<T> prepareAdd(T root, String key, NodeHandler<T> handler)
{
DefaultConfigurationKey.KeyIterator it = new DefaultConfigurationKey(
this, key).iterator();
@@ -308,8 +325,8 @@ public class DefaultExpressionEngine imp
"Key for add operation must be defined!");
}
- NodeAddData result = new NodeAddData();
- result.setParent(findLastPathNode(it, root));
+ T parent = findLastPathNode(it, root, handler);
+ List<String> pathNodes = new LinkedList<String>();
while (it.hasNext())
{
@@ -319,30 +336,32 @@ public class DefaultExpressionEngine imp
"Invalid key for add operation: " + key
+ " (Attribute key in the middle.)");
}
- result.addPathNode(it.currentKey());
+ pathNodes.add(it.currentKey());
it.next();
}
- result.setNewNodeName(it.currentKey());
- result.setAttribute(!it.isPropertyKey());
- return result;
+ return new NodeAddData<T>(parent, it.currentKey(), !it.isPropertyKey(),
+ pathNodes);
}
/**
* Recursive helper method for evaluating a key. This method processes all
* facets of a configuration key, traverses the tree of properties and
- * fetches the the nodes of all matching properties.
+ * fetches the results of all matching properties.
*
+ * @param <T> the type of nodes to be dealt with
* @param keyPart the configuration key iterator
- * @param node the actual node
- * @param nodes here the found nodes are stored
+ * @param node the current node
+ * @param results here the found results are stored
+ * @param handler the node handler
*/
- protected void findNodesForKey(DefaultConfigurationKey.KeyIterator keyPart,
- ConfigurationNode node, Collection<ConfigurationNode> nodes)
+ protected <T> void findNodesForKey(
+ DefaultConfigurationKey.KeyIterator keyPart, T node,
+ Collection<QueryResult<T>> results, NodeHandler<T> handler)
{
if (!keyPart.hasNext())
{
- nodes.add(node);
+ results.add(QueryResult.createNodeResult(node));
}
else
@@ -350,26 +369,32 @@ public class DefaultExpressionEngine imp
String key = keyPart.nextKey(false);
if (keyPart.isPropertyKey())
{
- processSubNodes(keyPart, node.getChildren(key), nodes);
+ processSubNodes(keyPart, handler.getChildren(node, key),
+ results, handler);
}
- if (keyPart.isAttribute())
+ if (keyPart.isAttribute() && !keyPart.hasNext())
{
- processSubNodes(keyPart, node.getAttributes(key), nodes);
+ if (handler.getAttributeValue(node, key) != null)
+ {
+ results.add(QueryResult.createAttributeResult(node, key));
+ }
}
}
}
/**
* Finds the last existing node for an add operation. This method traverses
- * the configuration node tree along the specified key. The last existing
- * node on this path is returned.
+ * the node tree along the specified key. The last existing node on this
+ * path is returned.
*
+ * @param <T> the type of the nodes to be dealt with
* @param keyIt the key iterator
- * @param node the actual node
+ * @param node the current node
+ * @param handler the node handler
* @return the last existing node on the given path
*/
- protected ConfigurationNode findLastPathNode(
- DefaultConfigurationKey.KeyIterator keyIt, ConfigurationNode node)
+ protected <T> T findLastPathNode(DefaultConfigurationKey.KeyIterator keyIt,
+ T node, NodeHandler<T> handler)
{
String keyPart = keyIt.nextKey(false);
@@ -382,15 +407,17 @@ public class DefaultExpressionEngine imp
"Invalid path for add operation: "
+ "Attribute key in the middle!");
}
- int idx = keyIt.hasIndex() ? keyIt.getIndex() : node
- .getChildrenCount(keyPart) - 1;
- if (idx < 0 || idx >= node.getChildrenCount(keyPart))
+ int idx =
+ keyIt.hasIndex() ? keyIt.getIndex() : handler
+ .getChildrenCount(node, keyPart) - 1;
+ if (idx < 0 || idx >= handler.getChildrenCount(node, keyPart))
{
return node;
}
else
{
- return findLastPathNode(keyIt, node.getChildren(keyPart).get(idx));
+ return findLastPathNode(keyIt,
+ handler.getChildren(node, keyPart).get(idx), handler);
}
}
@@ -405,28 +432,46 @@ public class DefaultExpressionEngine imp
* the current node depending on the type of the current key part (children,
* attributes, or both).
*
+ * @param <T> the type of the nodes to be dealt with
* @param keyPart the key part
* @param subNodes a list with the sub nodes to process
* @param nodes the target collection
+ * @param handler the node handler
*/
- private void processSubNodes(DefaultConfigurationKey.KeyIterator keyPart,
- List<ConfigurationNode> subNodes, Collection<ConfigurationNode> nodes)
+ private <T> void processSubNodes(DefaultConfigurationKey.KeyIterator keyPart,
+ List<T> subNodes, Collection<QueryResult<T>> nodes, NodeHandler<T> handler)
{
if (keyPart.hasIndex())
{
if (keyPart.getIndex() >= 0 && keyPart.getIndex() < subNodes.size())
{
findNodesForKey((DefaultConfigurationKey.KeyIterator) keyPart
- .clone(), subNodes.get(keyPart.getIndex()), nodes);
+ .clone(), subNodes.get(keyPart.getIndex()), nodes, handler);
}
}
else
{
- for (ConfigurationNode node : subNodes)
+ for (T node : subNodes)
{
findNodesForKey((DefaultConfigurationKey.KeyIterator) keyPart
- .clone(), node, nodes);
+ .clone(), node, nodes, handler);
}
}
}
+
+ /**
+ * Determines the index of the given node based on its parent node.
+ *
+ * @param node the current node
+ * @param parent the parent node
+ * @param nodeName the name of the current node
+ * @param handler the node handler
+ * @param <T> the type of the nodes to be dealt with
+ * @return the index of this node
+ */
+ private static <T> int determineIndex(T node, T parent, String nodeName,
+ NodeHandler<T> handler)
+ {
+ return handler.getChildren(parent, nodeName).indexOf(node);
+ }
}
Modified: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/ExpressionEngine.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/ExpressionEngine.java?rev=1588831&r1=1588830&r2=1588831&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/ExpressionEngine.java (original)
+++ commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/ExpressionEngine.java Sun Apr 20 19:32:08 2014
@@ -27,56 +27,93 @@ import java.util.List;
* An <em>expression engine</em> knows how to map a key for a configuration's
* property to a single or a set of configuration nodes. Thus it defines the way
* how properties are addressed in this configuration. Methods of a
- * configuration that have to handle property key (e.g.
- * {@code getProperty()} or {@code addProperty()} do not interpret
- * the passed in keys on their own, but delegate this task to an associated
- * expression engine. This expression engine will then find out, which
- * configuration nodes are addressed by the key.
+ * configuration that have to handle property keys (e.g. {@code getProperty()}
+ * or {@code addProperty()} do not interpret the passed in keys on their own,
+ * but delegate this task to an associated expression engine. This expression
+ * engine will then find out, which configuration nodes are addressed by the
+ * key.
* </p>
* <p>
* Separating the task of evaluating property keys from the configuration object
- * has the advantage that many different expression languages (i.e. ways for
+ * has the advantage that multiple different expression languages (i.e. ways for
* querying or setting properties) can be supported. Just set a suitable
* implementation of this interface as the configuration's expression engine,
* and you can use the syntax provided by this implementation.
* </p>
+ * <p>
+ * An {@code ExpressionEngine} can deal with nodes of different types. To
+ * achieve this, a {@link NodeHandler} for the desired type must be passed to
+ * the methods.
+ * </p>
*
* @since 1.3
- * @author <a
- * href="http://commons.apache.org/configuration/team-list.html">Commons
- * Configuration team</a>
* @version $Id$
*/
public interface ExpressionEngine
{
/**
- * Finds the node(s) that is (are) matched by the specified key. This is the
- * main method for interpreting property keys. An implementation must
- * traverse the given root node and its children to find all nodes that are
- * matched by the given key. If the key is not correct in the syntax
- * provided by that implementation, it is free to throw a (runtime)
- * exception indicating this error condition.
+ * Finds the nodes and/or attributes that are matched by the specified key.
+ * This is the main method for interpreting property keys. An implementation
+ * must traverse the given root node and its children to find all results
+ * that are matched by the given key. If the key is not correct in the
+ * syntax provided by that implementation, it is free to throw a (runtime)
+ * exception indicating this error condition. The passed in
+ * {@code NodeHandler} can be used to gather the required information from
+ * the node object.
*
- * @param root the root node of a hierarchy of configuration nodes
+ * @param <T> the type of the node to be processed
+ * @param root the root node of a hierarchy of nodes
* @param key the key to be evaluated
- * @return a list with the nodes that are matched by the key (should never
- * be <b>null</b>)
+ * @param handler the {@code NodeHandler} for accessing the node
+ * @return a list with the results that are matched by the key (should never
+ * be <b>null</b>)
*/
- List<ConfigurationNode> query(ConfigurationNode root, String key);
+ <T> List<QueryResult<T>> query(T root, String key, NodeHandler<T> handler);
/**
* Returns the key for the specified node in the expression language
* supported by an implementation. This method is called whenever a property
* key for a node has to be constructed, e.g. by the
- * {@link org.apache.commons.configuration.Configuration#getKeys() getKeys()}
- * method.
+ * {@link org.apache.commons.configuration.Configuration#getKeys()
+ * getKeys()} method.
*
+ * @param <T> the type of the node to be processed
* @param node the node, for which the key must be constructed
* @param parentKey the key of this node's parent (can be <b>null</b> for
- * the root node)
+ * the root node)
+ * @param handler the {@code NodeHandler} for accessing the node
* @return this node's key
*/
- String nodeKey(ConfigurationNode node, String parentKey);
+ <T> String nodeKey(T node, String parentKey, NodeHandler<T> handler);
+
+ /**
+ * Returns the key of an attribute. The passed in {@code parentKey} must
+ * reference the parent node of the attribute. A concrete implementation
+ * must concatenate this parent key with the attribute name to a valid key
+ * for this attribute.
+ *
+ * @param parentKey the key to the node owning this attribute
+ * @param attributeName the name of the attribute in question
+ * @return the resulting key referencing this attribute
+ */
+ String attributeKey(String parentKey, String attributeName);
+
+ /**
+ * Determines a "canonical" key for the specified node in the
+ * expression language supported by this implementation. This means that
+ * always a unique key if generated pointing to this specific node. For most
+ * concrete implementations, this means that an index is added to the node
+ * name to ensure that there are no ambiguities with child nodes having the
+ * same names.
+ *
+ * @param <T> the type of the node to be processed
+ * @param node the node, for which the key must be constructed
+ * @param parentKey the key of this node's parent (can be <b>null</b> for
+ * the root node)
+ * @param handler the {@code NodeHandler} for accessing the node
+ * @return the canonical key of this node
+ */
+ <T> String canonicalKey(T node, String parentKey, NodeHandler<T> handler);
/**
* Returns information needed for an add operation. This method gets called
@@ -84,9 +121,11 @@ public interface ExpressionEngine
* has to interpret the specified key, find the parent node for the new
* elements, and provide all information about new nodes to be added.
*
+ * @param <T> the type of the node to be processed
* @param root the root node
* @param key the key for the new property
+ * @param handler the {@code NodeHandler} for accessing the node
* @return an object with all information needed for the add operation
*/
- NodeAddData prepareAdd(ConfigurationNode root, String key);
+ <T> NodeAddData<T> prepareAdd(T root, String key, NodeHandler<T> handler);
}
Modified: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/ImmutableNode.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/ImmutableNode.java?rev=1588831&r1=1588830&r2=1588831&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/ImmutableNode.java (original)
+++ commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/ImmutableNode.java Sun Apr 20 19:32:08 2014
@@ -40,6 +40,7 @@ import java.util.Map;
* </p>
*
* @version $Id$
+ * @since 2.0
*/
public class ImmutableNode
{
@@ -113,6 +114,19 @@ public class ImmutableNode
/**
* Creates a new {@code ImmutableNode} instance which is a copy of this
+ * object with the name changed to the passed in value.
+ *
+ * @param name the name of the newly created node
+ * @return the new node with the changed name
+ */
+ public ImmutableNode setName(String name)
+ {
+ return new Builder(children, attributes).name(name).value(value)
+ .create();
+ }
+
+ /**
+ * Creates a new {@code ImmutableNode} instance which is a copy of this
* object with the value changed to the passed in value.
*
* @param newValue the value of the newly created node
@@ -202,6 +216,23 @@ public class ImmutableNode
/**
* Returns a new {@code ImmutableNode} instance which is a copy of this
+ * object, but with the children replaced by the ones in the passed in
+ * collection. With this method all children can be replaced in a single
+ * step. For the collection the same rules apply as for
+ * {@link Builder#addChildren(Collection)}.
+ *
+ * @param newChildren the collection with the new children (may be
+ * <b>null</b>)
+ */
+ public ImmutableNode replaceChildren(Collection<ImmutableNode> newChildren)
+ {
+ Builder builder = new Builder(null, attributes);
+ builder.addChildren(newChildren);
+ return createWithBasicProperties(builder);
+ }
+
+ /**
+ * Returns a new {@code ImmutableNode} instance which is a copy of this
* object, but with the specified attribute set to the given value. If an
* attribute with this name does not exist, it is created now. Otherwise,
* the new value overrides the old one.
@@ -219,6 +250,28 @@ public class ImmutableNode
/**
* Returns a new {@code ImmutableNode} instance which is a copy of this
+ * object, but with all attributes added defined by the given map. This
+ * method is analogous to {@link #setAttribute(String, Object)}, but all
+ * attributes in the given map are added. If the map is <b>null</b> or
+ * empty, this method has no effect.
+ *
+ * @param newAttributes the map with attributes to be added
+ * @return the new node with these attributes
+ */
+ public ImmutableNode setAttributes(Map<String, ?> newAttributes)
+ {
+ if (newAttributes == null || newAttributes.isEmpty())
+ {
+ return this;
+ }
+
+ Map<String, Object> newAttrs = new HashMap<String, Object>(attributes);
+ newAttrs.putAll(newAttributes);
+ return createWithNewAttributes(newAttrs);
+ }
+
+ /**
+ * Returns a new {@code ImmutableNode} instance which is a copy of this
* object, but with the specified attribute removed. If there is no
* attribute with the given name, the same node instance is returned.
*
@@ -421,10 +474,11 @@ public class ImmutableNode
* {@link #addChild(ImmutableNode)}, but it allows setting a number of
* child nodes at once.
*
+ *
* @param children a collection with the child nodes to be added
* @return a reference to this object for method chaining
*/
- public Builder addChildren(Collection<ImmutableNode> children)
+ public Builder addChildren(Collection<? extends ImmutableNode> children)
{
if (children != null)
{
@@ -576,11 +630,12 @@ public class ImmutableNode
/**
* Filters null entries from the passed in collection with child nodes.
*
+ *
* @param children the collection to be filtered
* @return the collection with null entries removed
*/
private static Collection<? extends ImmutableNode> filterNull(
- Collection<ImmutableNode> children)
+ Collection<? extends ImmutableNode> children)
{
List<ImmutableNode> result =
new ArrayList<ImmutableNode>(children.size());
Modified: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/MergeCombiner.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/MergeCombiner.java?rev=1588831&r1=1588830&r2=1588831&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/MergeCombiner.java (original)
+++ commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/MergeCombiner.java Sun Apr 20 19:32:08 2014
@@ -17,9 +17,12 @@
package org.apache.commons.configuration.tree;
import java.util.ArrayList;
-import java.util.Iterator;
+import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang3.ObjectUtils;
/**
* <p>
@@ -36,9 +39,6 @@ import java.util.List;
* </ol>
* </p>
*
- * @author <a
- * href="http://commons.apache.org/configuration/team-list.html">Commons
- * Configuration team</a>
* @version $Id$
* @since 1.7
*/
@@ -53,18 +53,18 @@ public class MergeCombiner extends NodeC
*/
@Override
- public ConfigurationNode combine(ConfigurationNode node1, ConfigurationNode node2)
+ public ImmutableNode combine(ImmutableNode node1, ImmutableNode node2)
{
- ViewNode result = createViewNode();
- result.setName(node1.getName());
- result.setValue(node1.getValue());
+ ImmutableNode.Builder result = new ImmutableNode.Builder();
+ result.name(node1.getNodeName());
+ result.value(node1.getValue());
addAttributes(result, node1, node2);
// Check if nodes can be combined
- List<ConfigurationNode> children2 = new LinkedList<ConfigurationNode>(node2.getChildren());
- for (ConfigurationNode child1 : node1.getChildren())
+ List<ImmutableNode> children2 = new LinkedList<ImmutableNode>(node2.getChildren());
+ for (ImmutableNode child1 : node1.getChildren())
{
- ConfigurationNode child2 = canCombine(node1, node2, child1, children2);
+ ImmutableNode child2 = canCombine(node2, child1, children2);
if (child2 != null)
{
result.addChild(combine(child1, child2));
@@ -77,11 +77,11 @@ public class MergeCombiner extends NodeC
}
// Add remaining children of node 2
- for (ConfigurationNode c : children2)
+ for (ImmutableNode c : children2)
{
result.addChild(c);
}
- return result;
+ return result.create();
}
/**
@@ -90,21 +90,23 @@ public class MergeCombiner extends NodeC
* second node, which are not contained in the first node, will also be
* added.
*
- * @param result the resulting node
+ * @param result the builder for the resulting node
* @param node1 the first node
* @param node2 the second node
*/
- protected void addAttributes(ViewNode result, ConfigurationNode node1,
- ConfigurationNode node2)
+ protected void addAttributes(ImmutableNode.Builder result, ImmutableNode node1,
+ ImmutableNode node2)
{
- result.appendAttributes(node1);
- for (ConfigurationNode attr : node2.getAttributes())
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.putAll(node1.getAttributes());
+ for (Map.Entry<String, Object> e : node2.getAttributes().entrySet())
{
- if (node1.getAttributeCount(attr.getName()) == 0)
+ if (!attributes.containsKey(e.getKey()))
{
- result.addAttribute(attr);
+ attributes.put(e.getKey(), e.getValue());
}
}
+ result.addAttributes(attributes);
}
/**
@@ -112,35 +114,22 @@ public class MergeCombiner extends NodeC
* only be combined if its attributes are all present in the second node and
* they all have the same value.
*
- * @param node1 the first node
* @param node2 the second node
* @param child the child node (of the first node)
+ * @param children2 the children of the 2nd node
* @return a child of the second node, with which a combination is possible
*/
- protected ConfigurationNode canCombine(ConfigurationNode node1,
- ConfigurationNode node2, ConfigurationNode child, List<ConfigurationNode> children2)
+ protected ImmutableNode canCombine(ImmutableNode node2,
+ ImmutableNode child, List<ImmutableNode> children2)
{
- List<ConfigurationNode> attrs1 = child.getAttributes();
- List<ConfigurationNode> nodes = new ArrayList<ConfigurationNode>();
+ Map<String, Object> attrs1 = child.getAttributes();
+ List<ImmutableNode> nodes = new ArrayList<ImmutableNode>();
- List<ConfigurationNode> children = node2.getChildren(child.getName());
- Iterator<ConfigurationNode> it = children.iterator();
- while (it.hasNext())
- {
- ConfigurationNode node = it.next();
- Iterator<ConfigurationNode> iter = attrs1.iterator();
- while (iter.hasNext())
- {
- ConfigurationNode attr1 = iter.next();
- List<ConfigurationNode> list2 = node.getAttributes(attr1.getName());
- if (list2.size() == 1
- && !attr1.getValue().equals(list2.get(0).getValue()))
- {
- node = null;
- break;
- }
- }
- if (node != null)
+ List<ImmutableNode> children =
+ HANDLER.getChildren(node2, child.getNodeName());
+ for (ImmutableNode node : children)
+ {
+ if (matchAttributes(attrs1, node))
{
nodes.add(node);
}
@@ -152,13 +141,36 @@ public class MergeCombiner extends NodeC
}
if (nodes.size() > 1 && !isListNode(child))
{
- Iterator<ConfigurationNode> iter = nodes.iterator();
- while (iter.hasNext())
+ for (ImmutableNode node : nodes)
{
- children2.remove(iter.next());
+ children2.remove(node);
}
}
return null;
}
+
+ /**
+ * Checks whether the attributes of the passed in node are compatible.
+ *
+ * @param attrs1 the attributes of the first node
+ * @param node the 2nd node
+ * @return a flag whether these nodes can be combined regarding their
+ * attributes
+ */
+ private static boolean matchAttributes(Map<String, Object> attrs1,
+ ImmutableNode node)
+ {
+ Map<String, Object> attrs2 = node.getAttributes();
+ for (Map.Entry<String, Object> e : attrs1.entrySet())
+ {
+ if (attrs2.containsKey(e.getKey())
+ && !ObjectUtils
+ .equals(e.getValue(), attrs2.get(e.getKey())))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
}
Modified: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/NodeAddData.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/NodeAddData.java?rev=1588831&r1=1588830&r2=1588831&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/NodeAddData.java (original)
+++ commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/NodeAddData.java Sun Apr 20 19:32:08 2014
@@ -16,8 +16,9 @@
*/
package org.apache.commons.configuration.tree;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
-import java.util.LinkedList;
import java.util.List;
/**
@@ -46,47 +47,41 @@ import java.util.List;
* </p>
*
* @since 1.3
- * @author <a
- * href="http://commons.apache.org/configuration/team-list.html">Commons
- * Configuration team</a>
* @version $Id$
+ * @param <T> the type of nodes this class can handle
*/
-public class NodeAddData
+public class NodeAddData<T>
{
/** Stores the parent node of the add operation. */
- private ConfigurationNode parent;
+ private final T parent;
/**
- * Stores a list with nodes that are on the path between the parent node and
- * the new node.
+ * Stores a list with the names of nodes that are on the path between the
+ * parent node and the new node.
*/
- private List<String> pathNodes;
+ private final List<String> pathNodes;
/** Stores the name of the new node. */
- private String newNodeName;
+ private final String newNodeName;
/** Stores the attribute flag. */
- private boolean attribute;
+ private final boolean attribute;
/**
- * Creates a new, uninitialized instance of {@code NodeAddData}.
- */
- public NodeAddData()
- {
- this(null, null);
- }
-
- /**
- * Creates a new instance of {@code NodeAddData} and sets the most
- * important data fields.
+ * Creates a new instance of {@code NodeAddData} and initializes it.
*
- * @param parent the parent node
- * @param nodeName the name of the new node
+ * @param parentNode the parent node of the add operation
+ * @param newName the name of the new node
+ * @param isAttr flag whether the new node is an attribute
+ * @param intermediateNodes an optional collection with path nodes
*/
- public NodeAddData(ConfigurationNode parent, String nodeName)
+ public NodeAddData(T parentNode, String newName, boolean isAttr,
+ Collection<String> intermediateNodes)
{
- setParent(parent);
- setNewNodeName(nodeName);
+ parent = parentNode;
+ newNodeName = newName;
+ attribute = isAttr;
+ pathNodes = createPathNodes(intermediateNodes);
}
/**
@@ -101,17 +96,6 @@ public class NodeAddData
}
/**
- * Sets the attribute flag. This flag determines whether an attribute or a
- * child node will be added.
- *
- * @param attribute the attribute flag
- */
- public void setAttribute(boolean attribute)
- {
- this.attribute = attribute;
- }
-
- /**
* Returns the name of the new node.
*
* @return the new node's name
@@ -122,39 +106,18 @@ public class NodeAddData
}
/**
- * Sets the name of the new node. A node with this name will be added to the
- * configuration's node hierarchy.
- *
- * @param newNodeName the name of the new node
- */
- public void setNewNodeName(String newNodeName)
- {
- this.newNodeName = newNodeName;
- }
-
- /**
* Returns the parent node.
*
* @return the parent node
*/
- public ConfigurationNode getParent()
+ public T getParent()
{
return parent;
}
/**
- * Sets the parent node. New nodes will be added to this node.
- *
- * @param parent the parent node
- */
- public void setParent(ConfigurationNode parent)
- {
- this.parent = parent;
- }
-
- /**
* Returns a list with further nodes that must be added. This is needed if a
- * complete branch is to be added at once. For instance imagine that there
+ * complete branch is to be added at once. For instance, imagine that there
* exists only a node {@code database}. Now the key
* {@code database.connection.settings.username} (assuming the syntax
* of the default expression engine) is to be added. Then
@@ -168,29 +131,26 @@ public class NodeAddData
*/
public List<String> getPathNodes()
{
- if (pathNodes != null)
- {
- return Collections.unmodifiableList(pathNodes);
- }
- else
- {
- return Collections.emptyList();
- }
+ return pathNodes;
}
/**
- * Adds the name of a path node. With this method an additional node to be
- * added can be defined.
+ * Creates the list with path nodes. Handles null input.
*
- * @param nodeName the name of the node
- * @see #getPathNodes()
+ * @param intermediateNodes the nodes passed to the constructor
+ * @return an unmodifiable list of path nodes
*/
- public void addPathNode(String nodeName)
+ private static List<String> createPathNodes(
+ Collection<String> intermediateNodes)
{
- if (pathNodes == null)
+ if (intermediateNodes == null)
+ {
+ return Collections.emptyList();
+ }
+ else
{
- pathNodes = new LinkedList<String>();
+ return Collections.unmodifiableList(new ArrayList<String>(
+ intermediateNodes));
}
- pathNodes.add(nodeName);
}
}
Modified: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/NodeCombiner.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/NodeCombiner.java?rev=1588831&r1=1588830&r2=1588831&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/NodeCombiner.java (original)
+++ commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/NodeCombiner.java Sun Apr 20 19:32:08 2014
@@ -44,16 +44,22 @@ import java.util.Set;
* can be passed the name of a node, which should be considered a list node.
* </p>
*
- * @author <a
- * href="http://commons.apache.org/configuration/team-list.html">Commons
- * Configuration team</a>
* @version $Id$
* @since 1.3
*/
public abstract class NodeCombiner
{
+ /**
+ * A default handler object for immutable nodes. This object can be used by
+ * derived classes for dealing with nodes. However, it provides only limited
+ * functionality; it supports only operations on child nodes, but no
+ * references to parent nodes.
+ */
+ protected static final NodeHandler<ImmutableNode> HANDLER =
+ createNodeHandler();
+
/** Stores a list with node names that are known to be list nodes. */
- protected Set<String> listNodes;
+ private final Set<String> listNodes;
/**
* Creates a new instance of {@code NodeCombiner}.
@@ -92,9 +98,9 @@ public abstract class NodeCombiner
* @param node the node to be tested
* @return a flag whether this is a list node
*/
- public boolean isListNode(ConfigurationNode node)
+ public boolean isListNode(ImmutableNode node)
{
- return listNodes.contains(node.getName());
+ return listNodes.contains(node.getNodeName());
}
/**
@@ -104,21 +110,32 @@ public abstract class NodeCombiner
*
* @param node1 the first root node
* @param node2 the second root node
- * @return the resulting combined node structure
+ * @return the root node of the resulting combined node structure
*/
- public abstract ConfigurationNode combine(ConfigurationNode node1,
- ConfigurationNode node2);
+ public abstract ImmutableNode combine(ImmutableNode node1,
+ ImmutableNode node2);
/**
- * Creates a new view node. This method will be called whenever a new view
- * node is to be created. It can be overridden to create special view nodes.
- * This base implementation returns a new instance of
- * {@link ViewNode}.
+ * Creates a node handler object for immutable nodes which can be used by
+ * sub classes to perform advanced operations on nodes.
*
- * @return the new view node
+ * @return the node handler implementation
*/
- protected ViewNode createViewNode()
+ private static NodeHandler<ImmutableNode> createNodeHandler()
{
- return new ViewNode();
+ return new AbstractImmutableNodeHandler()
+ {
+ @Override
+ public ImmutableNode getParent(ImmutableNode node)
+ {
+ return null;
+ }
+
+ @Override
+ public ImmutableNode getRootNode()
+ {
+ return null;
+ }
+ };
}
}
Modified: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/NodeHandler.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/NodeHandler.java?rev=1588831&r1=1588830&r2=1588831&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/NodeHandler.java (original)
+++ commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/NodeHandler.java Sun Apr 20 19:32:08 2014
@@ -17,6 +17,7 @@
package org.apache.commons.configuration.tree;
import java.util.List;
+import java.util.Set;
/**
* <p>
@@ -28,15 +29,15 @@ import java.util.List;
* {@code NodeHandler} is used. The handler provides a number of methods for
* querying the internal state of a node in a read-only way.
* </p>
- *
+ *
* @version $Id$
- * @param T the type of the nodes this handler deals with
+ * @param <T> the type of the nodes this handler deals with
*/
public interface NodeHandler<T>
{
/**
* Returns the name of the specified node
- *
+ *
* @param node the node
* @return the name of this node
*/
@@ -44,7 +45,7 @@ public interface NodeHandler<T>
/**
* Returns the value of the specified node.
- *
+ *
* @param node the node
* @return the value of this node
*/
@@ -52,7 +53,7 @@ public interface NodeHandler<T>
/**
* Returns the parent of the specified node.
- *
+ *
* @param node the node
* @return the parent node
*/
@@ -60,7 +61,7 @@ public interface NodeHandler<T>
/**
* Returns an unmodifiable list with all children of the specified node.
- *
+ *
* @param node the node
* @return a list with the child nodes of this node
*/
@@ -69,7 +70,7 @@ public interface NodeHandler<T>
/**
* Returns an unmodifiable list of all children of the specified node with
* the given name.
- *
+ *
* @param node the node
* @param name the name of the desired child nodes
* @return a list with all children with the given name
@@ -78,7 +79,7 @@ public interface NodeHandler<T>
/**
* Returns the child with the given index of the specified node.
- *
+ *
* @param node the node
* @param index the index (0-based)
* @return the child with the given index
@@ -86,18 +87,18 @@ public interface NodeHandler<T>
T getChild(T node, int index);
/**
- * Returns the index of the given child node relative to its name. This
- * method can be called when a unique identifier for a specific node is
- * needed. The node name alone might not be sufficient because there may be
- * multiple child nodes with the same name. This method returns 0 if the
- * given node is the first child node with this name, 1 for the second child
- * node and so on. If the node has no parent node or if it is an attribute,
- * -1 is returned.
- *
- * @param node a child node whose index is to be retrieved
+ * Returns the index of the given child node in the list of children of its
+ * parent. This method is the opposite operation of
+ * {@link #getChild(Object, int)}. This method returns 0 if the given node
+ * is the first child node with this name, 1 for the second child node and
+ * so on. If the node has no parent node or if it is an attribute, -1 is
+ * returned.
+ *
+ * @param parent the parent node
+ * @param child a child node whose index is to be retrieved
* @return the index of this child node
*/
- int indexOfChild(T node);
+ int indexOfChild(T parent, T child);
/**
* Returns the number of children of the specified node with the given name.
@@ -108,7 +109,7 @@ public interface NodeHandler<T>
* a child name is passed in, only the children with this name are taken
* into account. If the name <b>null</b> is passed, the total number of
* children must be returned.
- *
+ *
* @param node the node
* @param name the name of the children in question (can be <b>null</b> for
* all children)
@@ -117,17 +118,17 @@ public interface NodeHandler<T>
int getChildrenCount(T node, String name);
/**
- * Returns an unmodifiable list with the names of all attributes of the
+ * Returns an unmodifiable set with the names of all attributes of the
* specified node.
- *
+ *
* @param node the node
- * @return a list with the names of all attributes of this node
+ * @return a set with the names of all attributes of this node
*/
- List<String> getAttributes(T node);
+ Set<String> getAttributes(T node);
/**
* Returns a flag whether the passed in node has any attributes.
- *
+ *
* @param node the node
* @return a flag whether this node has any attributes
*/
@@ -137,7 +138,7 @@ public interface NodeHandler<T>
* Returns the value of the specified attribute from the given node. If a
* concrete {@code NodeHandler} supports attributes with multiple values,
* result might be a collection.
- *
+ *
* @param node the node
* @param name the name of the attribute
* @return the value of this attribute
@@ -148,9 +149,16 @@ public interface NodeHandler<T>
* Checks whether the specified node is defined. Nodes are
* "defined" if they contain any data, e.g. a value, or
* attributes, or defined children.
- *
+ *
* @param node the node to test
* @return a flag whether the passed in node is defined
*/
boolean isDefined(T node);
+
+ /**
+ * Returns the root node of the underlying hierarchy.
+ *
+ * @return the current root node
+ */
+ T getRootNode();
}
Modified: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/OverrideCombiner.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/OverrideCombiner.java?rev=1588831&r1=1588830&r2=1588831&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/OverrideCombiner.java (original)
+++ commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/OverrideCombiner.java Sun Apr 20 19:32:08 2014
@@ -47,9 +47,6 @@ package org.apache.commons.configuration
* will never be combined.
* </p>
*
- * @author <a
- * href="http://commons.apache.org/configuration/team-list.html">Commons
- * Configuration team</a>
* @version $Id$
* @since 1.3
*/
@@ -63,16 +60,16 @@ public class OverrideCombiner extends No
* @return the resulting combined node structure
*/
@Override
- public ConfigurationNode combine(ConfigurationNode node1,
- ConfigurationNode node2)
+ public ImmutableNode combine(ImmutableNode node1,
+ ImmutableNode node2)
{
- ViewNode result = createViewNode();
- result.setName(node1.getName());
+ ImmutableNode.Builder result = new ImmutableNode.Builder();
+ result.name(node1.getNodeName());
// Process nodes from the first structure, which override the second
- for (ConfigurationNode child : node1.getChildren())
+ for (ImmutableNode child : node1.getChildren())
{
- ConfigurationNode child2 = canCombine(node1, node2, child);
+ ImmutableNode child2 = canCombine(node1, node2, child);
if (child2 != null)
{
result.addChild(combine(child, child2));
@@ -85,9 +82,9 @@ public class OverrideCombiner extends No
// Process nodes from the second structure, which are not contained
// in the first structure
- for (ConfigurationNode child : node2.getChildren())
+ for (ImmutableNode child : node2.getChildren())
{
- if (node1.getChildrenCount(child.getName()) < 1)
+ if (HANDLER.getChildrenCount(node1, child.getNodeName()) < 1)
{
result.addChild(child);
}
@@ -95,31 +92,31 @@ public class OverrideCombiner extends No
// Handle attributes and value
addAttributes(result, node1, node2);
- result.setValue((node1.getValue() != null) ? node1.getValue() : node2
+ result.value((node1.getValue() != null) ? node1.getValue() : node2
.getValue());
- return result;
+ return result.create();
}
/**
* Handles the attributes during a combination process. First all attributes
- * of the first node will be added to the result. Then all attributes of the
- * second node, which are not contained in the first node, will also be
- * added.
+ * of the first node are added to the result. Then all attributes of the
+ * second node, which are not contained in the first node, are also added.
*
* @param result the resulting node
* @param node1 the first node
* @param node2 the second node
*/
- protected void addAttributes(ViewNode result, ConfigurationNode node1,
- ConfigurationNode node2)
+ protected void addAttributes(ImmutableNode.Builder result,
+ ImmutableNode node1, ImmutableNode node2)
{
- result.appendAttributes(node1);
- for (ConfigurationNode attr : node2.getAttributes())
+ result.addAttributes(node1.getAttributes());
+ for (String attr : node2.getAttributes().keySet())
{
- if (node1.getAttributeCount(attr.getName()) == 0)
+ if (!node1.getAttributes().containsKey(attr))
{
- result.addAttribute(attr);
+ result.addAttribute(attr,
+ HANDLER.getAttributeValue(node2, attr));
}
}
}
@@ -136,14 +133,14 @@ public class OverrideCombiner extends No
* @param child the child node (of the first node)
* @return a child of the second node, with which a combination is possible
*/
- protected ConfigurationNode canCombine(ConfigurationNode node1,
- ConfigurationNode node2, ConfigurationNode child)
+ protected ImmutableNode canCombine(ImmutableNode node1,
+ ImmutableNode node2, ImmutableNode child)
{
- if (node2.getChildrenCount(child.getName()) == 1
- && node1.getChildrenCount(child.getName()) == 1
+ if (HANDLER.getChildrenCount(node2, child.getNodeName()) == 1
+ && HANDLER.getChildrenCount(node1, child.getNodeName()) == 1
&& !isListNode(child))
{
- return node2.getChildren(child.getName()).get(0);
+ return HANDLER.getChildren(node2, child.getNodeName()).get(0);
}
else
{
Modified: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/TreeUtils.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/TreeUtils.java?rev=1588831&r1=1588830&r2=1588831&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/TreeUtils.java (original)
+++ commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/TreeUtils.java Sun Apr 20 19:32:08 2014
@@ -17,13 +17,11 @@
package org.apache.commons.configuration.tree;
import java.io.PrintStream;
-import java.util.Iterator;
+import java.util.Map;
/**
* Utility methods.
- * @author <a
- * href="http://commons.apache.org/configuration/team-list.html">Commons
- * Configuration team</a>
+ *
* @version $Id$
* @since 1.7
*/
@@ -39,7 +37,7 @@ public final class TreeUtils
* @param stream The OutputStream.
* @param result The root node of the tree.
*/
- public static void printTree(PrintStream stream, ConfigurationNode result)
+ public static void printTree(PrintStream stream, ImmutableNode result)
{
if (stream != null)
{
@@ -47,14 +45,12 @@ public final class TreeUtils
}
}
- private static void printTree(PrintStream stream, String indent, ConfigurationNode result)
+ private static void printTree(PrintStream stream, String indent, ImmutableNode result)
{
- StringBuffer buffer = new StringBuffer(indent).append("<").append(result.getName());
- Iterator<ConfigurationNode> iter = result.getAttributes().iterator();
- while (iter.hasNext())
+ StringBuilder buffer = new StringBuilder(indent).append("<").append(result.getNodeName());
+ for (Map.Entry<String, Object> e : result.getAttributes().entrySet())
{
- ConfigurationNode node = iter.next();
- buffer.append(" ").append(node.getName()).append("='").append(node.getValue()).append("'");
+ buffer.append(' ').append(e.getKey()).append("='").append(e.getValue()).append("'");
}
buffer.append(">");
stream.print(buffer.toString());
@@ -63,13 +59,12 @@ public final class TreeUtils
stream.print(result.getValue());
}
boolean newline = false;
- if (result.getChildrenCount() > 0)
+ if (!result.getChildren().isEmpty())
{
stream.print("\n");
- iter = result.getChildren().iterator();
- while (iter.hasNext())
+ for (ImmutableNode child : result.getChildren())
{
- printTree(stream, indent + " ", iter.next());
+ printTree(stream, indent + " ", child);
}
newline = true;
}
@@ -77,6 +72,6 @@ public final class TreeUtils
{
stream.print(indent);
}
- stream.println("</" + result.getName() + ">");
+ stream.println("</" + result.getNodeName() + ">");
}
}
Modified: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/UnionCombiner.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/UnionCombiner.java?rev=1588831&r1=1588830&r2=1588831&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/UnionCombiner.java (original)
+++ commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/UnionCombiner.java Sun Apr 20 19:32:08 2014
@@ -25,7 +25,7 @@ import java.util.List;
* that constructs a union from two passed in node hierarchies.
* </p>
* <p>
- * The given source hierarchies are traversed and their nodes are added to the
+ * The given source hierarchies are traversed, and their nodes are added to the
* resulting structure. Under some circumstances two nodes can be combined
* rather than adding both. This is the case if both nodes are single children
* (no lists) of their parents and do not have values. The corresponding check
@@ -108,10 +108,14 @@ import java.util.List;
* must not combine the {@code Table} nodes, but add it both to the
* resulting tree.
* </p>
+ * <p>
+ * Another limitation is the handling of attributes: Attributes can only
+ * have a single value. So if two nodes are to be combined which both have
+ * an attribute with the same name, it is not possible to construct a
+ * proper union attribute. In this case, the attribute value from the
+ * first node is used.
+ * </p>
*
- * @author <a
- * href="http://commons.apache.org/configuration/team-list.html">Commons
- * Configuration team</a>
* @version $Id$
* @since 1.3
*/
@@ -125,20 +129,22 @@ public class UnionCombiner extends NodeC
* @return the union node
*/
@Override
- public ConfigurationNode combine(ConfigurationNode node1,
- ConfigurationNode node2)
+ public ImmutableNode combine(ImmutableNode node1,
+ ImmutableNode node2)
{
- ViewNode result = createViewNode();
- result.setName(node1.getName());
- result.appendAttributes(node1);
- result.appendAttributes(node2);
+ ImmutableNode.Builder result = new ImmutableNode.Builder();
+ result.name(node1.getNodeName());
+
+ // attributes of the first node take precedence
+ result.addAttributes(node2.getAttributes());
+ result.addAttributes(node1.getAttributes());
// Check if nodes can be combined
- List<ConfigurationNode> children2 = new LinkedList<ConfigurationNode>(node2.getChildren());
- for (ConfigurationNode child1 : node1.getChildren())
+ List<ImmutableNode> children2 = new LinkedList<ImmutableNode>(node2.getChildren());
+ for (ImmutableNode child1 : node1.getChildren())
{
- ConfigurationNode child2 = findCombineNode(node1, node2, child1,
- children2);
+ ImmutableNode child2 = findCombineNode(node1, node2, child1
+ );
if (child2 != null)
{
result.addChild(combine(child1, child2));
@@ -151,12 +157,12 @@ public class UnionCombiner extends NodeC
}
// Add remaining children of node 2
- for (ConfigurationNode c : children2)
+ for (ImmutableNode c : children2)
{
result.addChild(c);
}
- return result;
+ return result.create();
}
/**
@@ -188,19 +194,18 @@ public class UnionCombiner extends NodeC
* @param node1 the first source node
* @param node2 the second source node
* @param child the child node of the first source node to be checked
- * @param children a list with all children of the second source node
* @return the matching child node of the second source node or <b>null</b>
* if there is none
*/
- protected ConfigurationNode findCombineNode(ConfigurationNode node1,
- ConfigurationNode node2, ConfigurationNode child, List<ConfigurationNode> children)
+ protected ImmutableNode findCombineNode(ImmutableNode node1,
+ ImmutableNode node2, ImmutableNode child)
{
if (child.getValue() == null && !isListNode(child)
- && node1.getChildrenCount(child.getName()) == 1
- && node2.getChildrenCount(child.getName()) == 1)
+ && HANDLER.getChildrenCount(node1, child.getNodeName()) == 1
+ && HANDLER.getChildrenCount(node2, child.getNodeName()) == 1)
{
- ConfigurationNode child2 = node2.getChildren(
- child.getName()).iterator().next();
+ ImmutableNode child2 =
+ HANDLER.getChildren(node2, child.getNodeName()).get(0);
if (child2.getValue() == null)
{
return child2;
Modified: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodeIteratorAttribute.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodeIteratorAttribute.java?rev=1588831&r1=1588830&r2=1588831&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodeIteratorAttribute.java (original)
+++ commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodeIteratorAttribute.java Sun Apr 20 19:32:08 2014
@@ -18,46 +18,78 @@ package org.apache.commons.configuration
import java.util.ArrayList;
import java.util.Collections;
+import java.util.LinkedHashSet;
import java.util.List;
+import java.util.Set;
-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 <a
- * href="http://commons.apache.org/configuration/team-list.html">Commons
- * Configuration team</a>
* @version $Id$
+ * @param <T> the type of the nodes this iterator deals with
*/
-class ConfigurationNodeIteratorAttribute extends
- ConfigurationNodeIteratorBase
+class ConfigurationNodeIteratorAttribute<T> extends
+ ConfigurationNodeIteratorBase<T>
{
/** Constant for the wildcard node name.*/
private static final String WILDCARD = "*";
+ /** Stores the parent node pointer. */
+ private ConfigurationNodePointer<T> parentPointer;
+
+ /** A list with the names of the managed attributes. */
+ private List<String> attributeNames;
+
/**
* Creates a new instance of {@code ConfigurationNodeIteratorAttribute}.
* @param parent the parent node pointer
* @param name the name of the selected attribute
*/
- public ConfigurationNodeIteratorAttribute(NodePointer parent, QName name)
+ public ConfigurationNodeIteratorAttribute(
+ ConfigurationNodePointer<T> parent, QName name)
{
super(parent, false);
- initSubNodeList(createSubNodeList((ConfigurationNode) parent.getNode(),
- name));
+ parentPointer = parent;
+ attributeNames = createAttributeDataList(parent, name);
+ }
+
+ /**
+ * Creates a pointer for the node at the specified position.
+ *
+ * @param position the desired position
+ * @return a pointer for the attribute at this position
+ */
+ @Override
+ protected NodePointer createNodePointer(int position)
+ {
+ return new ConfigurationAttributePointer<T>(parentPointer,
+ attributeNames.get(position));
+ }
+
+ /**
+ * Returns the size of the managed iteration.
+ *
+ * @return the iteration size
+ */
+ @Override
+ protected int size()
+ {
+ return attributeNames.size();
}
/**
* Determines which attributes are selected based on the passed in node
* name.
- * @param node the current node
+ *
+ * @param parent the parent node pointer
* @param name the name of the selected attribute
* @return a list with the selected attributes
*/
- protected List<ConfigurationNode> createSubNodeList(ConfigurationNode node, QName name)
+ private List<String> createAttributeDataList(
+ ConfigurationNodePointer<T> parent, QName name)
{
if (name.getPrefix() != null)
{
@@ -65,16 +97,40 @@ class ConfigurationNodeIteratorAttribute
return Collections.emptyList();
}
- List<ConfigurationNode> result = new ArrayList<ConfigurationNode>();
+ List<String> result = new ArrayList<String>();
if (!WILDCARD.equals(name.getName()))
{
- result.addAll(node.getAttributes(name.getName()));
+ addAttributeData(parent, result, name.getName());
}
else
{
- result.addAll(node.getAttributes());
+ Set<String> names =
+ new LinkedHashSet<String>(parent.getNodeHandler()
+ .getAttributes(parent.getConfigurationNode()));
+ for (String n : names)
+ {
+ addAttributeData(parent, result, n);
+ }
}
return result;
}
+
+ /**
+ * Helper method for checking whether an attribute is defined and adding it
+ * to the list of attributes to iterate over.
+ *
+ * @param parent the parent node pointer
+ * @param result the result list
+ * @param name the name of the current attribute
+ */
+ private void addAttributeData(ConfigurationNodePointer<T> parent,
+ List<String> result, String name)
+ {
+ if (parent.getNodeHandler().getAttributeValue(
+ parent.getConfigurationNode(), name) != null)
+ {
+ result.add(name);
+ }
+ }
}
Modified: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodeIteratorBase.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodeIteratorBase.java?rev=1588831&r1=1588830&r2=1588831&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodeIteratorBase.java (original)
+++ commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodeIteratorBase.java Sun Apr 20 19:32:08 2014
@@ -16,9 +16,7 @@
*/
package org.apache.commons.configuration.tree.xpath;
-import java.util.List;
-
-import org.apache.commons.configuration.tree.ConfigurationNode;
+import org.apache.commons.configuration.tree.NodeHandler;
import org.apache.commons.jxpath.ri.model.NodeIterator;
import org.apache.commons.jxpath.ri.model.NodePointer;
@@ -33,18 +31,13 @@ import org.apache.commons.jxpath.ri.mode
* </p>
*
* @since 1.3
- * @author <a
- * href="http://commons.apache.org/configuration/team-list.html">Commons
- * Configuration team</a>
* @version $Id$
+ * @param <T> the type of the nodes this iterator deals with
*/
-abstract class ConfigurationNodeIteratorBase implements NodeIterator
+abstract class ConfigurationNodeIteratorBase<T> implements NodeIterator
{
/** Stores the parent node pointer. */
- private final NodePointer parent;
-
- /** Stores the list with the sub nodes. */
- private List<ConfigurationNode> subNodes;
+ private final ConfigurationNodePointer<T> parent;
/** Stores the current position. */
private int position;
@@ -62,7 +55,8 @@ abstract class ConfigurationNodeIterator
* @param parent the parent pointer
* @param reverse the reverse flag
*/
- protected ConfigurationNodeIteratorBase(NodePointer parent, boolean reverse)
+ protected ConfigurationNodeIteratorBase(ConfigurationNodePointer<T> parent,
+ boolean reverse)
{
this.parent = parent;
this.reverse = reverse;
@@ -73,7 +67,6 @@ abstract class ConfigurationNodeIterator
*
* @return the position
*/
- @Override
public int getPosition()
{
return position;
@@ -85,7 +78,6 @@ abstract class ConfigurationNodeIterator
* @param pos the new position
* @return a flag if this is a valid position
*/
- @Override
public boolean setPosition(int pos)
{
position = pos;
@@ -97,7 +89,6 @@ abstract class ConfigurationNodeIterator
*
* @return the current pointer in this iteration
*/
- @Override
public NodePointer getNodePointer()
{
if (getPosition() < 1 && !setPosition(1))
@@ -105,7 +96,7 @@ abstract class ConfigurationNodeIterator
return null;
}
- return createNodePointer(subNodes.get(positionToIndex(getPosition())));
+ return createNodePointer(positionToIndex(getPosition()));
}
/**
@@ -113,12 +104,23 @@ abstract class ConfigurationNodeIterator
*
* @return the parent node pointer
*/
- protected NodePointer getParent()
+ protected ConfigurationNodePointer<T> getParent()
{
return parent;
}
/**
+ * Returns the node handler for the managed nodes. This is a convenience
+ * method.
+ *
+ * @return the node handler
+ */
+ protected NodeHandler<T> getNodeHandler()
+ {
+ return getParent().getNodeHandler();
+ }
+
+ /**
* Returns the start offset of the iteration.
*
* @return the start offset
@@ -148,29 +150,25 @@ abstract class ConfigurationNodeIterator
}
/**
- * Initializes the list of sub nodes for the iteration. This method must be
- * called during initialization phase.
+ * Returns the maximum position for this iterator.
*
- * @param nodes the list with the sub nodes
+ * @return the maximum allowed position
*/
- protected void initSubNodeList(List<ConfigurationNode> nodes)
+ protected int getMaxPosition()
{
- subNodes = nodes;
- if (reverse)
- {
- setStartOffset(subNodes.size());
- }
+ return reverse ? getStartOffset() + 1 : size() - getStartOffset();
}
/**
- * Returns the maximum position for this iterator.
+ * Returns the index in the data list for the given position. This method
+ * also checks the reverse flag.
*
- * @return the maximum allowed position
+ * @param pos the position (1-based)
+ * @return the corresponding list index
*/
- protected int getMaxPosition()
+ protected int positionToIndex(int pos)
{
- return reverse ? getStartOffset() + 1 : subNodes.size()
- - getStartOffset();
+ return (reverse ? 1 - pos : pos - 1) + getStartOffset();
}
/**
@@ -178,23 +176,15 @@ abstract class ConfigurationNodeIterator
* method is called by {@code getNodePointer()}. Derived classes
* must create the correct pointer object.
*
- * @param node the current configuration node
+ * @param position the current position in the iteration
* @return the node pointer
*/
- protected NodePointer createNodePointer(ConfigurationNode node)
- {
- return new ConfigurationNodePointer(getParent(), node);
- }
+ protected abstract NodePointer createNodePointer(int position);
/**
- * Returns the index in the data list for the given position. This method
- * also checks the reverse flag.
+ * Returns the number of elements in this iteration.
*
- * @param pos the position (1-based)
- * @return the corresponding list index
+ * @return the number of elements
*/
- protected int positionToIndex(int pos)
- {
- return (reverse ? 1 - pos : pos - 1) + getStartOffset();
- }
+ protected abstract int size();
}
Modified: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodeIteratorChildren.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodeIteratorChildren.java?rev=1588831&r1=1588830&r2=1588831&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodeIteratorChildren.java (original)
+++ commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodeIteratorChildren.java Sun Apr 20 19:32:08 2014
@@ -20,7 +20,6 @@ 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.Compiler;
import org.apache.commons.jxpath.ri.QName;
import org.apache.commons.jxpath.ri.compiler.NodeNameTest;
@@ -34,37 +33,71 @@ import org.apache.commons.lang3.StringUt
* node.
*
* @since 1.3
- * @author <a
- * href="http://commons.apache.org/configuration/team-list.html">Commons
- * Configuration team</a>
* @version $Id$
*/
-class ConfigurationNodeIteratorChildren extends ConfigurationNodeIteratorBase
+class ConfigurationNodeIteratorChildren<T> extends
+ ConfigurationNodeIteratorBase<T>
{
+ /** The list with the sub nodes to iterate over. */
+ private final List<T> subNodes;
+
/**
- * Creates a new instance of {@code ConfigurationNodeIteratorChildren}
- * and initializes it.
+ * Creates a new instance of {@code ConfigurationNodeIteratorChildren} 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)
+ public ConfigurationNodeIteratorChildren(
+ ConfigurationNodePointer<T> parent, NodeTest nodeTest,
+ boolean reverse, ConfigurationNodePointer<T> startsWith)
{
super(parent, reverse);
- ConfigurationNode root = (ConfigurationNode) parent.getNode();
- List<ConfigurationNode> childNodes = createSubNodeList(root, nodeTest);
- initSubNodeList(childNodes);
+ T root = parent.getConfigurationNode();
+ subNodes = createSubNodeList(root, nodeTest);
+
if (startsWith != null)
{
- setStartOffset(findStartIndex(root,
- (ConfigurationNode) startsWith.getNode()));
+ setStartOffset(findStartIndex(subNodes,
+ startsWith.getConfigurationNode()));
+ }
+ else
+ {
+ if (reverse)
+ {
+ setStartOffset(size());
+ }
}
}
/**
+ * Creates the configuration node pointer for the current position.
+ *
+ * @param position the current position in the iteration
+ * @return the node pointer
+ */
+ @Override
+ protected NodePointer createNodePointer(int position)
+ {
+ return new ConfigurationNodePointer<T>(getParent(), subNodes
+ .get(position), getNodeHandler());
+ }
+
+ /**
+ * Returns the number of elements in this iteration. This is the number of
+ * elements in the children list.
+ *
+ * @return the number of elements
+ */
+ @Override
+ protected int size()
+ {
+ return subNodes.size();
+ }
+
+ /**
* 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.
@@ -73,9 +106,9 @@ class ConfigurationNodeIteratorChildren
* @param test the test object
* @return a list with the matching nodes
*/
- protected List<ConfigurationNode> createSubNodeList(ConfigurationNode node, NodeTest test)
+ private List<T> createSubNodeList(T node, NodeTest test)
{
- List<ConfigurationNode> children = node.getChildren();
+ List<T> children = getNodeHandler().getChildren(node);
if (test == null)
{
@@ -94,10 +127,11 @@ class ConfigurationNodeIteratorChildren
return children;
}
- List<ConfigurationNode> result = new ArrayList<ConfigurationNode>();
- for (ConfigurationNode child : children)
+ List<T> result = new ArrayList<T>();
+ for (T child : children)
{
- if (StringUtils.equals(name.getName(), child.getName()))
+ if (StringUtils.equals(name.getName(), getNodeHandler()
+ .nodeName(child)))
{
result.add(child);
}
@@ -124,19 +158,20 @@ class ConfigurationNodeIteratorChildren
* 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 children the children of the root node
* @param startNode the start node
* @return the start node's index
*/
- protected int findStartIndex(ConfigurationNode node,
- ConfigurationNode startNode)
+ private int findStartIndex(List<T> children, T startNode)
{
- for (int index = 0; index < node.getChildrenCount(); index++)
+ int index = 0;
+ for(T child : children)
{
- if (node.getChild(index) == startNode)
+ if(child == startNode)
{
return index;
}
+ index++;
}
return -1;
Modified: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodePointer.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodePointer.java?rev=1588831&r1=1588830&r2=1588831&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodePointer.java (original)
+++ commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/tree/xpath/ConfigurationNodePointer.java Sun Apr 20 19:32:08 2014
@@ -16,10 +16,9 @@
*/
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.NodeHandler;
import org.apache.commons.jxpath.ri.Compiler;
import org.apache.commons.jxpath.ri.QName;
import org.apache.commons.jxpath.ri.compiler.NodeTest;
@@ -36,31 +35,36 @@ import org.apache.commons.jxpath.ri.mode
* </p>
*
* @since 1.3
- * @author <a
- * href="http://commons.apache.org/configuration/team-list.html">Commons
- * Configuration team</a>
* @version $Id$
+ * @param <T> the type of the nodes this pointer deals with
*/
-class ConfigurationNodePointer extends NodePointer
+class ConfigurationNodePointer<T> extends NodePointer
{
/**
* The serial version UID.
*/
private static final long serialVersionUID = -1087475639680007713L;
- /** Stores the associated configuration node. */
- private final ConfigurationNode node;
+ /** The node handler. */
+ private final NodeHandler<T> handler;
+
+ /** Stores the associated node. */
+ private final T node;
/**
- * Creates a new instance of {@code ConfigurationNodePointer}.
+ * Creates a new instance of {@code ConfigurationNodePointer} pointing to
+ * the specified node.
*
- * @param node the node
+ * @param node the wrapped node
* @param locale the locale
+ * @param handler the {@code NodeHandler}
*/
- public ConfigurationNodePointer(ConfigurationNode node, Locale locale)
+ public ConfigurationNodePointer(T node, Locale locale,
+ NodeHandler<T> handler)
{
super(null, locale);
this.node = node;
+ this.handler = handler;
}
/**
@@ -69,11 +73,14 @@ class ConfigurationNodePointer extends N
*
* @param parent the parent pointer
* @param node the associated node
+ * @param handler the {@code NodeHandler}
*/
- public ConfigurationNodePointer(NodePointer parent, ConfigurationNode node)
+ public ConfigurationNodePointer(ConfigurationNodePointer<T> parent, T node,
+ NodeHandler<T> handler)
{
super(parent);
this.node = node;
+ this.handler = handler;
}
/**
@@ -85,7 +92,7 @@ class ConfigurationNodePointer extends N
@Override
public boolean isLeaf()
{
- return node.getChildrenCount() < 1;
+ return getNodeHandler().getChildrenCount(node, null) < 1;
}
/**
@@ -111,15 +118,15 @@ class ConfigurationNodePointer extends N
}
/**
- * Checks whether this node pointer refers to an attribute node. This method
- * checks the attribute flag of the associated configuration node.
+ * Checks whether this node pointer refers to an attribute node. This is
+ * not the case.
*
* @return the attribute flag
*/
@Override
public boolean isAttribute()
{
- return node.isAttribute();
+ return false;
}
/**
@@ -130,7 +137,7 @@ class ConfigurationNodePointer extends N
@Override
public QName getName()
{
- return new QName(null, node.getName());
+ return new QName(null, getNodeHandler().nodeName(node));
}
/**
@@ -164,18 +171,19 @@ class ConfigurationNodePointer extends N
@Override
public Object getValue()
{
- return node.getValue();
+ return getNodeHandler().getValue(node);
}
/**
- * Sets the value of this node.
+ * Sets the value of this node. This is not supported, so always an
+ * exception is thrown.
*
* @param value the new value
*/
@Override
public void setValue(Object value)
{
- node.setValue(value);
+ throw new UnsupportedOperationException("Node value cannot be set!");
}
/**
@@ -189,37 +197,22 @@ class ConfigurationNodePointer extends N
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;
- }
+ Object node1 = pointer1.getBaseValue();
+ Object node2 = pointer2.getBaseValue();
- else
+ // sort based on the occurrence in the sub node list
+ for (T child : getNodeHandler().getChildren(node))
{
- // sort based on the occurrence in the sub node list
- List<ConfigurationNode> subNodes = node1.isAttribute() ? node.getAttributes() : node
- .getChildren();
- for (ConfigurationNode child : subNodes)
+ if (child == node1)
{
- if (child == node1)
- {
- return -1;
- }
- else if (child == node2)
- {
- return 1;
- }
+ return -1;
+ }
+ else if (child == node2)
+ {
+ return 1;
}
- return 0; // should not happen
}
+ return 0; // should not happen
}
/**
@@ -231,7 +224,7 @@ class ConfigurationNodePointer extends N
@Override
public NodeIterator attributeIterator(QName name)
{
- return new ConfigurationNodeIteratorAttribute(this, name);
+ return new ConfigurationNodeIteratorAttribute<T>(this, name);
}
/**
@@ -246,8 +239,8 @@ class ConfigurationNodePointer extends N
public NodeIterator childIterator(NodeTest test, boolean reverse,
NodePointer startWith)
{
- return new ConfigurationNodeIteratorChildren(this, test, reverse,
- startWith);
+ return new ConfigurationNodeIteratorChildren<T>(this, test, reverse,
+ castPointer(startWith));
}
/**
@@ -267,4 +260,40 @@ class ConfigurationNodePointer extends N
}
return super.testNode(test);
}
+
+ /**
+ * Returns the {@code NodeHandler} used by this instance.
+ *
+ * @return the {@code NodeHandler}
+ */
+ public NodeHandler<T> getNodeHandler()
+ {
+ return handler;
+ }
+
+ /**
+ * Returns the wrapped configuration node.
+ *
+ * @return the wrapped node
+ */
+ public T getConfigurationNode()
+ {
+ return node;
+ }
+
+ /**
+ * Casts the given child pointer to a node pointer of this type. This is a
+ * bit dangerous. However, in a typical setup, child node pointers can only
+ * be created by this instance which ensures that they are of the correct
+ * type. Therefore, this cast is safe.
+ *
+ * @param p the {@code NodePointer} to cast
+ * @return the resulting {@code ConfigurationNodePointer}
+ */
+ private ConfigurationNodePointer<T> castPointer(NodePointer p)
+ {
+ @SuppressWarnings("unchecked") // see method comment
+ ConfigurationNodePointer<T> result = (ConfigurationNodePointer<T>) p;
+ return result;
+ }
}