org.apache.commons.configuration
Class HierarchicalConfiguration

java.lang.Object
  |
  +--org.apache.commons.configuration.AbstractConfiguration
        |
        +--org.apache.commons.configuration.HierarchicalConfiguration
All Implemented Interfaces:
Cloneable, Configuration, Serializable
Direct Known Subclasses:
AbstractHierarchicalFileConfiguration

public class HierarchicalConfiguration
extends AbstractConfiguration
implements Serializable, Cloneable

A specialized configuration class that extends its base class by the ability of keeping more structure in the stored properties.

There are some sources of configuration data that cannot be stored very well in a BaseConfiguration object because then their structure is lost. This is especially true for XML documents. This class can deal with such structured configuration sources by storing the properties in a tree-like organization.

The internal used storage form allows for a more sophisticated access to single properties. As an example consider the following XML document:

 <database>
   <tables>
     <table>
       <name>users</name>
       <fields>
         <field>
           <name>lid</name>
           <type>long</name>
         </field>
         <field>
           <name>usrName</name>
           <type>java.lang.String</type>
         </field>
        ...
       </fields>
     </table>
     <table>
       <name>documents</name>
       <fields>
         <field>
           <name>docid</name>
           <type>long</type>
         </field>
         ...
       </fields>
     </table>
     ...
   </tables>
 </database>
 

If this document is parsed and stored in a HierarchicalConfiguration object (which can be done by one of the sub classes), there are enhanced possibilities of accessing properties. The keys for querying information can contain indices that select a certain element if there are multiple hits.

For instance the key tables.table(0).name can be used to find out the name of the first table. In opposite tables.table.name would return a collection with the names of all available tables. Similarily the key tables.table(1).fields.field.name returns a collection with the names of all fields of the second table. If another index is added after the field element, a single field can be accessed: tables.table(1).fields.field(0).name.

There is a getMaxIndex() method that returns the maximum allowed index that can be added to a given property key. This method can be used to iterate over all values defined for a certain property.

Version:
$Id: HierarchicalConfiguration.java,v 1.14 2004/12/02 22:05:52 ebourg Exp $
Author:
Oliver Heger
See Also:
Serialized Form

Inner Class Summary
protected static class HierarchicalConfiguration.BuilderVisitor
          A specialized visitor base class that can be used for storing the tree of configuration nodes.
static class HierarchicalConfiguration.Node
          A data class for storing (hierarchical) property information.
static class HierarchicalConfiguration.NodeVisitor
          Definition of a visitor class for traversing a node and all of its children.This class defines the interface of a visitor for Node objects and provides a default implementation.
 
Fields inherited from class org.apache.commons.configuration.AbstractConfiguration
END_TOKEN, START_TOKEN
 
Constructor Summary
HierarchicalConfiguration()
           
 
Method Summary
 void addNodes(String key, Collection nodes)
          Adds a collection of nodes at the specified position of the configuration tree.
protected  void addPropertyDirect(String key, Object obj)
          Adds the property with the specified key.To be able to deal with the structure supported by this configuration implementation the passed in key is of importance, especially the indices it might contain.
protected  void clearNode(HierarchicalConfiguration.Node node)
          Clears the value of the specified node.
 void clearProperty(String key)
          Removes the property with the given key.
 void clearTree(String key)
          Removes all values of the property with the given name and of keys that start with this name.
 Object clone()
          Creates a copy of this object.
 boolean containsKey(String key)
          Checks if the specified key is contained in this configuration.
protected  HierarchicalConfiguration.Node createAddPath(ConfigurationKey.KeyIterator keyIt, HierarchicalConfiguration.Node root)
          Creates the missing nodes for adding a new property.
protected  HierarchicalConfiguration.Node createNode(String name)
          Creates a new Node object with the specified name.
protected  HierarchicalConfiguration.Node fetchAddNode(ConfigurationKey.KeyIterator keyIt, HierarchicalConfiguration.Node startNode)
          Returns a reference to the parent node of an add operation.
protected  List fetchNodeList(String key)
          Helper method for fetching a list of all nodes that are addressed by the specified key.
protected  HierarchicalConfiguration.Node findLastPathNode(ConfigurationKey.KeyIterator keyIt, HierarchicalConfiguration.Node node)
          Finds the last existing node for an add operation.
protected  void findPropertyNodes(ConfigurationKey.KeyIterator keyPart, HierarchicalConfiguration.Node node, Collection nodes)
          Recursive helper method for fetching a property.
 Iterator getKeys()
          Returns an iterator with all keys defined in this configuration.
 Iterator getKeys(String prefix)
          Returns an iterator with all keys defined in this configuration that start with the given prefix.
 int getMaxIndex(String key)
          Returns the maximum defined index for the given key.
 Object getProperty(String key)
          Fetches the specified property.
 HierarchicalConfiguration.Node getRoot()
          Returns the root node of this hierarchical configuration.
 boolean isEmpty()
          Checks if this configuration is empty.
protected  boolean nodeDefined(HierarchicalConfiguration.Node node)
          Checks if the specified node is defined.
protected  void removeNode(HierarchicalConfiguration.Node node)
          Removes the specified node from this configuration.
 void setProperty(String key, Object value)
          Sets the value of the specified property.
 void setRoot(HierarchicalConfiguration.Node node)
          Sets the root node of this hierarchical configuration.
 Configuration subset(String prefix)
          Creates a new Configuration object containing all keys that start with the specified prefix.
 
Methods inherited from class org.apache.commons.configuration.AbstractConfiguration
addProperty, clear, getBigDecimal, getBigDecimal, getBigInteger, getBigInteger, getBoolean, getBoolean, getBoolean, getByte, getByte, getByte, getDelimiter, getDouble, getDouble, getDouble, getFloat, getFloat, getFloat, getInt, getInt, getInteger, getList, getList, getLong, getLong, getLong, getProperties, getProperties, getShort, getShort, getShort, getString, getString, getStringArray, interpolate, interpolate, interpolateHelper, isThrowExceptionOnMissing, resolveContainerStore, setDelimiter, setThrowExceptionOnMissing
 
Methods inherited from class java.lang.Object
equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

HierarchicalConfiguration

public HierarchicalConfiguration()
Method Detail

getRoot

public HierarchicalConfiguration.Node getRoot()
Returns the root node of this hierarchical configuration.
Returns:
the root node

setRoot

public void setRoot(HierarchicalConfiguration.Node node)
Sets the root node of this hierarchical configuration.
Parameters:
node - the root node

getProperty

public Object getProperty(String key)
Fetches the specified property. Performs a recursive lookup in the tree with the configuration properties.
Parameters:
key - the key to be looked up
Returns:
the found value

addPropertyDirect

protected void addPropertyDirect(String key,
                                 Object obj)

Adds the property with the specified key.

To be able to deal with the structure supported by this configuration implementation the passed in key is of importance, especially the indices it might contain. The following example should clearify this: Suppose the actual configuration contains the following elements:

 tables
    +-- table
            +-- name = user
            +-- fields
                    +-- field
                            +-- name = uid
                    +-- field
                            +-- name = firstName
                    ...
    +-- table
            +-- name = documents
            +-- fields
                   ...
 

In this example a database structure is defined, e.g. all fields of the first table could be accessed using the key tables.table(0).fields.field.name. If now properties are to be added, it must be exactly specified at which position in the hierarchy the new property is to be inserted. So to add a new field name to a table it is not enough to say just

 config.addProperty("tables.table.fields.field.name", "newField");
 

The statement given above contains some ambiguity. For instance it is not clear, to which table the new field should be added. If this method finds such an ambiguity, it is resolved by following the last valid path. Here this would be the last table. The same is true for the field; because there are multiple fields and no explicit index is provided, a new name property would be added to the last field - which is propably not what was desired.

To make things clear explicit indices should be provided whenever possible. In the example above the exact table could be specified by providing an index for the table element as in tables.table(1).fields. By specifying an index it can also be expressed that at a given position in the configuration tree a new branch should be added. In the example above we did not want to add an additional name element to the last field of the table, but we want a complete new field element. This can be achieved by specifying an invalid index (like -1) after the element where a new branch should be created. Given this our example would run:

 config.addProperty("tables.table(1).fields.field(-1).name", "newField");
 

With this notation it is possible to add new branches everywhere. We could for instance create a new table element by specifying

 config.addProperty("tables.table(-1).fields.field.name", "newField2");
 

(Note that because after the table element a new branch is created indices in following elements are not relevant; the branch is new so there cannot be any ambiguities.)

Overrides:
addPropertyDirect in class AbstractConfiguration
Parameters:
key - the key of the new property
obj - the value of the new property

addNodes

public void addNodes(String key,
                     Collection nodes)
Adds a collection of nodes at the specified position of the configuration tree. This method works similar to addProperty(), but instead of a single property a whole collection of nodes can be added - and thus complete configuration sub trees. E.g. with this method it is possible to add parts of another HierarchicalConfiguration object to this object.
Parameters:
key - the key where the nodes are to be added; can be null , then they are added to the root node
nodes - a collection with the Node objects to be added

isEmpty

public boolean isEmpty()
Checks if this configuration is empty. Empty means that there are no keys with any values, though there can be some (empty) nodes.
Overrides:
isEmpty in class AbstractConfiguration
Returns:
a flag if this configuration is empty

subset

public Configuration subset(String prefix)
Creates a new Configuration object containing all keys that start with the specified prefix. This implementation will return a HierarchicalConfiguration object so that the structure of the keys will be saved.
Overrides:
subset in class AbstractConfiguration
Parameters:
prefix - the prefix of the keys for the subset
Returns:
a new configuration object representing the selected subset

containsKey

public boolean containsKey(String key)
Checks if the specified key is contained in this configuration. Note that for this configuration the term "contained" means that the key has an associated value. If there is a node for this key that has no value but children (either defined or undefined), this method will still return false .
Overrides:
containsKey in class AbstractConfiguration
Parameters:
key - the key to be chekced
Returns:
a flag if this key is contained in this configuration

setProperty

public void setProperty(String key,
                        Object value)
Sets the value of the specified property.
Overrides:
setProperty in class AbstractConfiguration
Parameters:
key - the key of the property to set
value - the new value of this property

clearTree

public void clearTree(String key)
Removes all values of the property with the given name and of keys that start with this name. So if there is a property with the key "foo" and a property with the key "foo.bar", a call of clearTree("foo") would remove both properties.
Parameters:
key - the key of the property to be removed

clearProperty

public void clearProperty(String key)
Removes the property with the given key. Properties with names that start with the given key (i.e. properties below the specified key in the hierarchy) won't be affected.
Overrides:
clearProperty in class AbstractConfiguration
Parameters:
key - the key of the property to be removed

getKeys

public Iterator getKeys()
Returns an iterator with all keys defined in this configuration. Note that the keys returned by this method will not contain any indices. This means that some structure will be lost.

Overrides:
getKeys in class AbstractConfiguration
Returns:
an iterator with the defined keys in this configuration

getKeys

public Iterator getKeys(String prefix)
Returns an iterator with all keys defined in this configuration that start with the given prefix. The returned keys will not contain any indices.
Overrides:
getKeys in class AbstractConfiguration
Parameters:
prefix - the prefix of the keys to start with
Returns:
an iterator with the found keys

getMaxIndex

public int getMaxIndex(String key)
Returns the maximum defined index for the given key. This is useful if there are multiple values for this key. They can then be addressed separately by specifying indices from 0 to the return value of this method.
Parameters:
key - the key to be checked
Returns:
the maximum defined index for this key

clone

public Object clone()
Creates a copy of this object. This new configuration object will contain copies of all nodes in the same structure.
Overrides:
clone in class Object
Returns:
the copy
Since:
1.2

fetchNodeList

protected List fetchNodeList(String key)
Helper method for fetching a list of all nodes that are addressed by the specified key.
Parameters:
key - the key
Returns:
a list with all affected nodes (never null )

findPropertyNodes

protected void findPropertyNodes(ConfigurationKey.KeyIterator keyPart,
                                 HierarchicalConfiguration.Node node,
                                 Collection nodes)
Recursive helper method for fetching a property. This method processes all facets of a configuration key, traverses the tree of properties and fetches the the nodes of all matching properties.
Parameters:
keyPart - the configuration key iterator
node - the actual node
nodes - here the found nodes are stored

nodeDefined

protected boolean nodeDefined(HierarchicalConfiguration.Node node)
Checks if the specified node is defined.
Parameters:
node - the node to be checked
Returns:
a flag if this node is defined

removeNode

protected void removeNode(HierarchicalConfiguration.Node node)
Removes the specified node from this configuration. This method ensures that parent nodes that become undefined by this operation are also removed.
Parameters:
node - the node to be removed

clearNode

protected void clearNode(HierarchicalConfiguration.Node node)
Clears the value of the specified node. If the node becomes undefined by this operation, it is removed from the hierarchy.
Parameters:
node - the node to be cleard

fetchAddNode

protected HierarchicalConfiguration.Node fetchAddNode(ConfigurationKey.KeyIterator keyIt,
                                                      HierarchicalConfiguration.Node startNode)
Returns a reference to the parent node of an add operation. Nodes for new properties can be added as children of this node. If the path for the specified key does not exist so far, it is created now.
Parameters:
keyIt - the iterator for the key of the new property
startNode - the node to start the search with
Returns:
the parent node for the add operation

findLastPathNode

protected HierarchicalConfiguration.Node findLastPathNode(ConfigurationKey.KeyIterator keyIt,
                                                          HierarchicalConfiguration.Node node)
Finds the last existing node for an add operation. This method traverses the configuration tree along the specified key. The last existing node on this path is returned.
Parameters:
keyIt - the key iterator
node - the actual node
Returns:
the last existing node on the given path

createAddPath

protected HierarchicalConfiguration.Node createAddPath(ConfigurationKey.KeyIterator keyIt,
                                                       HierarchicalConfiguration.Node root)
Creates the missing nodes for adding a new property. This method ensures that there are corresponding nodes for all components of the specified configuration key.
Parameters:
keyIt - the key iterator
root - the base node of the path to be created
Returns:
the last node of the path

createNode

protected HierarchicalConfiguration.Node createNode(String name)
Creates a new Node object with the specified name. This method can be overloaded in derived classes if a specific node type is needed. This base implementation always returns a new object of the Node class.
Parameters:
name - the name of the new node
Returns:
the new node


Copyright © 2001-2005 The Apache Software Foundation. All Rights Reserved.