1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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 }