/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.avalon.framework.configuration;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;

This is the default Configuration implementation.
Author:Avalon Development Team
Version:$Id: DefaultConfiguration.java 506231 2007-02-12 02:36:54Z crossley $
/** * This is the default <code>Configuration</code> implementation. * * @author <a href="mailto:dev@avalon.apache.org">Avalon Development Team</a> * @version $Id: DefaultConfiguration.java 506231 2007-02-12 02:36:54Z crossley $ */
public class DefaultConfiguration extends AbstractConfiguration implements MutableConfiguration, Serializable {
An empty (length zero) array of configuration objects.
/** * An empty (length zero) array of configuration objects. */
protected static final Configuration[] EMPTY_ARRAY = new Configuration[ 0 ]; private final String m_name; private final String m_location; private final String m_namespace; private final String m_prefix; private HashMap m_attributes; private ArrayList m_children; private String m_value; private boolean m_readOnly;
Copy constructor, to create a clone of another configuration. To modify children, use getChild(), removeChild() and addChild().
Params:
  • config – the Configuration to copy
  • deepCopy – true will cause clones of the children to be added, false will add the original instances and is thus faster.
Throws:
/** * Copy constructor, to create a clone of another configuration. * To modify children, use <code>getChild()</code>, * <code>removeChild()</code> and <code>addChild()</code>. * * @param config the <code>Configuration</code> to copy * @param deepCopy true will cause clones of the children to be added, * false will add the original instances and is thus * faster. * * @throws ConfigurationException if an error occurs when copying */
public DefaultConfiguration( Configuration config, boolean deepCopy ) throws ConfigurationException { this( config.getName(), config.getLocation(), config.getNamespace(), ( (config instanceof AbstractConfiguration) ? ((AbstractConfiguration)config).getPrefix() : "") ); addAll( config, deepCopy ); }
Shallow copy constructor, suitable for craeting a writable clone of a read-only configuration. To modify children, use getChild(), removeChild() and addChild().
Params:
  • config – the Configuration to copy
Throws:
/** * Shallow copy constructor, suitable for craeting a writable clone of * a read-only configuration. To modify children, use <code>getChild()</code>, * <code>removeChild()</code> and <code>addChild()</code>. * * @param config the <code>Configuration</code> to copy * @throws ConfigurationException if an error occurs when copying */
public DefaultConfiguration( Configuration config ) throws ConfigurationException { this( config, false ); }
Create a new DefaultConfiguration instance.
Params:
  • name – a String value
/** * Create a new <code>DefaultConfiguration</code> instance. * @param name a <code>String</code> value */
public DefaultConfiguration( final String name ) { this( name, null, "", "" ); }
Create a new DefaultConfiguration instance.
Params:
  • name – a String value
  • location – a String value
/** * Create a new <code>DefaultConfiguration</code> instance. * @param name a <code>String</code> value * @param location a <code>String</code> value */
public DefaultConfiguration( final String name, final String location ) { this( name, location, "", "" ); }
Create a new DefaultConfiguration instance.
Params:
  • name – config node name
  • location – Builder-specific locator string
  • ns – Namespace string (typically a URI). Should not be null; use "" if no namespace.
  • prefix – A short string prefixed to element names, associating elements with a longer namespace string. Should not be null; use "" if no namespace.
Since:4.1
/** * Create a new <code>DefaultConfiguration</code> instance. * @param name config node name * @param location Builder-specific locator string * @param ns Namespace string (typically a URI). Should not be null; use "" * if no namespace. * @param prefix A short string prefixed to element names, associating * elements with a longer namespace string. Should not be null; use "" if no * namespace. * @since 4.1 */
public DefaultConfiguration( final String name, final String location, final String ns, final String prefix ) { m_name = name; m_location = location; m_namespace = ns; m_prefix = prefix; // only used as a serialization hint. Cannot be null }
Returns the name of this configuration element.
Returns:a String value
/** * Returns the name of this configuration element. * @return a <code>String</code> value */
public String getName() { return m_name; }
Returns the namespace of this configuration element
Throws:
Returns:a String value
Since:4.1
/** * Returns the namespace of this configuration element * @return a <code>String</code> value * @throws ConfigurationException if an error occurs * @since 4.1 */
public String getNamespace() throws ConfigurationException { if( null != m_namespace ) { return m_namespace; } else { throw new ConfigurationException ( "No namespace (not even default \"\") is associated with the " + "configuration element \"" + getName() + "\" at " + getLocation() ); } }
Returns the prefix of the namespace
Throws:
Returns:a String value
Since:4.1
/** * Returns the prefix of the namespace * @return a <code>String</code> value * @throws ConfigurationException if prefix is not present (<code>null</code>). * @since 4.1 */
protected String getPrefix() throws ConfigurationException { if( null != m_prefix ) { return m_prefix; } else { throw new ConfigurationException ( "No prefix (not even default \"\") is associated with the " + "configuration element \"" + getName() + "\" at " + getLocation() ); } }
Returns a description of location of element.
Returns:a String value
/** * Returns a description of location of element. * @return a <code>String</code> value */
public String getLocation() { return m_location; }
Returns the value of the configuration element as a String.
Params:
  • defaultValue – the default value to return if value malformed or empty
Returns:a String value
/** * Returns the value of the configuration element as a <code>String</code>. * * @param defaultValue the default value to return if value malformed or empty * @return a <code>String</code> value */
public String getValue( final String defaultValue ) { if( null != m_value ) { return m_value; } else { return defaultValue; } }
Returns the value of the configuration element as a String.
Throws:
Returns:a String value
/** * Returns the value of the configuration element as a <code>String</code>. * * @return a <code>String</code> value * @throws ConfigurationException If the value is not present. */
public String getValue() throws ConfigurationException { if( null != m_value ) { return m_value; } else { throw new ConfigurationException( "No value is associated with the " + "configuration element \"" + getName() + "\" at " + getLocation() ); } }
Return an array of all attribute names.
Returns:a String[] value
/** * Return an array of all attribute names. * @return a <code>String[]</code> value */
public String[] getAttributeNames() { if( null == m_attributes ) { return new String[ 0 ]; } else { return (String[])m_attributes.keySet().toArray( new String[ 0 ] ); } }
Return an array of Configuration elements containing all node children.
Returns:The child nodes with name
/** * Return an array of <code>Configuration</code> * elements containing all node children. * * @return The child nodes with name */
public Configuration[] getChildren() { if( null == m_children ) { return new Configuration[ 0 ]; } else { return (Configuration[])m_children.toArray( new Configuration[ 0 ] ); } }
Returns the value of the attribute specified by its name as a String.
Params:
  • name – a String value
Throws:
Returns:a String value
/** * Returns the value of the attribute specified by its name as a * <code>String</code>. * * @param name a <code>String</code> value * @return a <code>String</code> value * @throws ConfigurationException If the attribute is not present. */
public String getAttribute( final String name ) throws ConfigurationException { final String value = ( null != m_attributes ) ? (String)m_attributes.get( name ) : null; if( null != value ) { return value; } else { throw new ConfigurationException( "No attribute named \"" + name + "\" is " + "associated with the configuration element \"" + getName() + "\" at " + getLocation() ); } }
Return the first Configuration object child of this associated with the given name.
Params:
  • name – a String value
  • createNew – a boolean value
Returns:a Configuration value
/** * Return the first <code>Configuration</code> object child of this * associated with the given name. * @param name a <code>String</code> value * @param createNew a <code>boolean</code> value * @return a <code>Configuration</code> value */
public Configuration getChild( final String name, final boolean createNew ) { if( null != m_children ) { final int size = m_children.size(); for( int i = 0; i < size; i++ ) { final Configuration configuration = (Configuration)m_children.get( i ); if( name.equals( configuration.getName() ) ) { return configuration; } } } if( createNew ) { return new DefaultConfiguration( name, "<generated>" + getLocation(), m_namespace, m_prefix ); } else { return null; } }
Return an array of Configuration objects children of this associated with the given name.
The returned array may be empty but is never null.
Params:
  • name – The name of the required children Configuration.
Returns:a Configuration[] value
/** * Return an array of <code>Configuration</code> objects * children of this associated with the given name. * <br> * The returned array may be empty but is never <code>null</code>. * * @param name The name of the required children <code>Configuration</code>. * @return a <code>Configuration[]</code> value */
public Configuration[] getChildren( final String name ) { if( null == m_children ) { return new Configuration[ 0 ]; } else { final ArrayList children = new ArrayList(); final int size = m_children.size(); for( int i = 0; i < size; i++ ) { final Configuration configuration = (Configuration)m_children.get( i ); if( name.equals( configuration.getName() ) ) { children.add( configuration ); } } return (Configuration[])children.toArray( new Configuration[ 0 ] ); } }
Append data to the value of this configuration element.
Params:
  • value – a String value
Deprecated:Use setValue() instead
/** * Append data to the value of this configuration element. * * @param value a <code>String</code> value * @deprecated Use setValue() instead */
public void appendValueData( final String value ) { checkWriteable(); if( null == m_value ) { m_value = value; } else { m_value += value; } }
Set the value of this Configuration object to the specified string.
Params:
  • value – a String value
/** * Set the value of this <code>Configuration</code> object to the specified string. * * @param value a <code>String</code> value */
public void setValue( final String value ) { checkWriteable(); m_value = value; }
Set the value of this Configuration object to the specified int.
Params:
  • value – a int value
/** * Set the value of this <code>Configuration</code> object to the specified int. * * @param value a <code>int</code> value */
public void setValue( final int value ) { setValue( String.valueOf( value ) ); }
Set the value of this Configuration object to the specified long.
Params:
  • value – a long value
/** * Set the value of this <code>Configuration</code> object to the specified long. * * @param value a <code>long</code> value */
public void setValue( final long value ) { setValue( String.valueOf( value ) ); }
Set the value of this Configuration object to the specified boolean.
Params:
  • value – a boolean value
/** * Set the value of this <code>Configuration</code> object to the specified boolean. * * @param value a <code>boolean</code> value */
public void setValue( final boolean value ) { setValue( String.valueOf( value ) ); }
Set the value of this Configuration object to the specified float.
Params:
  • value – a float value
/** * Set the value of this <code>Configuration</code> object to the specified float. * * @param value a <code>float</code> value */
public void setValue( final float value ) { setValue( String.valueOf( value ) ); }
Set the value of this Configuration object to the specified double.
Params:
  • value – a double value
/** * Set the value of this <code>Configuration</code> object to the specified double. * * @param value a <code>double</code> value */
public void setValue( final double value ) { setValue( String.valueOf( value ) ); }
Set the value of the specified attribute to the specified string.
Params:
  • name – name of the attribute to set
  • value – a String value
/** * Set the value of the specified attribute to the specified string. * * @param name name of the attribute to set * @param value a <code>String</code> value */
public void setAttribute( final String name, final String value ) { checkWriteable(); if( null != value ) { if( null == m_attributes ) { m_attributes = new HashMap(); } m_attributes.put( name, value ); } else { if( null != m_attributes ) { m_attributes.remove( name ); } } }
Set the value of the specified attribute to the specified int.
Params:
  • name – name of the attribute to set
  • value – an int value
/** * Set the value of the specified attribute to the specified int. * * @param name name of the attribute to set * @param value an <code>int</code> value */
public void setAttribute( final String name, final int value ) { setAttribute( name, String.valueOf( value ) ); }
Set the value of the specified attribute to the specified long.
Params:
  • name – name of the attribute to set
  • value – an long value
/** * Set the value of the specified attribute to the specified long. * * @param name name of the attribute to set * @param value an <code>long</code> value */
public void setAttribute( final String name, final long value ) { setAttribute( name, String.valueOf( value ) ); }
Set the value of the specified attribute to the specified boolean.
Params:
  • name – name of the attribute to set
  • value – an boolean value
/** * Set the value of the specified attribute to the specified boolean. * * @param name name of the attribute to set * @param value an <code>boolean</code> value */
public void setAttribute( final String name, final boolean value ) { setAttribute( name, String.valueOf( value ) ); }
Set the value of the specified attribute to the specified float.
Params:
  • name – name of the attribute to set
  • value – an float value
/** * Set the value of the specified attribute to the specified float. * * @param name name of the attribute to set * @param value an <code>float</code> value */
public void setAttribute( final String name, final float value ) { setAttribute( name, String.valueOf( value ) ); }
Set the value of the specified attribute to the specified double.
Params:
  • name – name of the attribute to set
  • value – an double value
/** * Set the value of the specified attribute to the specified double. * * @param name name of the attribute to set * @param value an <code>double</code> value */
public void setAttribute( final String name, final double value ) { setAttribute( name, String.valueOf( value ) ); }
Add an attribute to this configuration element, returning its old value or null.
Params:
  • name – a String value
  • value – a String value
Returns:a String value
Deprecated:Use setAttribute() instead
/** * Add an attribute to this configuration element, returning its old * value or <b>null</b>. * * @param name a <code>String</code> value * @param value a <code>String</code> value * @return a <code>String</code> value * @deprecated Use setAttribute() instead */
public String addAttribute( final String name, String value ) { checkWriteable(); if( null == m_attributes ) { m_attributes = new HashMap(); } return (String)m_attributes.put( name, value ); }
Add a child Configuration to this configuration element.
Params:
  • configuration – a Configuration value
/** * Add a child <code>Configuration</code> to this configuration element. * @param configuration a <code>Configuration</code> value */
public void addChild( final Configuration configuration ) { checkWriteable(); if( null == m_children ) { m_children = new ArrayList(); } m_children.add( configuration ); }
Add all the attributes, children and value from specified configuration element to current configuration element.
Params:
  • other – the Configuration element
  • deepCopy – true will cause clones of the children to be added, false will add the original instances and is thus faster. throws ConfigurationException If there are any problems cloning the children.
/** * Add all the attributes, children and value * from specified configuration element to current * configuration element. * * @param other the {@link Configuration} element * @param deepCopy true will cause clones of the children to be added, * false will add the original instances and is thus * faster. * * throws ConfigurationException If there are any problems cloning the * children. */
public void addAll( final Configuration other, final boolean deepCopy ) throws ConfigurationException { checkWriteable(); setValue( other.getValue( null ) ); addAllAttributes( other ); addAllChildren( other, deepCopy ); }
Add all the attributes, children and value from specified configuration element to current configuration element.
Params:
/** * Add all the attributes, children and value * from specified configuration element to current * configuration element. * * @param other the {@link Configuration} element */
public void addAll( final Configuration other ) { checkWriteable(); setValue( other.getValue( null ) ); addAllAttributes( other ); addAllChildren( other ); }
Add all attributes from specified configuration element to current configuration element.
Params:
/** * Add all attributes from specified configuration * element to current configuration element. * * @param other the {@link Configuration} element */
public void addAllAttributes( final Configuration other ) { checkWriteable(); final String[] attributes = other.getAttributeNames(); for( int i = 0; i < attributes.length; i++ ) { final String name = attributes[ i ]; final String value = other.getAttribute( name, null ); setAttribute( name, value ); } }
Add all child Configuration objects from specified configuration element to current configuration element.
Params:
  • deepCopy – true will cause clones of the children to be added, false will add the original instances and is thus faster.
  • other – the other Configuration value throws ConfigurationException If there are any problems cloning the children.
/** * Add all child <code>Configuration</code> objects from specified * configuration element to current configuration element. * * @param deepCopy true will cause clones of the children to be added, * false will add the original instances and is thus * faster. * * @param other the other {@link Configuration} value * * throws ConfigurationException If there are any problems cloning the * children. */
public void addAllChildren( final Configuration other, final boolean deepCopy ) throws ConfigurationException { checkWriteable(); final Configuration[] children = other.getChildren(); for( int i = 0; i < children.length; i++ ) { if ( deepCopy ) { addChild( new DefaultConfiguration( children[ i ], true ) ); } else { addChild( children[ i ] ); } } }
Add all child Configuration objects from specified configuration element to current configuration element.
Params:
/** * Add all child <code>Configuration</code> objects from specified * configuration element to current configuration element. * * @param other the other {@link Configuration} value */
public void addAllChildren( final Configuration other ) { checkWriteable(); final Configuration[] children = other.getChildren(); for( int i = 0; i < children.length; i++ ) { addChild( children[ i ] ); } }
Remove a child Configuration to this configuration element.
Params:
  • configuration – a Configuration value
/** * Remove a child <code>Configuration</code> to this configuration element. * @param configuration a <code>Configuration</code> value */
public void removeChild( final Configuration configuration ) { checkWriteable(); if( null == m_children ) { return; } m_children.remove( configuration ); }
Return count of children.
Returns:an int value
/** * Return count of children. * @return an <code>int</code> value */
public int getChildCount() { if( null == m_children ) { return 0; } return m_children.size(); }
Make this configuration read-only.
/** * Make this configuration read-only. * */
public void makeReadOnly() { m_readOnly = true; }
heck if this configuration is writeable.
Throws:
  • IllegalStateException – if this configuration s read-only
/** * heck if this configuration is writeable. * * @throws IllegalStateException if this configuration s read-only */
protected final void checkWriteable() throws IllegalStateException { if( m_readOnly ) { throw new IllegalStateException ( "Configuration is read only and can not be modified" ); } }
Returns true iff this DefaultConfiguration has been made read-only.
/** * Returns true iff this DefaultConfiguration has been made read-only. */
protected final boolean isReadOnly() { return m_readOnly; }
Convenience function to convert a child to a mutable configuration. If the child is-a MutableConfiguration, and it isn't a read-only DefaultConfiguration (which isn't really mutable), the child is cast to MutableConfiguration and returned. If not, the child is replaced in the m_children array with a new writable DefaultConfiguration that is a shallow copy of the child, and the new child is returned.
/** * Convenience function to convert a child to a mutable configuration. * If the child is-a MutableConfiguration, and it isn't a read-only DefaultConfiguration * (which isn't really mutable), the child is cast to MutableConfiguration and returned. * If not, the child is replaced in the m_children array with a new writable DefaultConfiguration * that is a shallow copy of the child, and the new child is returned. */
private MutableConfiguration toMutable( Configuration child ) throws ConfigurationException { if (child instanceof MutableConfiguration && !( child instanceof DefaultConfiguration && ((DefaultConfiguration) child).isReadOnly() )) { // Child is already mutable - return it. return (MutableConfiguration) child; } // Child isn't mutable. (This is a mutating operation, so let's check // if we're writable.) checkWriteable(); DefaultConfiguration config = new DefaultConfiguration( child ); // Replace the old child. for( int i = 0; i < m_children.size(); i++) { if( m_children.get(i) == child ) { m_children.set( i, config ); break; } } return config; } public MutableConfiguration getMutableChild( final String name ) throws ConfigurationException { return getMutableChild( name, true ); } public MutableConfiguration getMutableChild( final String name, boolean autoCreate ) throws ConfigurationException { Configuration child = getChild( name, false ); if( child == null ) { // No child. Create? if( autoCreate ) { DefaultConfiguration config = new DefaultConfiguration( name, "-" ); addChild( config ); return config; } else { return null; } } // Child exists return toMutable( child ); } public MutableConfiguration[] getMutableChildren() throws ConfigurationException { if( null == m_children ) { return new MutableConfiguration[ 0 ]; } else { final ArrayList children = new ArrayList(); final int size = m_children.size(); for( int i = 0; i < size; i++ ) { final Configuration configuration = (Configuration)m_children.get( i ); children.add( toMutable( configuration ) ); } return (MutableConfiguration[])children.toArray( new MutableConfiguration[ 0 ] ); } } public MutableConfiguration[] getMutableChildren( final String name ) throws ConfigurationException { if( null == m_children ) { return new MutableConfiguration[ 0 ]; } else { final ArrayList children = new ArrayList(); final int size = m_children.size(); for( int i = 0; i < size; i++ ) { final Configuration configuration = (Configuration)m_children.get( i ); if( name.equals( configuration.getName() ) ) { children.add( toMutable( configuration ) ); } } return (MutableConfiguration[])children.toArray( new MutableConfiguration[ 0 ] ); } }
Compare if this configuration is equal to another.
Params:
  • other – The other configuration
Returns:true if they are the same.
/** * Compare if this configuration is equal to another. * * @param other The other configuration * @return <code>true</code> if they are the same. */
public boolean equals( Object other ) { if( other == null ) return false; if( !( other instanceof DefaultConfiguration ) ) { // Niclas: It is not possible to validate equality against any // Configuration implementation, as it would be // impossible to get the hashCode() method return the // same value for two instances evaluating equal(). // I.e. If we were to do equality at API level, we would be // breaking the equals()/hashCode() semantic contract. return false; } DefaultConfiguration c = (DefaultConfiguration) other; if( m_readOnly ^ c.m_readOnly ) return false; if( check( m_name, c.m_name ) ) return false; if( check( m_location, c.m_location ) ) return false; if( check( m_namespace, c.m_namespace ) ) return false; if( check( m_prefix, c.m_prefix ) ) return false; if( check( m_value, c.m_value ) ) return false; if( check( m_attributes, c.m_attributes ) ) return false; if( check( m_children, c.m_children ) ) return false; return true; } private boolean check( Object one, Object two ) { if( one == null ) return two != null; return ! one.equals( two ); }
Obtaine the hashcode for this configuration.
Returns:the hashcode.
/** * Obtaine the hashcode for this configuration. * * @return the hashcode. */
public int hashCode() { int hash = m_prefix.hashCode(); if( m_name != null ) hash ^= m_name.hashCode(); hash >>>= 7; if( m_location != null ) hash ^= m_location.hashCode(); hash >>>= 7; if( m_namespace != null ) hash ^= m_namespace.hashCode(); hash >>>= 7; if( m_attributes != null ) hash ^= m_attributes.hashCode(); hash >>>= 7; if( m_children != null ) hash ^= m_children.hashCode(); hash >>>= 7; if( m_value != null ) hash ^= m_value.hashCode(); hash >>>= ( m_readOnly ) ? 7 : 13; return hash; } }