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/13 18:01:21 UTC
svn commit: r1587015 - in
/commons/proper/configuration/branches/immutableNodes/src:
main/java/org/apache/commons/configuration/CombinedConfiguration.java
test/java/org/apache/commons/configuration/TestCombinedConfiguration.java
Author: oheger
Date: Sun Apr 13 16:01:21 2014
New Revision: 1587015
URL: http://svn.apache.org/r1587015
Log:
Reworked CombinedConfiguration to operate on immutable nodes.
The majority of tests is working, but there are still some test failures.
Modified:
commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/CombinedConfiguration.java
commons/proper/configuration/branches/immutableNodes/src/test/java/org/apache/commons/configuration/TestCombinedConfiguration.java
Modified: commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/CombinedConfiguration.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/CombinedConfiguration.java?rev=1587015&r1=1587014&r2=1587015&view=diff
==============================================================================
--- commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/CombinedConfiguration.java (original)
+++ commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/CombinedConfiguration.java Sun Apr 13 16:01:21 2014
@@ -33,13 +33,11 @@ import org.apache.commons.configuration.
import org.apache.commons.configuration.sync.LockMode;
import org.apache.commons.configuration.tree.ConfigurationNode;
import org.apache.commons.configuration.tree.DefaultConfigurationKey;
-import org.apache.commons.configuration.tree.DefaultConfigurationNode;
import org.apache.commons.configuration.tree.DefaultExpressionEngine;
import org.apache.commons.configuration.tree.ExpressionEngine;
+import org.apache.commons.configuration.tree.ImmutableNode;
import org.apache.commons.configuration.tree.NodeCombiner;
-import org.apache.commons.configuration.tree.TreeUtils;
import org.apache.commons.configuration.tree.UnionCombiner;
-import org.apache.commons.configuration.tree.ViewNode;
/**
* <p>
@@ -172,9 +170,6 @@ import org.apache.commons.configuration.
* configuration itself). However, this is not enforced.
* </p>
*
- * @author <a
- * href="http://commons.apache.org/configuration/team-list.html">Commons
- * Configuration team</a>
* @since 1.3
* @version $Id$
*/
@@ -198,12 +193,13 @@ public class CombinedConfiguration exten
/** Constant for the default node combiner. */
private static final NodeCombiner DEFAULT_COMBINER = new UnionCombiner();
+ /** Constant for a root node for an empty configuration. */
+ private static final ImmutableNode EMPTY_ROOT = new ImmutableNode.Builder()
+ .create();
+
/** Stores the combiner. */
private NodeCombiner nodeCombiner;
- /** Stores the combined root node. */
- private ConfigurationNode combinedRoot;
-
/** Stores a list with the contained configurations. */
private List<ConfigData> configurations;
@@ -216,6 +212,9 @@ public class CombinedConfiguration exten
*/
private ExpressionEngine conversionExpressionEngine;
+ /** A flag whether this configuration is up-to-date. */
+ private boolean upToDate;
+
/**
* Creates a new instance of {@code CombinedConfiguration} and
* initializes the combiner to be used.
@@ -644,22 +643,6 @@ public class CombinedConfiguration exten
}
/**
- * Returns the configuration root node of this combined configuration. When
- * starting a read or write operation (by obtaining a corresponding lock for
- * this configuration) a combined node structure is constructed if necessary
- * using the current node combiner. This method just returns this combined
- * node. Note that this method should only be called with a lock held!
- * Otherwise, result may be <b>null</b> under certain circumstances.
- *
- * @return the combined root node
- */
- @Override
- public ConfigurationNode getRootNode()
- {
- return combinedRoot;
- }
-
- /**
* Clears this configuration. All contained configurations will be removed.
*/
@Override
@@ -692,7 +675,6 @@ public class CombinedConfiguration exten
.getConfiguration()), cd.getName(), cd.getAt());
}
- copy.setRootNode(new DefaultConfigurationNode());
return copy;
}
finally
@@ -734,25 +716,27 @@ public class CombinedConfiguration exten
beginRead(false);
try
{
- List<ConfigurationNode> nodes = fetchNodeList(key);
- if (nodes.isEmpty())
- {
- return null;
- }
-
- Iterator<ConfigurationNode> it = nodes.iterator();
- Configuration source = findSourceConfiguration(it.next());
- while (it.hasNext())
- {
- Configuration src = findSourceConfiguration(it.next());
- if (src != source)
- {
- throw new IllegalArgumentException("The key " + key
- + " is defined by multiple sources!");
- }
- }
-
- return source;
+// List<ConfigurationNode> nodes = fetchNodeList(key);
+// if (nodes.isEmpty())
+// {
+// return null;
+// }
+//
+// Iterator<ConfigurationNode> it = nodes.iterator();
+// Configuration source = findSourceConfiguration(it.next());
+// while (it.hasNext())
+// {
+// Configuration src = findSourceConfiguration(it.next());
+// if (src != source)
+// {
+// throw new IllegalArgumentException("The key " + key
+// + " is defined by multiple sources!");
+// }
+// }
+//
+// return source;
+ //TODO implementation
+ return null;
}
finally
{
@@ -777,8 +761,8 @@ public class CombinedConfiguration exten
boolean lockObtained = false;
do
{
- super.beginRead(optimize);
- if (combinedRoot != null)
+ super.beginRead(false);
+ if (isUpToDate())
{
lockObtained = true;
}
@@ -808,9 +792,11 @@ public class CombinedConfiguration exten
try
{
- if (combinedRoot == null)
+ if (!isUpToDate())
{
- combinedRoot = constructCombinedNode();
+ getSubConfigurationParentModel().replaceRoot(
+ constructCombinedNode(), this);
+ upToDate = true;
}
}
catch (RuntimeException rex)
@@ -821,6 +807,18 @@ public class CombinedConfiguration exten
}
/**
+ * Returns a flag whether this configuration has been invalidated. This
+ * means that the combined nodes structure has to be rebuilt before the
+ * configuration can be accessed.
+ *
+ * @return a flag whether this configuration is invalid
+ */
+ private boolean isUpToDate()
+ {
+ return upToDate;
+ }
+
+ /**
* Marks this configuration as invalid. This means that the next access
* re-creates the root node. An invalidate event is also fired. Note:
* This implementation expects that an exclusive (write) lock is held on
@@ -828,7 +826,7 @@ public class CombinedConfiguration exten
*/
private void invalidateInternal()
{
- combinedRoot = null;
+ upToDate = false;
fireEvent(EVENT_COMBINED_INVALIDATE, null, null, false);
}
@@ -847,7 +845,7 @@ public class CombinedConfiguration exten
*
* @return the combined root node
*/
- private ConfigurationNode constructCombinedNode()
+ private ImmutableNode constructCombinedNode()
{
if (getNumberOfConfigurationsInternal() < 1)
{
@@ -855,13 +853,13 @@ public class CombinedConfiguration exten
{
getLogger().debug("No configurations defined for " + this);
}
- return new ViewNode();
+ return EMPTY_ROOT;
}
else
{
Iterator<ConfigData> it = configurations.iterator();
- ConfigurationNode node = it.next().getTransformedRoot();
+ ImmutableNode node = it.next().getTransformedRoot();
while (it.hasNext())
{
node = nodeCombiner.combine(node,
@@ -871,7 +869,8 @@ public class CombinedConfiguration exten
{
ByteArrayOutputStream os = new ByteArrayOutputStream();
PrintStream stream = new PrintStream(os);
- TreeUtils.printTree(stream, node);
+ //TODO rework TreeUtils
+ //TreeUtils.printTree(stream, node);
getLogger().debug(os.toString());
}
return node;
@@ -967,7 +966,7 @@ public class CombinedConfiguration exten
private final String at;
/** Stores the root node for this child configuration.*/
- private ConfigurationNode rootNode;
+ private ImmutableNode rootNode;
/**
* Creates a new instance of {@code ConfigData} and initializes
@@ -1021,7 +1020,7 @@ public class CombinedConfiguration exten
* @return the root node of this child configuration
* @since 1.5
*/
- public ConfigurationNode getRootNode()
+ public ImmutableNode getRootNode()
{
return rootNode;
}
@@ -1033,41 +1032,83 @@ public class CombinedConfiguration exten
*
* @return the transformed root node
*/
- public ConfigurationNode getTransformedRoot()
+ public ImmutableNode getTransformedRoot()
{
- ViewNode result = new ViewNode();
- ViewNode atParent = result;
+ ImmutableNode configRoot = getRootNodeOfConfiguration();
+ return (atPath == null) ? configRoot : prependAtPath(configRoot);
+ }
- if (atPath != null)
+ /**
+ * Prepends the at path to the given node.
+ *
+ * @param node the root node of the represented configuration
+ * @return the new root node including the at path
+ */
+ private ImmutableNode prependAtPath(ImmutableNode node)
+ {
+ ImmutableNode.Builder pathBuilder = new ImmutableNode.Builder();
+ Iterator<String> pathIterator = atPath.iterator();
+ prependAtPathComponent(pathBuilder, pathIterator.next(),
+ pathIterator, node);
+ return new ImmutableNode.Builder(1).addChild(pathBuilder.create())
+ .create();
+ }
+
+ /**
+ * Handles a single component of the at path. A corresponding node is
+ * created and added to the hierarchical path to the original root node
+ * of the configuration.
+ *
+ * @param builder the current node builder object
+ * @param currentComponent the name of the current path component
+ * @param components an iterator with all components of the at path
+ * @param orgRoot the original root node of the wrapped configuration
+ */
+ private void prependAtPathComponent(ImmutableNode.Builder builder,
+ String currentComponent, Iterator<String> components,
+ ImmutableNode orgRoot)
+ {
+ builder.name(currentComponent);
+ if (components.hasNext())
+ {
+ ImmutableNode.Builder childBuilder =
+ new ImmutableNode.Builder();
+ prependAtPathComponent(childBuilder, components.next(),
+ components, orgRoot);
+ builder.addChild(childBuilder.create());
+ }
+ else
{
- // Build the complete path
- for (String p : atPath)
- {
- ViewNode node = new ViewNode();
- node.setName(p);
- atParent.addChild(node);
- atParent = node;
- }
+ builder.addChildren(orgRoot.getChildren());
+ builder.addAttributes(orgRoot.getAttributes());
+ builder.value(orgRoot.getValue());
}
+ }
- // Copy data of the root node to the new path
+ /**
+ * Obtains the root node of the wrapped configuration. If necessary, a
+ * hierarchical representation of the configuration has to be created
+ * first.
+ *
+ * @return the root node of the associated configuration
+ */
+ private ImmutableNode getRootNodeOfConfiguration()
+ {
getConfiguration().lock(LockMode.READ);
try
{
- ConfigurationNode root =
- ConfigurationUtils.convertToHierarchical(
- getConfiguration(), conversionExpressionEngine)
- .getRootNode();
- atParent.appendChildren(root);
- atParent.appendAttributes(root);
+ ImmutableNode root =
+ ConfigurationUtils
+ .convertToHierarchical(getConfiguration(),
+ conversionExpressionEngine).getModel()
+ .getInMemoryRepresentation();
rootNode = root;
+ return root;
}
finally
{
getConfiguration().unlock(LockMode.READ);
}
-
- return result;
}
/**
Modified: commons/proper/configuration/branches/immutableNodes/src/test/java/org/apache/commons/configuration/TestCombinedConfiguration.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/immutableNodes/src/test/java/org/apache/commons/configuration/TestCombinedConfiguration.java?rev=1587015&r1=1587014&r2=1587015&view=diff
==============================================================================
--- commons/proper/configuration/branches/immutableNodes/src/test/java/org/apache/commons/configuration/TestCombinedConfiguration.java (original)
+++ commons/proper/configuration/branches/immutableNodes/src/test/java/org/apache/commons/configuration/TestCombinedConfiguration.java Sun Apr 13 16:01:21 2014
@@ -45,10 +45,11 @@ import org.apache.commons.configuration.
import org.apache.commons.configuration.sync.LockMode;
import org.apache.commons.configuration.sync.ReadWriteSynchronizer;
import org.apache.commons.configuration.sync.Synchronizer;
-import org.apache.commons.configuration.tree.ConfigurationNode;
import org.apache.commons.configuration.tree.DefaultExpressionEngine;
import org.apache.commons.configuration.tree.DefaultExpressionEngineSymbols;
+import org.apache.commons.configuration.tree.ImmutableNode;
import org.apache.commons.configuration.tree.NodeCombiner;
+import org.apache.commons.configuration.tree.NodeModel;
import org.apache.commons.configuration.tree.OverrideCombiner;
import org.apache.commons.configuration.tree.UnionCombiner;
import org.junit.Before;
@@ -689,7 +690,7 @@ public class TestCombinedConfiguration
SynchronizerTestImpl sync = setUpSynchronizerTest();
config.addConfiguration(new BaseHierarchicalConfiguration());
sync.verify(Methods.BEGIN_WRITE, Methods.END_WRITE);
- assertNull("Root node not reset", config.getRootNode());
+ checkCombinedRootNotConstructed();
}
/**
@@ -713,7 +714,7 @@ public class TestCombinedConfiguration
SynchronizerTestImpl sync = setUpSynchronizerTest();
assertNotNull("No node combiner", config.getNodeCombiner());
sync.verify(Methods.BEGIN_READ, Methods.END_READ);
- assertNull("Root node was constructed", config.getRootNode());
+ checkCombinedRootNotConstructed();
}
/**
@@ -726,7 +727,7 @@ public class TestCombinedConfiguration
SynchronizerTestImpl sync = setUpSynchronizerTest();
assertNotNull("No configuration", config.getConfiguration(0));
sync.verify(Methods.BEGIN_READ, Methods.END_READ);
- assertNull("Root node was constructed", config.getRootNode());
+ checkCombinedRootNotConstructed();
}
/**
@@ -739,7 +740,7 @@ public class TestCombinedConfiguration
SynchronizerTestImpl sync = setUpSynchronizerTest();
assertNotNull("No configuration", config.getConfiguration(CHILD1));
sync.verify(Methods.BEGIN_READ, Methods.END_READ);
- assertNull("Root node was constructed", config.getRootNode());
+ checkCombinedRootNotConstructed();
}
/**
@@ -752,7 +753,7 @@ public class TestCombinedConfiguration
SynchronizerTestImpl sync = setUpSynchronizerTest();
assertFalse("No child names", config.getConfigurationNames().isEmpty());
sync.verify(Methods.BEGIN_READ, Methods.END_READ);
- assertNull("Root node was constructed", config.getRootNode());
+ checkCombinedRootNotConstructed();
}
/**
@@ -766,7 +767,17 @@ public class TestCombinedConfiguration
assertFalse("No child names", config.getConfigurationNameList()
.isEmpty());
sync.verify(Methods.BEGIN_READ, Methods.END_READ);
- assertNull("Root node was constructed", config.getRootNode());
+ checkCombinedRootNotConstructed();
+ }
+
+ /**
+ * Helper method for testing that the combined root node has not yet been
+ * constructed.
+ */
+ private void checkCombinedRootNotConstructed()
+ {
+ assertTrue("Root node was constructed", config.getRootNode()
+ .getChildren().isEmpty());
}
/**
@@ -779,7 +790,7 @@ public class TestCombinedConfiguration
assertFalse("No child configurations", config.getConfigurations()
.isEmpty());
sync.verify(Methods.BEGIN_READ, Methods.END_READ);
- assertNull("Root node was constructed", config.getRootNode());
+ checkCombinedRootNotConstructed();
}
/**
@@ -793,7 +804,7 @@ public class TestCombinedConfiguration
assertNull("Got a conversion engine",
config.getConversionExpressionEngine());
sync.verify(Methods.BEGIN_READ, Methods.END_READ);
- assertNull("Root node was constructed", config.getRootNode());
+ checkCombinedRootNotConstructed();
}
/**
@@ -807,7 +818,7 @@ public class TestCombinedConfiguration
config.setConversionExpressionEngine(new DefaultExpressionEngine(
DefaultExpressionEngineSymbols.DEFAULT_SYMBOLS));
sync.verify(Methods.BEGIN_WRITE, Methods.END_WRITE);
- assertNull("Root node was constructed", config.getRootNode());
+ checkCombinedRootNotConstructed();
}
/**
@@ -844,7 +855,7 @@ public class TestCombinedConfiguration
assertEquals("Wrong number of configurations", 2,
config.getNumberOfConfigurations());
sync.verify(Methods.BEGIN_READ, Methods.END_READ);
- assertNull("Root node was constructed", config.getRootNode());
+ checkCombinedRootNotConstructed();
}
/**
@@ -880,10 +891,9 @@ public class TestCombinedConfiguration
private static final long serialVersionUID = 1L;
@Override
- public ConfigurationNode getRootNode()
- {
+ public NodeModel<ImmutableNode> getModel() {
throw testEx;
- };
+ }
};
config.addConfiguration(childEx);
try