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