Author: oheger
Date: Fri Nov 6 21:11:24 2009
New Revision: 833557
URL:
http://svn.apache.org/viewvc?rev=833557&view=revLog:
Added a copy constructor to InMemoryConfigurationSource.
Modified:
commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/base/InMemoryConfigurationSource.java
commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/ConfigurationAssert.java
commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/base/TestInMemoryConfigurationSource.java
Modified: commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/base/InMemoryConfigurationSource.java
URL:
http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/base/InMemoryConfigurationSource.java?rev=833557&r1=833556&r2=833557&view=diff==============================================================================
--- commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/base/InMemoryConfigurationSource.java (original)
+++ commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/base/InMemoryConfigurationSource.java Fri Nov 6 21:11:24 2009
@@ -16,8 +16,11 @@
*/
package org.apache.commons.configuration2.base;
+import java.util.Stack;
+
import org.apache.commons.configuration2.expr.ConfigurationNodeHandler;
import org.apache.commons.configuration2.expr.NodeHandler;
+import org.apache.commons.configuration2.expr.NodeVisitorAdapter;
import org.apache.commons.configuration2.tree.ConfigurationNode;
import org.apache.commons.configuration2.tree.DefaultConfigurationNode;
@@ -58,6 +61,31 @@
}
/**
+ * Creates a new instance of {@code InMemoryConfigurationSource} and
+ * initializes it with the data stored in the specified {@code
+ * HierarchicalConfigurationSource}. From the nodes in the specified source
+ * a deep copy is created. So the node structure of the newly created source
+ * exactly corresponds to the one of the original source, but they are
+ * independent of each other. The passed in {@code
+ * HierarchicalConfigurationSource} can be <b>null</b>, then this
+ * constructor behaves like the default constructor.
+ *
+ * @param c the {@code HierarchicalConfigurationSource} to be copied
+ */
+ public InMemoryConfigurationSource(
+ HierarchicalConfigurationSource<? extends ConfigurationNode> c)
+ {
+ this();
+ if (c != null)
+ {
+ CloneVisitor visitor = new CloneVisitor();
+ NodeVisitorAdapter
+ .visit(visitor, c.getRootNode(), getNodeHandler());
+ setRootNode(visitor.getClone());
+ }
+ }
+
+ /**
* Returns a reference to the root node.
*
* @return the root configuration node
@@ -103,4 +131,77 @@
{
return NODE_HANDLER;
}
+
+ /**
+ * A specialized visitor that is able to create a deep copy of a node
+ * hierarchy.
+ */
+ private static class CloneVisitor extends
+ NodeVisitorAdapter<ConfigurationNode>
+ {
+ /** A stack with the actual object to be copied. */
+ private Stack<ConfigurationNode> copyStack;
+
+ /** Stores the result of the clone process. */
+ private ConfigurationNode result;
+
+ /**
+ * Creates a new instance of {@code CloneVisitor}.
+ */
+ public CloneVisitor()
+ {
+ copyStack = new Stack<ConfigurationNode>();
+ }
+
+ /**
+ * Visits the specified node after its children have been processed.
+ *
+ * @param node the node
+ */
+ @Override
+ public void visitAfterChildren(ConfigurationNode node,
+ NodeHandler<ConfigurationNode> handler)
+ {
+ ConfigurationNode copy = copyStack.pop();
+ if (copyStack.isEmpty())
+ {
+ result = copy;
+ }
+ }
+
+ /**
+ * Visits and copies the specified node.
+ *
+ * @param node the node
+ */
+ @Override
+ public void visitBeforeChildren(ConfigurationNode node,
+ NodeHandler<ConfigurationNode> handler)
+ {
+ ConfigurationNode copy = (ConfigurationNode) node.clone();
+ copy.setParentNode(null);
+
+ for (ConfigurationNode attr : node.getAttributes())
+ {
+ copy.addAttribute((ConfigurationNode) attr.clone());
+ }
+ if (!copyStack.isEmpty())
+ {
+ copyStack.peek().addChild(copy);
+ }
+
+ copyStack.push(copy);
+ }
+
+ /**
+ * Returns the result of the clone process. This is the root node of the
+ * cloned node hierarchy.
+ *
+ * @return the cloned root node
+ */
+ public ConfigurationNode getClone()
+ {
+ return result;
+ }
+ }
}
Modified: commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/ConfigurationAssert.java
URL:
http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/ConfigurationAssert.java?rev=833557&r1=833556&r2=833557&view=diff==============================================================================
--- commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/ConfigurationAssert.java (original)
+++ commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/ConfigurationAssert.java Fri Nov 6 21:11:24 2009
@@ -24,6 +24,9 @@
import junit.framework.Assert;
+import org.apache.commons.configuration2.base.ConfigurationImpl;
+import org.apache.commons.configuration2.base.HierarchicalConfigurationSource;
+
/**
* Assertions on configurations for the unit tests.
*
@@ -69,6 +72,57 @@
}
/**
+ * Compares two configurations with each other.
+ *
+ * @param <T> the type of the configuration nodes
+ * @param expected the expected configuration
+ * @param actual the configuration to check
+ */
+ public static <T> void assertEquals(
+ org.apache.commons.configuration2.base.Configuration<T> expected,
+ org.apache.commons.configuration2.base.Configuration<T> actual)
+ {
+ // check that the actual configuration contains all the properties of
+ // the expected configuration
+ for (Iterator<String> it = expected.getKeys(); it.hasNext();)
+ {
+ String key = it.next();
+ Assert.assertTrue(
+ "The actual configuration doesn't contain the expected key '"
+ + key + "'", actual.containsKey(key));
+ Assert.assertEquals("Value of the '" + key + "' property", expected
+ .getProperty(key), actual.getProperty(key));
+ }
+
+ // check that the actual configuration has no extra properties
+ for (Iterator<String> it = actual.getKeys(); it.hasNext();)
+ {
+ String key = it.next();
+ Assert.assertTrue(
+ "The actual configuration contains an extra key '" + key
+ + "'", expected.containsKey(key));
+ }
+ }
+
+ /**
+ * Compares the content of two hierarchical configuration sources.
+ *
+ * @param <T> the type of the nodes used within the sources
+ * @param expected the expected configuration source
+ * @param actual the configuration source to check
+ */
+ public static <T> void assertEquals(
+ HierarchicalConfigurationSource<T> expected,
+ HierarchicalConfigurationSource<T> actual)
+ {
+ org.apache.commons.configuration2.base.Configuration<T> expectedConfig = new ConfigurationImpl<T>(
+ expected);
+ org.apache.commons.configuration2.base.Configuration<T> actualConfig = new ConfigurationImpl<T>(
+ actual);
+ assertEquals(expectedConfig, actualConfig);
+ }
+
+ /**
* Returns a <code>File</code> object for the specified test file.
*
* @param name the name of the test file
Modified: commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/base/TestInMemoryConfigurationSource.java
URL:
http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/base/TestInMemoryConfigurationSource.java?rev=833557&r1=833556&r2=833557&view=diff==============================================================================
--- commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/base/TestInMemoryConfigurationSource.java (original)
+++ commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/base/TestInMemoryConfigurationSource.java Fri Nov 6 21:11:24 2009
@@ -21,6 +21,9 @@
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
+import java.util.Arrays;
+
+import org.apache.commons.configuration2.ConfigurationAssert;
import org.apache.commons.configuration2.expr.ConfigurationNodeHandler;
import org.apache.commons.configuration2.tree.ConfigurationNode;
import org.apache.commons.configuration2.tree.DefaultConfigurationNode;
@@ -62,6 +65,22 @@
}
/**
+ * Adds some test properties to the configuration source to be tested.
+ */
+ private void populate()
+ {
+ Configuration<ConfigurationNode> config = new ConfigurationImpl<ConfigurationNode>(source);
+ config.addProperty("test", Boolean.TRUE);
+ config.addProperty("test.list", Arrays.asList("value1", "value2", "value3"));
+ config.addProperty("test[@mode]", "full");
+ config.addProperty("answer", 42);
+ config.addProperty("database.connection", "jdbc:test:local:db");
+ config.addProperty("database.usr", "scott");
+ config.addProperty("database.pwd", "tiger");
+ config.addProperty("[@rootAttr]", "set");
+ }
+
+ /**
* Tests a newly created instance.
*/
@Test
@@ -114,4 +133,28 @@
assertTrue("Wrong node handler",
source.getNodeHandler() instanceof ConfigurationNodeHandler);
}
+
+ /**
+ * Tests the constructor which copies another configuration source.
+ */
+ @Test
+ public void testInitCopy()
+ {
+ populate();
+ InMemoryConfigurationSource src2 = new InMemoryConfigurationSource(
+ source);
+ ConfigurationAssert.assertEquals(source, src2);
+ }
+
+ /**
+ * Tests the copy constructor if null is passed in.
+ */
+ @Test
+ public void testInitCopyNull()
+ {
+ InMemoryConfigurationSource src2 = new InMemoryConfigurationSource(null);
+ Configuration<ConfigurationNode> conf = new ConfigurationImpl<ConfigurationNode>(
+ src2);
+ assertTrue("Not empty", conf.isEmpty());
+ }
}