    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 }