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.beanutils;
18  
19  import java.util.Map;
20  
21  import org.apache.commons.configuration.HierarchicalConfiguration;
22  import org.apache.commons.configuration.tree.ConfigurationNode;
23  
24  import junit.framework.TestCase;
25  
26  /***
27   * Test class for XMLBeanDeclaration.
28   *
29   * @since 1.3
30   * @author Oliver Heger
31   * @version $Id: TestXMLBeanDeclaration.java 439648 2006-09-02 20:42:10Z oheger $
32   */
33  public class TestXMLBeanDeclaration extends TestCase
34  {
35      /*** An array with some test properties. */
36      static final String[] TEST_PROPS =
37      { "firstName", "lastName", "department", "age", "hobby"};
38  
39      /*** An array with the values for the test properties. */
40      static final String[] TEST_VALUES =
41      { "John", "Smith", "Engineering", "42", "TV"};
42  
43      /*** An array with the names of nested (complex) properties. */
44      static final String[] COMPLEX_PROPS =
45      { "address", "car"};
46  
47      /*** An array with the names of the classes of the complex properties. */
48      static final String[] COMPLEX_CLASSES =
49      { "org.apache.commons.configuration.test.AddressTest",
50              "org.apache.commons.configuration.test.CarTest"};
51  
52      /*** An array with the property names of the complex properties. */
53      static final String[][] COMPLEX_ATTRIBUTES =
54      {
55      { "street", "zip", "city", "country"},
56      { "brand", "color"}};
57  
58      /*** An array with the values of the complex properties. */
59      static final String[][] COMPLEX_VALUES =
60      {
61      { "Baker Street", "12354", "London", "UK"},
62      { "Bentley", "silver"}};
63  
64      /*** Constant for the key with the bean declaration. */
65      static final String KEY = "myBean";
66  
67      /*** Constant for the section with the variables.*/
68      static final String VARS = "variables.";
69  
70      /*** Stores the object to be tested. */
71      XMLBeanDeclaration decl;
72  
73      /***
74       * Tests creating a declaration from a null node. This should cause an
75       * exception.
76       */
77      public void testInitFromNullNode()
78      {
79          try
80          {
81              decl = new XMLBeanDeclaration(new HierarchicalConfiguration().configurationAt(null),
82                      (ConfigurationNode) null);
83              fail("Could init declaration with null node!");
84          }
85          catch (IllegalArgumentException iex)
86          {
87              // ok
88          }
89      }
90  
91      /***
92       * Tests creating a declaration from a null configuration. This should cause
93       * an exception.
94       */
95      public void testInitFromNullConfiguration()
96      {
97          try
98          {
99              decl = new XMLBeanDeclaration((HierarchicalConfiguration) null);
100             fail("Could init declaration with null configuration!");
101         }
102         catch (IllegalArgumentException iex)
103         {
104             // ok
105         }
106     }
107 
108     /***
109      * Tests creating a declaration from a null configuration with a key. This
110      * should cause an exception.
111      */
112     public void testInitFromNullConfigurationAndKey()
113     {
114         try
115         {
116             decl = new XMLBeanDeclaration(null, KEY);
117             fail("Could init declaration with null configuration and key!");
118         }
119         catch (IllegalArgumentException iex)
120         {
121             // ok
122         }
123     }
124 
125     /***
126      * Tests creating a declaration from a null configuration with a node. This
127      * should cause an exception.
128      */
129     public void testInitFromNullConfigurationAndNode()
130     {
131         try
132         {
133             decl = new XMLBeanDeclaration(null, new HierarchicalConfiguration()
134                     .getRoot());
135             fail("Could init declaration with null configuration and node!");
136         }
137         catch (IllegalArgumentException iex)
138         {
139             // ok
140         }
141     }
142 
143     /***
144      * Tests fetching the bean's class name.
145      */
146     public void testGetBeanClassName()
147     {
148         HierarchicalConfiguration config = new HierarchicalConfiguration();
149         config.addProperty(KEY + "[@config-class]", getClass().getName());
150         decl = new XMLBeanDeclaration(config, KEY);
151         assertEquals("Wrong class name", getClass().getName(), decl
152                 .getBeanClassName());
153     }
154 
155     /***
156      * Tests fetching the bean's class name if it is undefined.
157      */
158     public void testGetBeanClassNameUndefined()
159     {
160         decl = new XMLBeanDeclaration(new HierarchicalConfiguration());
161         assertNull(decl.getBeanClassName());
162     }
163 
164     /***
165      * Tests fetching the name of the bean factory.
166      */
167     public void testGetBeanFactoryName()
168     {
169         HierarchicalConfiguration config = new HierarchicalConfiguration();
170         config.addProperty(KEY + "[@config-factory]", "myFactory");
171         decl = new XMLBeanDeclaration(config, KEY);
172         assertEquals("Wrong factory name", "myFactory", decl
173                 .getBeanFactoryName());
174     }
175 
176     /***
177      * Tests fetching the name of the bean factory if it is undefined.
178      */
179     public void testGetBeanFactoryNameUndefined()
180     {
181         decl = new XMLBeanDeclaration(new HierarchicalConfiguration());
182         assertNull(decl.getBeanFactoryName());
183     }
184 
185     /***
186      * Tests fetching the paramter for the bean factory.
187      */
188     public void testGetBeanFactoryParameter()
189     {
190         HierarchicalConfiguration config = new HierarchicalConfiguration();
191         config
192                 .addProperty(KEY + "[@config-factoryParam]",
193                         "myFactoryParameter");
194         decl = new XMLBeanDeclaration(config, KEY);
195         assertEquals("Wrong factory parameter", "myFactoryParameter", decl
196                 .getBeanFactoryParameter());
197     }
198 
199     /***
200      * Tests fetching the paramter for the bean factory if it is undefined.
201      */
202     public void testGetBeanFactoryParameterUndefined()
203     {
204         decl = new XMLBeanDeclaration(new HierarchicalConfiguration());
205         assertNull(decl.getBeanFactoryParameter());
206     }
207 
208     /***
209      * Tests if the bean's properties are correctly extracted from the
210      * configuration object.
211      */
212     public void testGetBeanProperties()
213     {
214         HierarchicalConfiguration config = new HierarchicalConfiguration();
215         setupBeanDeclaration(config, KEY, TEST_PROPS, TEST_VALUES);
216         decl = new XMLBeanDeclaration(config, KEY);
217         checkProperties(decl, TEST_PROPS, TEST_VALUES);
218     }
219 
220     /***
221      * Tests obtaining the bean's properties when reserved attributes are
222      * involved. These should be ignored.
223      */
224     public void testGetBeanPropertiesWithReservedAttributes()
225     {
226         HierarchicalConfiguration config = new HierarchicalConfiguration();
227         setupBeanDeclaration(config, KEY, TEST_PROPS, TEST_VALUES);
228         config.addProperty(KEY + "[@config-testattr]", "yes");
229         config.addProperty(KEY + "[@config-anothertest]", "this, too");
230         decl = new XMLBeanDeclaration(config, KEY);
231         checkProperties(decl, TEST_PROPS, TEST_VALUES);
232     }
233 
234     /***
235      * Tests fetching properties if none are defined.
236      */
237     public void testGetBeanPropertiesEmpty()
238     {
239         decl = new XMLBeanDeclaration(new HierarchicalConfiguration());
240         Map props = decl.getBeanProperties();
241         assertTrue("Properties found", props == null || props.isEmpty());
242     }
243 
244     /***
245      * Tests fetching nested bean declarations.
246      */
247     public void testGetNestedBeanDeclarations()
248     {
249         HierarchicalConfiguration config = new HierarchicalConfiguration();
250         setupBeanDeclaration(config, KEY, TEST_PROPS, TEST_VALUES);
251         for (int i = 0; i < COMPLEX_PROPS.length; i++)
252         {
253             setupBeanDeclaration(config, KEY + '.' + COMPLEX_PROPS[i],
254                     COMPLEX_ATTRIBUTES[i], COMPLEX_VALUES[i]);
255             config.addProperty(
256                     KEY + '.' + COMPLEX_PROPS[i] + "[@config-class]",
257                     COMPLEX_CLASSES[i]);
258         }
259 
260         decl = new XMLBeanDeclaration(config, KEY);
261         checkProperties(decl, TEST_PROPS, TEST_VALUES);
262 
263         Map nested = decl.getNestedBeanDeclarations();
264         assertEquals("Wrong number of nested declarations",
265                 COMPLEX_PROPS.length, nested.size());
266         for (int i = 0; i < COMPLEX_PROPS.length; i++)
267         {
268             XMLBeanDeclaration d = (XMLBeanDeclaration) nested
269                     .get(COMPLEX_PROPS[i]);
270             assertNotNull("No declaration found for " + COMPLEX_PROPS[i], d);
271             checkProperties(d, COMPLEX_ATTRIBUTES[i], COMPLEX_VALUES[i]);
272             assertEquals("Wrong bean class", COMPLEX_CLASSES[i], d
273                     .getBeanClassName());
274         }
275     }
276 
277     /***
278      * Tests fetching nested bean declarations if none are defined.
279      */
280     public void testGetNestedBeanDeclarationsEmpty()
281     {
282         HierarchicalConfiguration config = new HierarchicalConfiguration();
283         setupBeanDeclaration(config, KEY, TEST_PROPS, TEST_VALUES);
284         decl = new XMLBeanDeclaration(config, KEY);
285         Map nested = decl.getNestedBeanDeclarations();
286         assertTrue("Found nested declarations", nested == null
287                 || nested.isEmpty());
288     }
289 
290     /***
291      * Tests whether interpolation of bean properties works.
292      */
293     public void testGetInterpolatedBeanProperties()
294     {
295         HierarchicalConfiguration config = new HierarchicalConfiguration();
296         String[] varValues = new String[TEST_PROPS.length];
297         for(int i = 0; i < TEST_PROPS.length; i++)
298         {
299             varValues[i] = "${" + VARS + TEST_PROPS[i] + "}";
300             config.addProperty(VARS + TEST_PROPS[i], TEST_VALUES[i]);
301         }
302         setupBeanDeclaration(config, KEY, TEST_PROPS, varValues);
303         decl = new XMLBeanDeclaration(config, KEY);
304         checkProperties(decl, TEST_PROPS, TEST_VALUES);
305     }
306 
307     /***
308      * Tests constructing a bean declaration from an undefined key. This should
309      * cause an exception.
310      */
311     public void testInitFromUndefinedKey()
312     {
313         HierarchicalConfiguration config = new HierarchicalConfiguration();
314         setupBeanDeclaration(config, KEY, TEST_PROPS, TEST_VALUES);
315         try
316         {
317             decl = new XMLBeanDeclaration(config, "undefined_key");
318             fail("Could create declaration from an undefined key!");
319         }
320         catch (IllegalArgumentException iex)
321         {
322             // ok
323         }
324     }
325 
326     /***
327      * Tests constructing a bean declaration from a key, which is undefined when
328      * the optional flag is set. In this case an empty declaration should be
329      * created, which can be used for creating beans as long as a default class
330      * is provided.
331      */
332     public void testInitFromUndefinedKeyOptional()
333     {
334         HierarchicalConfiguration config = new HierarchicalConfiguration();
335         setupBeanDeclaration(config, KEY, TEST_PROPS, TEST_VALUES);
336         decl = new XMLBeanDeclaration(config, "undefined_key", true);
337         assertNull("Found a bean class", decl.getBeanClassName());
338     }
339 
340     /***
341      * Tests constructing a bean declaration from a key with multiple values.
342      * This should cause an exception because keys must be unique.
343      */
344     public void testInitFromMultiValueKey()
345     {
346         HierarchicalConfiguration config = new HierarchicalConfiguration();
347         config.addProperty(KEY, "myFirstKey");
348         config.addProperty(KEY, "mySecondKey");
349         try
350         {
351             decl = new XMLBeanDeclaration(config, KEY);
352             fail("Could create declaration from multi-valued property!");
353         }
354         catch (IllegalArgumentException iex)
355         {
356             // ok
357         }
358     }
359 
360     /***
361      * Initializes a configuration object with a bean declaration. Under the
362      * specified key the given properties will be added.
363      *
364      * @param config the configuration to initialize
365      * @param key the key of the bean declaration
366      * @param names an array with the names of the properties
367      * @param values an array with the corresponding values
368      */
369     private void setupBeanDeclaration(HierarchicalConfiguration config,
370             String key, String[] names, String[] values)
371     {
372         for (int i = 0; i < names.length; i++)
373         {
374             config.addProperty(key + "[@" + names[i] + "]", values[i]);
375         }
376     }
377 
378     /***
379      * Checks the properties returned by a bean declaration.
380      *
381      * @param beanDecl the bean declaration
382      * @param names an array with the expected property names
383      * @param values an array with the expected property values
384      */
385     private void checkProperties(BeanDeclaration beanDecl, String[] names,
386             String[] values)
387     {
388         Map props = beanDecl.getBeanProperties();
389         assertEquals("Wrong number of properties", names.length, props.size());
390         for (int i = 0; i < names.length; i++)
391         {
392             assertTrue("Property " + names[i] + " not contained", props
393                     .containsKey(names[i]));
394             assertEquals("Wrong value for property " + names[i], values[i],
395                     props.get(names[i]));
396         }
397     }
398 }