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 }