View Javadoc

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17  package org.apache.commons.configuration;
    18
    19  import org.apache.commons.configuration.tree.ConfigurationNode;
    20
    21  /***
    22   * <p>
    23   * A specialized hierarchical configuration class that wraps a single node of
    24   * its parent configuration.
    25   * </p>
    26   * <p>
    27   * Configurations of this type are initialized with a parent configuration and a
    28   * configuration node of this configuration. This node becomes the root node of
    29   * the subnode configuration. All property accessor methods are evaluated
    30   * relative to this root node. A good use case for a
    31   * <code>SubnodeConfiguration</code> is when multiple properties from a
    32   * specific sub tree of the whole configuration need to be accessed. Then a
    33   * <code>SubnodeConfiguration</code> can be created with the parent node of
    34   * the affected sub tree as root node. This allows for simpler property keys and
    35   * is also more efficient.
    36   * </p>
    37   * <p>
    38   * A subnode configuration and its parent configuration operate on the same
    39   * hierarchy of configuration nodes. So if modifications are performed at the
    40   * subnode configuration, these changes are immideately visible in the parent
    41   * configuration. Analogously will updates of the parent configuration affect
    42   * the subnode configuration if the sub tree spanned by the subnode
    43   * configuration's root node is involved.
    44   * </p>
    45   * <p>
    46   * When a subnode configuration is created, it inherits the settings of its
    47   * parent configuration, e.g. some flags like the
    48   * <code>throwExceptionOnMissing</code> flag or the settings for handling list
    49   * delimiters) or the expression engine. If these settings are changed later in
    50   * either the subnode or the parent configuration, the changes are not visible
    51   * for each other. So you could create a subnode configuration, change its
    52   * expression engine without affecting the parent configuration.
    53   * </p>
    54   * <p>
    55   * From its purpose this class is quite similar to
    56   * <code>{@link SubsetConfiguration}</code>. The difference is that a subset
    57   * configuration of a hierarchical configuration may combine multiple
    58   * configuration nodes from different sub trees of the configuration, while all
    59   * nodes in a subnode configuration belong to the same sub tree. If an
    60   * application can live with this limitation, it is recommended to use this
    61   * class instead of <code>SubsetConfiguration</code> because creating a subset
    62   * configuration is more expensive than creating a subnode configuration.
    63   * </p>
    64   *
    65   * @since 1.3
    66   * @author Oliver Heger
    67   * @version $Id: SubnodeConfiguration.java 439648 2006-09-02 20:42:10Z oheger $
    68   */
    69  public class SubnodeConfiguration extends HierarchicalConfiguration
    70  {
    71      /***
    72       * The serial version UID.
    73       */
    74      private static final long serialVersionUID = 3105734147019386480L;
    75
    76      /*** Stores the parent configuration. */
    77      private HierarchicalConfiguration parent;
    78
    79      /***
    80       * Creates a new instance of <code>SubnodeConfiguration</code> and
    81       * initializes it with the parent configuration and the new root node.
    82       *
    83       * @param parent the parent configuration
    84       * @param root the root node of this subnode configuration
    85       */
    86      public SubnodeConfiguration(HierarchicalConfiguration parent, ConfigurationNode root)
    87      {
    88          if (parent == null)
    89          {
    90              throw new IllegalArgumentException(
    91                      "Parent configuration must not be null!");
    92          }
    93          if (root == null)
    94          {
    95              throw new IllegalArgumentException("Root node must not be null!");
    96          }
    97
    98          setRootNode(root);
    99          this.parent = parent;
    100         initFromParent(parent);
    101     }
    102
    103     /***
    104      * Returns the parent configuration of this subnode configuration.
    105      *
    106      * @return the parent configuration
    107      */
    108     public HierarchicalConfiguration getParent()
    109     {
    110         return parent;
    111     }
    112
    113     /***
    114      * Returns a hierarchical configuration object for the given sub node.
    115      * This implementation will ensure that the returned
    116      * <code>SubnodeConfiguration</code> object will have the same parent than
    117      * this object.
    118      *
    119      * @param node the sub node, for which the configuration is to be created
    120      * @return a hierarchical configuration for this sub node
    121      */
    122     protected SubnodeConfiguration createSubnodeConfiguration(ConfigurationNode node)
    123     {
    124         return new SubnodeConfiguration(getParent(), node);
    125     }
    126
    127     /***
    128      * Creates a new node. This task is delegated to the parent.
    129      *
    130      * @param name the node's name
    131      * @return the new node
    132      */
    133     protected Node createNode(String name)
    134     {
    135         return getParent().createNode(name);
    136     }
    137
    138     /***
    139      * Initializes this subnode configuration from the given parent
    140      * configuration. This method is called by the constructor. It will copy
    141      * many settings from the parent.
    142      *
    143      * @param parentConfig the parent configuration
    144      */
    145     protected void initFromParent(HierarchicalConfiguration parentConfig)
    146     {
    147         setExpressionEngine(parentConfig.getExpressionEngine());
    148         setListDelimiter(parentConfig.getListDelimiter());
    149         setDelimiterParsingDisabled(parentConfig.isDelimiterParsingDisabled());
    150         setThrowExceptionOnMissing(parentConfig.isThrowExceptionOnMissing());
    151     }
    152
    153     /***
    154      * Performs interpolation. This implementation will ask the parent
    155      * configuration to perform the interpolation so that variables can be
    156      * evaluated in the global context.
    157      *
    158      * @param value the value to be interpolated
    159      */
    160     protected Object interpolate(Object value)
    161     {
    162         return getParent().interpolate(value);
    163     }
    164 }