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/03/01 21:06:25 UTC

svn commit: r1573214 - in /commons/proper/configuration/branches/immutableNodes/src: main/java/org/apache/commons/configuration/tree/ test/java/org/apache/commons/configuration/tree/

Author: oheger
Date: Sat Mar  1 20:06:24 2014
New Revision: 1573214

URL: http://svn.apache.org/r1573214
Log:
Extracted NodeModel interface from InMemoryNodeModel.

This is a generic interface allowing hierarchical configuration objects to
interact with arbitrary hierarchical nodes structures.

Added:
    commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/tree/NodeModel.java
Modified:
    commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/tree/ImmutableNode.java
    commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/tree/InMemoryNodeModel.java
    commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/tree/ModelTransaction.java
    commons/proper/configuration/branches/immutableNodes/src/test/java/org/apache/commons/configuration/tree/TestInMemoryNodeModel.java

Modified: commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/tree/ImmutableNode.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/tree/ImmutableNode.java?rev=1573214&r1=1573213&r2=1573214&view=diff
==============================================================================
--- commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/tree/ImmutableNode.java (original)
+++ commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/tree/ImmutableNode.java Sat Mar  1 20:06:24 2014
@@ -438,10 +438,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)
             {
@@ -593,11 +594,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/branches/immutableNodes/src/main/java/org/apache/commons/configuration/tree/InMemoryNodeModel.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/tree/InMemoryNodeModel.java?rev=1573214&r1=1573213&r2=1573214&view=diff
==============================================================================
--- commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/tree/InMemoryNodeModel.java (original)
+++ commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/tree/InMemoryNodeModel.java Sat Mar  1 20:06:24 2014
@@ -34,11 +34,23 @@ import org.apache.commons.lang3.StringUt
  * A specialized node model implementation which operates on
  * {@link ImmutableNode} structures.
  * </p>
+ * <p>
+ * This {@code NodeModel} implementation keeps all its data as a tree of
+ * {@link ImmutableNode} objects in memory. The managed structure can be
+ * manipulated in a thread-safe, non-blocking way. This is achieved by using
+ * atomic variables: The root of the tree is stored in an atomic reference
+ * variable. Each update operation causes a new structure to be constructed
+ * (which reuses as much from the original structure as possible). The old root
+ * node is then replaced by the new one using an atomic compare-and-set
+ * operation. If this fails, the manipulation has to be done anew on the updated
+ * structure.
+ * </p>
  *
  * @version $Id$
  * @since 2.0
  */
-public class InMemoryNodeModel implements NodeHandler<ImmutableNode>
+public class InMemoryNodeModel implements NodeHandler<ImmutableNode>,
+        NodeModel<ImmutableNode>
 {
     /** Stores information about the current nodes structure. */
     private final AtomicReference<TreeData> structure;
@@ -66,21 +78,15 @@ public class InMemoryNodeModel implement
                         createTreeData(initialRootNode(root)));
     }
 
-    /**
-     * Returns the root node of this model.
-     *
-     * @return the root node
-     */
     public ImmutableNode getRootNode()
     {
         return getTreeData().getRoot();
     }
 
     /**
-     * Returns a {@code NodeHandler} for dealing with the nodes managed by this
-     * model.
-     *
-     * @return the {@code NodeHandler}
+     * {@inheritDoc} {@code InMemoryNodeModel} implements the
+     * {@code NodeHandler} interface itself. So this implementation just returns
+     * the <strong>this</strong> reference.
      */
     public NodeHandler<ImmutableNode> getNodeHandler()
     {
@@ -181,15 +187,6 @@ public class InMemoryNodeModel implement
         return checkIfNodeDefined(node);
     }
 
-    /**
-     * Adds a new property to this node model consisting of an arbitrary number
-     * of values. The key for the add operation is provided. For each value a
-     * new node has to be added.
-     *
-     * @param key the key
-     * @param values the values to be added at the position defined by the key
-     * @param resolver the {@code NodeKeyResolver}
-     */
     public void addProperty(final String key, final Iterable<?> values,
             final NodeKeyResolver resolver)
     {
@@ -204,20 +201,8 @@ public class InMemoryNodeModel implement
         }
     }
 
-    /**
-     * Adds a collection of new nodes to this model. This operation corresponds
-     * to the {@code addNodes()} method of the {@code Configuration} interface.
-     * The new nodes are either added to an existing node (if the passed in key
-     * selects exactly one node) or to a newly created node.
-     *
-     * @param key the key
-     * @param nodes the collection of nodes to be added (may be <b>null</b>)
-     * @param resolver the {@code NodeKeyResolver}
-     * @throws IllegalArgumentException if the key references an attribute (of
-     *         course, it is not possible to add something to an attribute)
-     */
     public void addNodes(final String key,
-            final Collection<ImmutableNode> nodes,
+            final Collection<? extends ImmutableNode> nodes,
             final NodeKeyResolver resolver)
     {
         if (nodes != null && !nodes.isEmpty())
@@ -257,19 +242,6 @@ public class InMemoryNodeModel implement
         }
     }
 
-    /**
-     * Changes the value of a property. This is a more complex operation as it
-     * might involve adding, updating, or deleting nodes and attributes from the
-     * model. The object representing the new value is passed to the
-     * {@code NodeKeyResolver} which will produce a corresponding
-     * {@link NodeUpdateData} object. Based on the content of this object,
-     * update operations are performed.
-     *
-     * @param key the key
-     * @param value the new value for this property (to be evaluated by the
-     *        {@code NodeKeyResolver})
-     * @param resolver the {@code NodeKeyResolver}
-     */
     public void setProperty(final String key, final Object value,
             final NodeKeyResolver resolver)
     {
@@ -300,12 +272,9 @@ public class InMemoryNodeModel implement
     }
 
     /**
-     * Removes the sub trees defined by the given key from this model. All nodes
-     * selected by this key are retrieved and removed from the model. If this
-     * causes other nodes to become undefined, they are removed, too.
-     *
-     * @param key the key selecting the properties to be removed
-     * @param resolver the {@code NodeKeyResolver}
+     * {@inheritDoc} This implementation checks whether nodes become undefined
+     * after subtrees have been removed. If this is the case, such nodes are
+     * removed, too.
      */
     public void clearTree(final String key, final NodeKeyResolver resolver)
     {
@@ -342,14 +311,8 @@ public class InMemoryNodeModel implement
     }
 
     /**
-     * Clears the value of a property. This method is similar to
-     * {@link #clearTree(String, NodeKeyResolver)}: However, the nodes
-     * referenced by the passed in key are not removed completely, but only
-     * their value is set to <b>null</b>. (If this operation leaves the affected
-     * node in an undefined state, it is indeed removed.)
-     *
-     * @param key the key selecting the properties to be cleared
-     * @param resolver the {@code NodeKeyResolver}
+     * {@inheritDoc} If this operation leaves an affected node in an undefined
+     * state, it is removed from the model.
      */
     public void clearProperty(final String key, final NodeKeyResolver resolver)
     {
@@ -365,7 +328,7 @@ public class InMemoryNodeModel implement
     }
 
     /**
-     * Removes all data from this model. A new empty root node is created with
+     * {@inheritDoc} A new empty root node is created with
      * the same name as the current root node. Implementation note: Because this
      * is a hard reset the usual dance for dealing with concurrent updates is
      * not required here.
@@ -381,16 +344,14 @@ public class InMemoryNodeModel implement
     }
 
     /**
-     * Sets a new root node for this model. The whole structure is replaced by
-     * the new node and its children. Care has to be taken when this method is
-     * used and the model is accessed by multiple threads. It is not
-     * deterministic which concurrent operations see the old root and which see
-     * the new root node.
+     * {@inheritDoc} Care has to be taken when this method is used and the model
+     * is accessed by multiple threads. It is not deterministic which concurrent
+     * operations see the old root and which see the new root node.
      *
      * @param newRoot the new root node to be set (can be <b>null</b>, then an
      *        empty root node is set)
      */
-    public void setRoot(ImmutableNode newRoot)
+    public void setRootNode(ImmutableNode newRoot)
     {
         structure.set(createTreeData(initialRootNode(newRoot)));
     }

Modified: commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/tree/ModelTransaction.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/tree/ModelTransaction.java?rev=1573214&r1=1573213&r2=1573214&view=diff
==============================================================================
--- commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/tree/ModelTransaction.java (original)
+++ commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/tree/ModelTransaction.java Sat Mar  1 20:06:24 2014
@@ -131,7 +131,7 @@ class ModelTransaction
      * @param newNodes the collection of new child nodes
      */
     public void addAddNodesOperation(ImmutableNode parent,
-            Collection<ImmutableNode> newNodes)
+            Collection<? extends ImmutableNode> newNodes)
     {
         ChildrenUpdateOperation op = new ChildrenUpdateOperation();
         op.addNewNodes(newNodes);
@@ -586,7 +586,7 @@ class ModelTransaction
          *
          * @param nodes the collection with new nodes
          */
-        public void addNewNodes(Collection<ImmutableNode> nodes)
+        public void addNewNodes(Collection<? extends ImmutableNode> nodes)
         {
             newNodes = concatenate(newNodes, nodes);
         }

Added: commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/tree/NodeModel.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/tree/NodeModel.java?rev=1573214&view=auto
==============================================================================
--- commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/tree/NodeModel.java (added)
+++ commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/tree/NodeModel.java Sat Mar  1 20:06:24 2014
@@ -0,0 +1,140 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.configuration.tree;
+
+import java.util.Collection;
+
+/**
+ * <p>
+ * Definition of an interface describing a model based on a nodes structure.
+ * </p>
+ * <p>
+ * This interface can be used for dealing with hierarchical, tree-like data. It
+ * defines basic operations for manipulating the tree structure which use keys
+ * to select the nodes affected.
+ * </p>
+ * <p>
+ * The idea behind this interface is that concrete implementations can be used
+ * by hierarchical configurations. This makes it possible to integrate various
+ * hierarchical structures with the API of a hierarchical configuration, e.g.
+ * configuration nodes stored in memory, JNDI contexts, or other structures. The
+ * configuration object interacts with the underlying data structure via this
+ * interface. For more complex operations access to an {@link ExpressionEngine}
+ * may be required in order to interpret the passed in keys. For these purposes
+ * a {@link NodeKeyResolver} has to be provided which knows how to deal with
+ * keys.
+ * </p>
+ *
+ * @version $Id$
+ * @since 2.0
+ * @param <T> the type of the nodes managed by this model
+ */
+public interface NodeModel<T>
+{
+    /**
+     * Returns the root node of this model.
+     *
+     * @return the root node
+     */
+    T getRootNode();
+
+    /**
+     * Sets a new root node for this model. The whole structure is replaced by
+     * the new node and its children.
+     *
+     * @param newRoot the new root node to be set (can be <b>null</b>, then an
+     *        empty root node is set)
+     */
+    void setRootNode(T newRoot);
+
+    /**
+     * Returns a {@code NodeHandler} for dealing with the nodes managed by this
+     * model.
+     *
+     * @return the {@code NodeHandler}
+     */
+    NodeHandler<T> getNodeHandler();
+
+    /**
+     * Adds a new property to this node model consisting of an arbitrary number
+     * of values. The key for the add operation is provided. For each value a
+     * new node has to be added. The passed in resolver is queried for a
+     * {@link NodeAddData} object defining the add operation to be performed.
+     *
+     * @param key the key
+     * @param values the values to be added at the position defined by the key
+     * @param resolver the {@code NodeKeyResolver}
+     */
+    void addProperty(String key, Iterable<?> values, NodeKeyResolver resolver);
+
+    /**
+     * Adds a collection of new nodes to this model. This operation corresponds
+     * to the {@code addNodes()} method of the {@code HierarchicalConfiguration}
+     * interface. The new nodes are either added to an existing node (if the
+     * passed in key selects exactly one node) or to a newly created node. The
+     * passed in {@code NodeKeyResolver} is used to interpret the given key.
+     *
+     * @param key the key
+     * @param nodes the collection of nodes to be added (may be <b>null</b>)
+     * @param resolver the {@code NodeKeyResolver}
+     * @throws IllegalArgumentException if the key references an attribute (of
+     *         course, it is not possible to add something to an attribute)
+     */
+    void addNodes(String key, Collection<? extends T> nodes,
+            NodeKeyResolver resolver);
+
+    /**
+     * Changes the value of a property. This is a more complex operation as it
+     * might involve adding, updating, or deleting nodes and attributes from the
+     * model. The object representing the new value is passed to the
+     * {@code NodeKeyResolver} which will produce a corresponding
+     * {@link NodeUpdateData} object. Based on the content of this object,
+     * update operations are performed.
+     *
+     * @param key the key
+     * @param value the new value for this property (to be evaluated by the
+     *        {@code NodeKeyResolver})
+     * @param resolver the {@code NodeKeyResolver}
+     */
+    void setProperty(String key, Object value, NodeKeyResolver resolver);
+
+    /**
+     * Removes the sub trees defined by the given key from this model. All nodes
+     * selected by this key are retrieved from the specified
+     * {@code NodeKeyResolver} and removed from the model.
+     *
+     * @param key the key selecting the properties to be removed
+     * @param resolver the {@code NodeKeyResolver}
+     */
+    void clearTree(String key, NodeKeyResolver resolver);
+
+    /**
+     * Clears the value of a property. This method is similar to
+     * {@link #clearTree(String, NodeKeyResolver)}: However, the nodes
+     * referenced by the passed in key are not removed completely, but only
+     * their value is set to <b>null</b>.
+     *
+     * @param key the key selecting the properties to be cleared
+     * @param resolver the {@code NodeKeyResolver}
+     */
+    void clearProperty(String key, NodeKeyResolver resolver);
+
+    /**
+     * Removes all data from this model.
+     */
+    void clear();
+}

Modified: commons/proper/configuration/branches/immutableNodes/src/test/java/org/apache/commons/configuration/tree/TestInMemoryNodeModel.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/immutableNodes/src/test/java/org/apache/commons/configuration/tree/TestInMemoryNodeModel.java?rev=1573214&r1=1573213&r2=1573214&view=diff
==============================================================================
--- commons/proper/configuration/branches/immutableNodes/src/test/java/org/apache/commons/configuration/tree/TestInMemoryNodeModel.java (original)
+++ commons/proper/configuration/branches/immutableNodes/src/test/java/org/apache/commons/configuration/tree/TestInMemoryNodeModel.java Sat Mar  1 20:06:24 2014
@@ -1233,7 +1233,7 @@ public class TestInMemoryNodeModel
     {
         InMemoryNodeModel model =
                 new InMemoryNodeModel(NodeStructureHelper.ROOT_PERSONAE_TREE);
-        model.setRoot(NodeStructureHelper.ROOT_AUTHORS_TREE);
+        model.setRootNode(NodeStructureHelper.ROOT_AUTHORS_TREE);
         assertSame("Root node not changed",
                 NodeStructureHelper.ROOT_AUTHORS_TREE, model.getRootNode());
         ImmutableNode node = nodeForKey(model, "Homer/Ilias");
@@ -1249,7 +1249,7 @@ public class TestInMemoryNodeModel
     {
         InMemoryNodeModel model =
                 new InMemoryNodeModel(NodeStructureHelper.ROOT_PERSONAE_TREE);
-        model.setRoot(null);
+        model.setRootNode(null);
         ImmutableNode rootNode = model.getRootNode();
         assertTrue("Got children", rootNode.getChildren().isEmpty());
     }