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/17 22:08:34 UTC
svn commit: r1578574 - in
/commons/proper/configuration/branches/immutableNodes/src:
main/java/org/apache/commons/configuration/tree/
test/java/org/apache/commons/configuration/tree/
Author: oheger
Date: Mon Mar 17 21:08:34 2014
New Revision: 1578574
URL: http://svn.apache.org/r1578574
Log:
Added a replaceTrackedNode() method to InMemoryNodeModel.
This method is useful when working on sub trees of the model. It is then
possible to detach a whole sub tree and to replace its root node.
Modified:
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/NodeTracker.java
commons/proper/configuration/branches/immutableNodes/src/test/java/org/apache/commons/configuration/tree/TestInMemoryNodeModelTrackedNodes.java
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=1578574&r1=1578573&r2=1578574&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 Mon Mar 17 21:08:34 2014
@@ -412,6 +412,38 @@ public class InMemoryNodeModel implement
}
/**
+ * Replaces a tracked node by another node. If the tracked node is not yet
+ * detached, it becomes now detached. The passed in node (which must not be
+ * <b>null</b>) becomes the new root node of an independent model for this
+ * tracked node. Further updates of this model do not affect the tracked
+ * node's model and vice versa.
+ *
+ * @param selector the {@code NodeSelector} defining the tracked node
+ * @param newNode the node replacing the tracked node (must not be
+ * <b>null</b>)
+ * @throws ConfigurationRuntimeException if the selector cannot be resolved
+ * @throws IllegalArgumentException if the replacement node is <b>null</b>
+ */
+ public void replaceTrackedNode(NodeSelector selector, ImmutableNode newNode)
+ {
+ if (newNode == null)
+ {
+ throw new IllegalArgumentException(
+ "Replacement node must not be null!");
+ }
+
+ boolean done;
+ do
+ {
+ TreeData currentData = structure.get();
+ done =
+ replaceDetachedTrackedNode(currentData, selector, newNode)
+ || replaceActiveTrackedNode(currentData, selector,
+ newNode);
+ } while (!done);
+ }
+
+ /**
* Returns a {@code NodeHandler} for a tracked node. Such a handler may be
* required for operations on a sub tree of the model. The handler to be
* returned depends on the current state of the tracked node. If it is still
@@ -886,6 +918,46 @@ public class InMemoryNodeModel implement
}
/**
+ * Replaces a tracked node if it is already detached.
+ *
+ * @param currentData the current data of the model
+ * @param selector the {@code NodeSelector} defining the tracked node
+ * @param newNode the node replacing the tracked node
+ * @return a flag whether the operation was successful
+ */
+ private boolean replaceDetachedTrackedNode(TreeData currentData,
+ NodeSelector selector, ImmutableNode newNode)
+ {
+ InMemoryNodeModel detachedNodeModel =
+ currentData.getNodeTracker().getDetachedNodeModel(selector);
+ if (detachedNodeModel != null)
+ {
+ detachedNodeModel.setRootNode(newNode);
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Replaces an active tracked node. The node then becomes detached.
+ *
+ * @param currentData the current data of the model
+ * @param selector the {@code NodeSelector} defining the tracked node
+ * @param newNode the node replacing the tracked node
+ * @return a flag whether the operation was successful
+ */
+ private boolean replaceActiveTrackedNode(TreeData currentData,
+ NodeSelector selector, ImmutableNode newNode)
+ {
+ NodeTracker newTracker =
+ currentData.getNodeTracker().replaceAndDetachTrackedNode(
+ selector, newNode);
+ return structure.compareAndSet(currentData,
+ currentData.updateNodeTracker(newTracker));
+ }
+
+ /**
* Checks whether the specified collection with values is not empty.
*
* @param values the collection with node values
Modified: commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/tree/NodeTracker.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/tree/NodeTracker.java?rev=1578574&r1=1578573&r2=1578574&view=diff
==============================================================================
--- commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/tree/NodeTracker.java (original)
+++ commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/tree/NodeTracker.java Mon Mar 17 21:08:34 2014
@@ -258,6 +258,24 @@ class NodeTracker
}
/**
+ * Replaces a tracked node by another one. This operation causes the tracked
+ * node to become detached.
+ *
+ * @param selector the {@code NodeSelector}
+ * @param newNode the replacement node
+ * @return the updated instance
+ * @throws ConfigurationRuntimeException if the selector cannot be resolved
+ */
+ public NodeTracker replaceAndDetachTrackedNode(NodeSelector selector,
+ ImmutableNode newNode)
+ {
+ Map<NodeSelector, TrackedNodeData> newState =
+ new HashMap<NodeSelector, TrackedNodeData>(trackedNodes);
+ newState.put(selector, getTrackedNodeData(selector).detach(newNode));
+ return new NodeTracker(newState);
+ }
+
+ /**
* Obtains the {@code TrackedNodeData} object for the specified selector. If
* the selector cannot be resolved, an exception is thrown.
*
Modified: commons/proper/configuration/branches/immutableNodes/src/test/java/org/apache/commons/configuration/tree/TestInMemoryNodeModelTrackedNodes.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/immutableNodes/src/test/java/org/apache/commons/configuration/tree/TestInMemoryNodeModelTrackedNodes.java?rev=1578574&r1=1578573&r2=1578574&view=diff
==============================================================================
--- commons/proper/configuration/branches/immutableNodes/src/test/java/org/apache/commons/configuration/tree/TestInMemoryNodeModelTrackedNodes.java (original)
+++ commons/proper/configuration/branches/immutableNodes/src/test/java/org/apache/commons/configuration/tree/TestInMemoryNodeModelTrackedNodes.java Mon Mar 17 21:08:34 2014
@@ -594,7 +594,7 @@ public class TestInMemoryNodeModelTracke
{
assertEquals("Wrong number of field nodes",
NodeStructureHelper.fieldsLength(1), nodeFields.getChildren()
- .size());
+ .size());
int childIndex = 0;
for (ImmutableNode field : nodeFields.getChildren())
{
@@ -693,4 +693,49 @@ public class TestInMemoryNodeModelTracke
assertTrue("Wrong handler: " + handler, handler instanceof TreeData);
assertNotSame("Shared handler", model.getNodeHandler(), handler);
}
+
+ /**
+ * Helper method for testing whether a tracked node can be replaced.
+ */
+ private void checkReplaceTrackedNode()
+ {
+ ImmutableNode newNode =
+ new ImmutableNode.Builder().name("newNode").create();
+ model.replaceTrackedNode(selector, newNode);
+ assertSame("Node not changed", newNode, model.getTrackedNode(selector));
+ assertTrue("Node not detached", model.isTrackedNodeDetached(selector));
+ }
+
+ /**
+ * Tests whether an active tracked node can be replaced.
+ */
+ @Test
+ public void testReplaceTrackedNodeForActiveTrackedNode()
+ {
+ NodeKeyResolver<ImmutableNode> resolver = createResolver();
+ model.trackNode(selector, resolver);
+ checkReplaceTrackedNode();
+ }
+
+ /**
+ * Tests whether a detached tracked node can be replaced.
+ */
+ @Test
+ public void testReplaceTrackedNodeForDetachedNode()
+ {
+ NodeKeyResolver<ImmutableNode> resolver = createResolver();
+ model.trackNode(selector, resolver);
+ initDetachedNode(resolver);
+ checkReplaceTrackedNode();
+ }
+
+ /**
+ * Tries to replace a tracked node with a null node.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testReplaceTrackedNodeNull()
+ {
+ model.trackNode(selector, createResolver());
+ model.replaceTrackedNode(selector, null);
+ }
}