You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by oh...@apache.org on 2004/12/18 17:33:03 UTC
cvs commit: jakarta-commons/configuration/src/test/org/apache/commons/configuration TestHierarchicalXMLConfiguration.java
oheger 2004/12/18 08:33:03
Modified: configuration/src/java/org/apache/commons/configuration
HierarchicalXMLConfiguration.java
HierarchicalConfiguration.java
configuration/src/test/org/apache/commons/configuration
TestHierarchicalXMLConfiguration.java
Log:
Made HierarchicalXMLConfiguration fully compatible with XMLConfiguration: fixed an issue with attribute handling, implemented the auto save feature, added the constructors for file based configurations.
Revision Changes Path
1.8 +160 -43 jakarta-commons/configuration/src/java/org/apache/commons/configuration/HierarchicalXMLConfiguration.java
Index: HierarchicalXMLConfiguration.java
===================================================================
RCS file: /home/cvs/jakarta-commons/configuration/src/java/org/apache/commons/configuration/HierarchicalXMLConfiguration.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- HierarchicalXMLConfiguration.java 13 Dec 2004 16:40:13 -0000 1.7
+++ HierarchicalXMLConfiguration.java 18 Dec 2004 16:33:03 -0000 1.8
@@ -25,6 +25,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
+import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
@@ -63,13 +64,15 @@
* @author <a href="mailto:oliver.heger@t-online.de">Oliver Heger </a>
* @version $Revision$, $Date$
*/
-public class HierarchicalXMLConfiguration extends HierarchicalConfiguration implements
- FileConfiguration
+public class HierarchicalXMLConfiguration extends HierarchicalConfiguration implements FileConfiguration
{
/** Constant for the default root element name. */
private static final String DEFAULT_ROOT_NAME = "configuration";
- private FileConfiguration delegate = new FileConfigurationDelegate();
+ /** Delimiter character for attributes. */
+ private static char ATTR_DELIMITER = ',';
+
+ private FileConfigurationDelegate delegate = new FileConfigurationDelegate();
/** The document from this configuration's data source. */
private Document document;
@@ -78,6 +81,59 @@
private String rootElementName;
/**
+ * Creates a new instance of <code>HierarchicalXMLConfiguration</code>.
+ */
+ public HierarchicalXMLConfiguration()
+ {
+ super();
+ }
+
+ /**
+ * Creates a new instance of <code>HierarchicalXMLConfiguration</code>.
+ * The configuration is loaded from the specified file
+ *
+ * @param fileName the name of the file to load
+ * @throws ConfigurationException if the file cannot be loaded
+ */
+ public HierarchicalXMLConfiguration(String fileName) throws ConfigurationException
+ {
+ this();
+ setFileName(fileName);
+ load();
+ }
+
+ /**
+ * Creates a new instance of <code>HierarchicalXMLConfiguration</code>.
+ * The configuration is loaded from the specified file.
+ *
+ * @param file the file
+ * @throws ConfigurationException if an error occurs while loading the file
+ */
+ public HierarchicalXMLConfiguration(File file) throws ConfigurationException
+ {
+ this();
+ setFile(file);
+ if (file.exists())
+ {
+ load();
+ }
+ }
+
+ /**
+ * Creates a new instance of <code>HierarchicalXMLConfiguration</code>.
+ * The configuration is loaded from the specified URL.
+ *
+ * @param url the URL
+ * @throws ConfigurationException if loading causes an error
+ */
+ public HierarchicalXMLConfiguration(URL url) throws ConfigurationException
+ {
+ this();
+ setURL(url);
+ load();
+ }
+
+ /**
* Returns the name of the root element.
*
* @return the name of the root element
@@ -89,8 +145,8 @@
/**
* Sets the name of the root element. This name is used when this
- * configuration object is stored in an XML file. Note that setting the
- * name of the root element works only if this configuration has been newly
+ * configuration object is stored in an XML file. Note that setting the name
+ * of the root element works only if this configuration has been newly
* created. If the configuration was loaded from an XML file, the name
* cannot be changed.
*
@@ -102,6 +158,33 @@
}
/**
+ * @inheritDoc
+ */
+ protected void addPropertyDirect(String key, Object obj)
+ {
+ super.addPropertyDirect(key, obj);
+ delegate.possiblySave();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public void clearProperty(String key)
+ {
+ super.clearProperty(key);
+ delegate.possiblySave();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public void setProperty(String key, Object value)
+ {
+ super.setProperty(key, value);
+ delegate.possiblySave();
+ }
+
+ /**
* Initializes this configuration from an XML document.
*
* @param document the document to be parsed
@@ -120,6 +203,7 @@
*/
private void constructHierarchy(Node node, Element element)
{
+ processAttributes(node, element);
StringBuffer buffer = new StringBuffer();
NodeList list = element.getChildNodes();
for (int i = 0; i < list.getLength(); i++)
@@ -131,7 +215,6 @@
Node childNode = new XMLNode(child.getTagName(), child);
constructHierarchy(childNode, child);
node.addChild(childNode);
- processAttributes(childNode, child);
}
else if (w3cNode instanceof Text)
{
@@ -162,10 +245,12 @@
if (w3cNode instanceof Attr)
{
Attr attr = (Attr) w3cNode;
- Node child = new XMLNode(ConfigurationKey.constructAttributeKey(attr.getName()),
- element);
- child.setValue(attr.getValue());
- node.addChild(child);
+ for (Iterator it = PropertyConverter.split(attr.getValue(), ATTR_DELIMITER).iterator(); it.hasNext();)
+ {
+ Node child = new XMLNode(ConfigurationKey.constructAttributeKey(attr.getName()), element);
+ child.setValue(it.next());
+ node.addChild(child);
+ }
}
}
}
@@ -423,7 +508,7 @@
{
if (ConfigurationKey.isAttributeKey(getName()))
{
- updateAttribute(value);
+ updateAttribute();
}
else
{
@@ -442,7 +527,7 @@
Element element = (Element) getReference();
if (ConfigurationKey.isAttributeKey(getName()))
{
- element.removeAttribute(ConfigurationKey.removeAttributeMarkers(getName()));
+ updateAttribute();
}
else
{
@@ -478,8 +563,7 @@
txtNode = document.createTextNode(value.toString());
if (((Element) getReference()).getFirstChild() != null)
{
- ((Element) getReference()).insertBefore(txtNode, ((Element) getReference())
- .getFirstChild());
+ ((Element) getReference()).insertBefore(txtNode, ((Element) getReference()).getFirstChild());
}
else
{
@@ -495,21 +579,11 @@
/**
* Updates the node's value if it represents an attribute.
- *
- * @param value the new value
+ *
*/
- private void updateAttribute(Object value)
+ private void updateAttribute()
{
- Element elem = (Element) getReference();
- if (value == null)
- {
- elem.removeAttribute(ConfigurationKey.removeAttributeMarkers(getName()));
- }
- else
- {
- elem.setAttribute(ConfigurationKey.removeAttributeMarkers(getName()), value
- .toString());
- }
+ XMLBuilderVisitor.updateAttribute(getParent(), getName());
}
/**
@@ -595,17 +669,8 @@
{
if (ConfigurationKey.isAttributeKey(newNode.getName()))
{
- if (newNode.getValue() != null)
- {
- getElement(parent).setAttribute(
- ConfigurationKey.removeAttributeMarkers(newNode.getName()),
- newNode.getValue().toString());
- return getElement(parent);
- }
- else
- {
- return null;
- }
+ updateAttribute(parent, getElement(parent), newNode.getName());
+ return null;
}
else
@@ -632,6 +697,61 @@
}
/**
+ * Helper method for updating the value of the specified node's
+ * attribute with the given name.
+ *
+ * @param node the affected node
+ * @param elem the element that is associated with this node
+ * @param name the name of the affected attribute
+ */
+ private static void updateAttribute(Node node, Element elem, String name)
+ {
+ if (node != null && elem != null)
+ {
+ List attrs = node.getChildren(name);
+ StringBuffer buf = new StringBuffer();
+ for (Iterator it = attrs.iterator(); it.hasNext();)
+ {
+ Node attr = (Node) it.next();
+ if (attr.getValue() != null)
+ {
+ if (buf.length() > 0)
+ {
+ buf.append(ATTR_DELIMITER);
+ }
+ buf.append(attr.getValue());
+ }
+ attr.setReference(elem);
+ }
+
+ if (buf.length() < 1)
+ {
+ elem.removeAttribute(ConfigurationKey.removeAttributeMarkers(name));
+ }
+ else
+ {
+ elem.setAttribute(ConfigurationKey.removeAttributeMarkers(name), buf.toString());
+ }
+ }
+ }
+
+ /**
+ * Updates the value of the specified attribute of the given node.
+ * Because there can be multiple child nodes representing this attribute
+ * the new value is determined by iterating over all those child nodes.
+ *
+ * @param node the affected node
+ * @param name the name of the attribute
+ */
+ static void updateAttribute(Node node, String name)
+ {
+ if (node != null)
+ {
+ updateAttribute(node, (Element) node.getReference(), name);
+ }
+ }
+
+ /**
* Helper method for accessing the element of the specified node.
*
* @param node the node
@@ -640,14 +760,12 @@
private Element getElement(Node node)
{
// special treatement for root node of the hierarchy
- return (node.getName() != null) ? (Element) node.getReference() : document
- .getDocumentElement();
+ return (node.getName() != null) ? (Element) node.getReference() : document.getDocumentElement();
}
}
private class FileConfigurationDelegate extends AbstractFileConfiguration
{
-
public void load(Reader in) throws ConfigurationException
{
HierarchicalXMLConfiguration.this.load(in);
@@ -657,6 +775,5 @@
{
HierarchicalXMLConfiguration.this.save(out);
}
-
}
}
1.17 +18 -16 jakarta-commons/configuration/src/java/org/apache/commons/configuration/HierarchicalConfiguration.java
Index: HierarchicalConfiguration.java
===================================================================
RCS file: /home/cvs/jakarta-commons/configuration/src/java/org/apache/commons/configuration/HierarchicalConfiguration.java,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -r1.16 -r1.17
--- HierarchicalConfiguration.java 14 Dec 2004 17:03:50 -0000 1.16
+++ HierarchicalConfiguration.java 18 Dec 2004 16:33:03 -0000 1.17
@@ -496,8 +496,7 @@
* @param node the actual node
* @param data here the found nodes are stored
*/
- protected void findPropertyNodes(ConfigurationKey.KeyIterator keyPart, Node node,
- Collection data)
+ protected void findPropertyNodes(ConfigurationKey.KeyIterator keyPart, Node node, Collection data)
{
if (!keyPart.hasNext())
{
@@ -511,16 +510,15 @@
{
if (keyPart.getIndex() < children.size() && keyPart.getIndex() >= 0)
{
- findPropertyNodes((ConfigurationKey.KeyIterator) keyPart.clone(),
- (Node) children.get(keyPart.getIndex()), data);
+ findPropertyNodes((ConfigurationKey.KeyIterator) keyPart.clone(), (Node) children.get(keyPart
+ .getIndex()), data);
}
}
else
{
for (Iterator it = children.iterator(); it.hasNext();)
{
- findPropertyNodes((ConfigurationKey.KeyIterator) keyPart.clone(), (Node) it
- .next(), data);
+ findPropertyNodes((ConfigurationKey.KeyIterator) keyPart.clone(), (Node) it.next(), data);
}
}
}
@@ -685,9 +683,10 @@
/** Stores the children of this node. */
private LinkedMap children; // Explict type here or we
- // will get a findbugs error
- // because Map doesn't imply
- // Serializable
+
+ // will get a findbugs error
+ // because Map doesn't imply
+ // Serializable
/**
* Creates a new instance of <code>Node</code>.
@@ -930,11 +929,12 @@
{
if (children != null)
{
- for (Iterator it = children.values().iterator(); it.hasNext();)
+ Iterator it = children.values().iterator();
+ children = null;
+ while (it.hasNext())
{
nodesRemoved((Collection) it.next());
}
- children = null;
}
}
@@ -965,8 +965,7 @@
if (children != null)
{
- for (Iterator it = children.values().iterator(); it.hasNext()
- && !visitor.terminate();)
+ for (Iterator it = children.values().iterator(); it.hasNext() && !visitor.terminate();)
{
Collection col = (Collection) it.next();
for (Iterator it2 = col.iterator(); it2.hasNext() && !visitor.terminate();)
@@ -1325,10 +1324,13 @@
for (Iterator it = newNodes.iterator(); it.hasNext();)
{
Node insertNode = (Node) it.next();
- Object ref = insert(insertNode, node, sibling1, sibling2);
- if (ref != null)
+ if (insertNode.getReference() == null)
{
- insertNode.setReference(ref);
+ Object ref = insert(insertNode, node, sibling1, sibling2);
+ if (ref != null)
+ {
+ insertNode.setReference(ref);
+ }
}
}
}
1.5 +6 -2 jakarta-commons/configuration/src/test/org/apache/commons/configuration/TestHierarchicalXMLConfiguration.java
Index: TestHierarchicalXMLConfiguration.java
===================================================================
RCS file: /home/cvs/jakarta-commons/configuration/src/test/org/apache/commons/configuration/TestHierarchicalXMLConfiguration.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- TestHierarchicalXMLConfiguration.java 13 Dec 2004 16:40:14 -0000 1.4
+++ TestHierarchicalXMLConfiguration.java 18 Dec 2004 16:33:03 -0000 1.5
@@ -53,7 +53,7 @@
private static final String TEST_SAVENAME = "testhierarchicalsave.xml";
/** File path for saving.*/
- private static final String TEST_SAVE = TEST_DIR + File.separator + TEST_SAVENAME;
+ private static final String TEST_SAVE = "target" + File.separator + TEST_SAVENAME;
/** Instance config used for tests. */
private HierarchicalXMLConfiguration config;
@@ -247,6 +247,8 @@
config.addProperty("list(1).sublist.item", "seven");
config.setProperty("clear", "yes");
config.setProperty("mean", "now it's simple");
+ config.addProperty("[@topattr]", "available");
+ config.addProperty("[@topattr]", "successfull");
removeTestSaveFile();
try
@@ -264,6 +266,8 @@
assertEquals("seven", config.getProperty("list(1).sublist.item(2)"));
assertEquals("yes", config.getProperty("clear"));
assertEquals("now it's simple", config.getString("mean"));
+ assertEquals("available", config.getString("[@topattr](0)"));
+ assertEquals("successfull", config.getString("[@topattr](1)"));
}
finally
{
---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org