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/02/15 18:59:07 UTC
svn commit: r1568650 - 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 Feb 15 17:59:07 2014
New Revision: 1568650
URL: http://svn.apache.org/r1568650
Log:
InMemoryNodeModel now supports adding attribute properties.
ModelTransaction was extended by a special Operation class for adding
attributes.
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/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/InMemoryNodeModel.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/tree/InMemoryNodeModel.java?rev=1568650&r1=1568649&r2=1568650&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 Feb 15 17:59:07 2014
@@ -198,17 +198,13 @@ public class InMemoryNodeModel implement
ModelTransaction tx = new ModelTransaction(currentStructure);
NodeAddData<ImmutableNode> addData =
resolver.resolveAddKey(currentStructure.getRoot(), key, this);
- // TODO handle attributes
- Collection<ImmutableNode> newNodes =
- createNodesToAdd(addData.getNewNodeName(), values);
- if (addData.getPathNodes().isEmpty())
+ if (addData.isAttribute())
{
- tx.addAddNodesOperation(addData.getParent(), newNodes);
+ addAttributeProperty(tx, addData, values);
}
else
{
- ImmutableNode newChild = createNodeToAddWithPath(addData, newNodes);
- tx.addAddNodeOperation(addData.getParent(), newChild);
+ addNodeProperty(tx, addData, values);
}
// TODO handle concurrency
@@ -242,6 +238,63 @@ public class InMemoryNodeModel implement
}
/**
+ * Handles an add property operation if the property to be added is a node.
+ *
+ * @param tx the transaction
+ * @param addData the {@code NodeAddData}
+ * @param values the collection with node values
+ */
+ private static void addNodeProperty(ModelTransaction tx,
+ NodeAddData<ImmutableNode> addData, Iterable<?> values)
+ {
+ Collection<ImmutableNode> newNodes =
+ createNodesToAdd(addData.getNewNodeName(), values);
+ if (addData.getPathNodes().isEmpty())
+ {
+ tx.addAddNodesOperation(addData.getParent(), newNodes);
+ }
+ else
+ {
+ ImmutableNode newChild = createNodeToAddWithPath(addData, newNodes);
+ tx.addAddNodeOperation(addData.getParent(), newChild);
+ }
+ }
+
+ /**
+ * Handles an add property operation if the property to be added is an
+ * attribute.
+ *
+ * @param tx the transaction
+ * @param addData the {@code NodeAddData}
+ * @param values the collection with node values
+ */
+ private static void addAttributeProperty(ModelTransaction tx,
+ NodeAddData<ImmutableNode> addData, Iterable<?> values)
+ {
+ if (addData.getPathNodes().isEmpty())
+ {
+ tx.addAttributeOperation(addData.getParent(),
+ addData.getNewNodeName(), values.iterator().next());
+ }
+ else
+ {
+ int pathNodeCount = addData.getPathNodes().size();
+ ImmutableNode childWithAttribute =
+ new ImmutableNode.Builder()
+ .name(addData.getPathNodes().get(pathNodeCount - 1))
+ .addAttribute(addData.getNewNodeName(),
+ values.iterator().next()).create();
+ ImmutableNode newChild =
+ (pathNodeCount > 1) ? createNodeOnPath(addData
+ .getPathNodes().subList(0, pathNodeCount - 1)
+ .iterator(),
+ Collections.singleton(childWithAttribute))
+ : childWithAttribute;
+ tx.addAddNodeOperation(addData.getParent(), newChild);
+ }
+ }
+
+ /**
* Creates a collection with new nodes with a given name and a value from a
* given collection.
*
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=1568650&r1=1568649&r2=1568650&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 Feb 15 17:59:07 2014
@@ -132,6 +132,20 @@ class ModelTransaction
}
/**
+ * Adds an operation for adding an attribute to a target node.
+ *
+ * @param target the target node
+ * @param name the name of the attribute
+ * @param value the value of the attribute
+ */
+ public void addAttributeOperation(ImmutableNode target, String name,
+ Object value)
+ {
+ fetchOperations(target, LEVEL_UNKNOWN).addOperation(
+ new AddAttributeOperation(name, value));
+ }
+
+ /**
* Executes this transaction resulting in a new {@code TreeData} object. The
* object returned by this method serves as the definition of a new node
* structure for the calling model.
@@ -440,6 +454,37 @@ class ModelTransaction
}
/**
+ * A specialized operation class for adding an attribute to a target node.
+ */
+ private class AddAttributeOperation extends Operation
+ {
+ /** The attribute name. */
+ private final String attributeName;
+
+ /** The attribute value. */
+ private final Object attributeValue;
+
+ /**
+ * Creates a new instance of {@code AddAttributeOperation}.
+ *
+ * @param name the name of the attribute
+ * @param value the value of the attribute
+ */
+ public AddAttributeOperation(String name, Object value)
+ {
+ attributeName = name;
+ attributeValue = value;
+ }
+
+ @Override
+ protected ImmutableNode apply(ImmutableNode target,
+ Operations operations)
+ {
+ return target.setAttribute(attributeName, attributeValue);
+ }
+ }
+
+ /**
* A helper class which collects multiple update operations to be executed
* on a single node.
*/
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=1568650&r1=1568649&r2=1568650&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 Feb 15 17:59:07 2014
@@ -672,4 +672,70 @@ public class TestInMemoryNodeModel
assertSame("Wrong root node", model.getRootNode(),
model.getParent(node));
}
+
+ /**
+ * Tests whether an attribute can be added if there are some path nodes.
+ */
+ @Test
+ public void testAddPropertyAttributeWithPathNodes()
+ {
+ NodeKeyResolver resolver = EasyMock.createMock(NodeKeyResolver.class);
+ NodeAddData<ImmutableNode> addData =
+ new NodeAddData<ImmutableNode>(nodeForKey(rootAuthorsTree,
+ "Homer/Ilias"), "number", true, Arrays.asList("scenes",
+ "scene"));
+ InMemoryNodeModel model = new InMemoryNodeModel(rootAuthorsTree);
+ EasyMock.expect(resolver.resolveAddKey(rootAuthorsTree, KEY, model))
+ .andReturn(addData);
+ EasyMock.replay(resolver);
+
+ model.addProperty(KEY, Collections.singleton(1), resolver);
+ ImmutableNode node = nodeForKey(model, "Homer/Ilias/scenes/scene");
+ assertEquals("Attribute not set", 1, node.getAttributes().get("number"));
+ }
+
+ /**
+ * Tests the special case that an attribute is added with a single path
+ * node.
+ */
+ @Test
+ public void testAddPropertyAttributeWithSinglePathNode()
+ {
+ NodeKeyResolver resolver = EasyMock.createMock(NodeKeyResolver.class);
+ NodeAddData<ImmutableNode> addData =
+ new NodeAddData<ImmutableNode>(nodeForKey(rootAuthorsTree,
+ AUTHORS[0]), "year", true, Arrays.asList("dateOfBirth"));
+ InMemoryNodeModel model = new InMemoryNodeModel(rootAuthorsTree);
+ EasyMock.expect(resolver.resolveAddKey(rootAuthorsTree, KEY, model))
+ .andReturn(addData);
+ EasyMock.replay(resolver);
+
+ final Integer year = 1564;
+ model.addProperty(KEY, Collections.singleton(year), resolver);
+ ImmutableNode node = nodeForKey(model, "Shakespeare/dateOfBirth");
+ assertEquals("Attribute not set", year, node.getAttributes()
+ .get("year"));
+ }
+
+ /**
+ * Tests whether an attribute property can be added if there are no path
+ * nodes.
+ */
+ @Test
+ public void testAddPropertyAttributeNoPathNodes()
+ {
+ NodeKeyResolver resolver = EasyMock.createMock(NodeKeyResolver.class);
+ NodeAddData<ImmutableNode> addData =
+ new NodeAddData<ImmutableNode>(nodeForKey(rootAuthorsTree,
+ "Shakespeare/The Tempest"), "year", true, null);
+ InMemoryNodeModel model = new InMemoryNodeModel(rootAuthorsTree);
+ EasyMock.expect(resolver.resolveAddKey(rootAuthorsTree, KEY, model))
+ .andReturn(addData);
+ EasyMock.replay(resolver);
+
+ model.addProperty(KEY, Collections.singleton(1611), resolver);
+ ImmutableNode node = nodeForKey(model, "Shakespeare/The Tempest");
+ assertEquals("Attribute not set", 1611, node.getAttributes()
+ .get("year"));
+ }
}