    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.beanutils;
    18
    19  import java.util.Map;
    20  import java.util.HashMap;
    21  import java.util.TreeMap;
    22  import java.util.List;
    23  import java.util.ArrayList;
    24  import java.util.LinkedList;
    25  import java.lang.reflect.InvocationTargetException;
    26  import junit.framework.TestCase;
    27  import junit.framework.Test;
    28  import junit.framework.TestSuite;
    29
    30  /***
    31   * <p>Test Case for the <code>LazyDynaMap</code> implementation class.</p>
    32   *
    33   * @author Niall Pemberton
    34   */
    35  public class LazyDynaMapTestCase extends TestCase {
    36
    37      protected LazyDynaMap  dynaMap    = null;
    38      protected String testProperty     = "myProperty";
    39      protected String testPropertyA    = "myProperty-A";
    40      protected String testPropertyB    = "myProperty-B";
    41      protected String testString1      = "myStringValue-1";
    42      protected String testString2      = "myStringValue-2";
    43      protected Integer testInteger1    = new Integer(30);
    44      protected Integer testInteger2    = new Integer(40);
    45      protected String testKey          = "myKey";
    46
    47      // ---------------------------------------------------------- Constructors
    48
    49      /***
    50       * Construct a new instance of this test case.
    51       *
    52       * @param name Name of the test case
    53       */
    54      public LazyDynaMapTestCase(String name) {
    55          super(name);
    56      }
    57
    58      // -------------------------------------------------- Overall Test Methods
    59
    60      /***
    61       * Run thus Test
    62       */
    63      public static void main(String[] args) {
    64          junit.textui.TestRunner.run(suite());
    65      }
    66
    67      /***
    68       * Return the tests included in this test suite.
    69       */
    70      public static Test suite() {
    71          return (new TestSuite(LazyDynaMapTestCase.class));
    72      }
    73
    74      /***
    75       * Set up instance variables required by this test case.
    76       */
    77      public void setUp() throws Exception {
    78          dynaMap = new LazyDynaMap();
    79          dynaMap.setReturnNull(true);
    80      }
    81
    82      /***
    83       * Tear down instance variables required by this test case.
    84       */
    85      public void tearDown() {
    86        dynaMap = null;
    87      }
    88
    89      // ------------------------------------------------ Individual Test Methods
    90
    91      /***
    92       * General Tests
    93       */
    94      public void testGeneral() {
    95  //        LazyDynaMap bean = new LazyDynaMap("TestBean");
    96          assertEquals("Check DynaClass name", "TestBean", new LazyDynaMap("TestBean").getName());
    97
    98      }
    99
    100     /***
    101      * Test Getting/Setting a Simple Property
    102      */
    103     public void testSimpleProperty() {
    104
    105         // Check the property & value doesn't exist
    106         assertNull("Check Property doesn't exist", dynaMap.getDynaProperty(testProperty));
    107         assertNull("Check Value is null", dynaMap.get(testProperty));
    108
    109         // Set a new property - should add new property and set value
    110         dynaMap.set(testProperty, testInteger1);
    111         assertEquals("Check First Value is correct", testInteger1, dynaMap.get(testProperty));
    112         assertEquals("Check Property type is correct", Integer.class, dynaMap.getDynaProperty(testProperty).getType());
    113
    114         // Set the property again - should set the new value
    115         dynaMap.set(testProperty, testInteger2);
    116         assertEquals("Check Second Value is correct", testInteger2, dynaMap.get(testProperty));
    117
    118         // Set the property again - with a different type, should succeed
    119         dynaMap.set(testProperty, testString1);
    120         assertEquals("Check Third Value is correct", testString1, dynaMap.get(testProperty));
    121
    122     }
    123
    124     /***
    125      * Test Setting a Simple Property when MutableDynaClass is set to restricted
    126      */
    127     public void testSimplePropertyRestricted() {
    128
    129         // Set the MutableDyanClass to 'restricted' (i.e. no new properties cab be added
    130         dynaMap.setRestricted(true);
    131         assertTrue("Check MutableDynaClass is restricted", dynaMap.isRestricted());
    132
    133         // Check the property & value doesn't exist
    134         assertNull("Check Property doesn't exist", dynaMap.getDynaProperty(testProperty));
    135         assertNull("Check Value is null", dynaMap.get(testProperty));
    136
    137         // Set the property - should fail because property doesn't exist and MutableDynaClass is restricted
    138         try {
    139             dynaMap.set(testProperty, testString1);
    140             fail("expected IllegalArgumentException trying to add new property to restricted DynaClass");
    141         } catch (IllegalArgumentException expected) {
    142             // expected result
    143         }
    144
    145     }
    146
    147     /***
    148      * Test Getting/Setting a 'Mapped' Property - default HashMap property
    149      */
    150     public void testMappedPropertyDefault() {
    151
    152         // Check the property & value doesn't exist
    153         assertNull("Check Mapped Property doesn't exist", dynaMap.getDynaProperty(testProperty));
    154         assertNull("Check Map is null", dynaMap.get(testProperty));
    155         assertNull("Check Mapped Value is null", dynaMap.get(testProperty, testKey));
    156
    157         // Set a new mapped property - should add new HashMap property and set the mapped value
    158         dynaMap.set(testProperty, testKey, testInteger1);
    159         assertEquals("Check Mapped Property exists", HashMap.class, dynaMap.get(testProperty).getClass());
    160         assertEquals("Check First Mapped Value is correct(a)", testInteger1, dynaMap.get(testProperty, testKey));
    161         assertEquals("Check First Mapped Value is correct(b)", testInteger1, ((HashMap)dynaMap.get(testProperty)).get(testKey));
    162
    163         // Set the property again - should set the new value
    164         dynaMap.set(testProperty, testKey, testInteger2);
    165         assertEquals("Check Second Mapped Value is correct(a)", testInteger2, dynaMap.get(testProperty, testKey));
    166         assertEquals("Check Second Mapped Value is correct(b)", testInteger2, ((HashMap)dynaMap.get(testProperty)).get(testKey));
    167     }
    168
    169     /***
    170      * Test Getting/Setting a 'Mapped' Property - use TreeMap property
    171      */
    172     public void testMappedPropertyTreeMap() {
    173
    174         // Check the property & value doesn't exist
    175         assertNull("Check Mapped Property doesn't exist", dynaMap.getDynaProperty(testProperty));
    176         assertNull("Check Map is null", dynaMap.get(testProperty));
    177
    178         // Add a 'TreeMap' property to the DynaClass
    179         dynaMap.add(testProperty, TreeMap.class);
    180         assertTrue("Check Property is mapped", dynaMap.getDynaProperty(testProperty).isMapped());
    181         assertEquals("Check Property is correct type", TreeMap.class, dynaMap.getDynaProperty(testProperty).getType());
    182         assertEquals("Check Mapped Property now exists", TreeMap.class, dynaMap.get(testProperty).getClass());
    183
    184         // Set a new mapped property - should instatiate a new TreeMap property and set the mapped value
    185         dynaMap.set(testProperty, testKey, testInteger1);
    186         assertEquals("Check Mapped Property exists", TreeMap.class, dynaMap.get(testProperty).getClass());
    187         assertEquals("Check First Mapped Value is correct(a)", testInteger1, dynaMap.get(testProperty, testKey));
    188         assertEquals("Check First Mapped Value is correct(b)", testInteger1, ((TreeMap)dynaMap.get(testProperty)).get(testKey));
    189
    190         // Set the property again - should set the new value
    191         dynaMap.set(testProperty, testKey, testInteger2);
    192         assertEquals("Check Second Mapped Value is correct(a)", testInteger2, dynaMap.get(testProperty, testKey));
    193         assertEquals("Check Second Mapped Value is correct(b)", testInteger2, ((TreeMap)dynaMap.get(testProperty)).get(testKey));
    194     }
    195
    196     /***
    197      * Test Setting a 'Mapped' Property using PropertyUtils
    198      */
    199     public void testMappedPropertyUtils() {
    200
    201         dynaMap.setReturnNull(false);
    202
    203         // Check the property & value doesn't exist
    204         assertFalse("Check Mapped Property doesn't exist", dynaMap.isDynaProperty(testProperty));
    205         assertNull("Check Map is null", dynaMap.get(testProperty));
    206         assertNull("Check Mapped Value is null", dynaMap.get(testProperty, testKey));
    207
    208         // Set the mapped property using PropertyUtils
    209         try {
    210           PropertyUtils.setProperty(dynaMap, testProperty+"("+testKey+")", testString1);
    211         }
    212         catch (NoSuchMethodException ex) {
    213             fail("testIndexedPropertyUtils threw "+ex);
    214         }
    215         catch (InvocationTargetException ex) {
    216             fail("testIndexedPropertyUtils threw "+ex);
    217         }
    218         catch (IllegalAccessException ex) {
    219             fail("testIndexedPropertyUtils threw "+ex);
    220         }
    221
    222         // Check property value correctly set
    223         assertEquals("Check Mapped Bean Value is correct", testString1, dynaMap.get(testProperty, testKey));
    224
    225     }
    226
    227     /***
    228      * Test Setting a Mapped Property when MutableDynaClass is set to restricted
    229      */
    230     public void testMappedPropertyRestricted() {
    231
    232         // Set the MutableDyanClass to 'restricted' (i.e. no new properties cab be added
    233         dynaMap.setRestricted(true);
    234         assertTrue("Check MutableDynaClass is restricted", dynaMap.isRestricted());
    235
    236         // Check the property & value doesn't exist
    237         assertNull("Check Property doesn't exist", dynaMap.getDynaProperty(testProperty));
    238         assertNull("Check Value is null", dynaMap.get(testProperty));
    239
    240         // Set the property - should fail because property doesn't exist and MutableDynaClass is restricted
    241         try {
    242             dynaMap.set(testProperty, testKey, testInteger1);
    243             fail("expected IllegalArgumentException trying to add new property to restricted MutableDynaClass");
    244         } catch (IllegalArgumentException expected) {
    245             // expected result
    246         }
    247
    248     }
    249
    250     /***
    251      * Test setting mapped property for type which is not Map
    252      */
    253     public void testMappedInvalidType() {
    254         dynaMap.set(testProperty, new Integer(1));
    255         assertFalse("Check Property is not mapped", dynaMap.getDynaProperty(testProperty).isMapped());
    256         try {
    257             dynaMap.set(testProperty, testKey, testInteger1);
    258             fail("set(property, key, value) should have thrown IllegalArgumentException");
    259         } catch (IllegalArgumentException expected) {
    260             // expected result
    261         }
    262     }
    263
    264     /***
    265      * Test Getting/Setting an 'Indexed' Property - default ArrayList property
    266      */
    267     public void testIndexedPropertyDefault() {
    268
    269         int index = 3;
    270
    271         // Check the property & value doesn't exist
    272         assertNull("Check Indexed Property doesn't exist", dynaMap.getDynaProperty(testProperty));
    273         assertNull("Check Indexed Property is null", dynaMap.get(testProperty));
    274         assertNull("Check Indexed value is null", dynaMap.get(testProperty, index));
    275
    276         // Set the property, should create new ArrayList and set appropriate indexed value
    277         dynaMap.set(testProperty, index, testInteger1);
    278         assertNotNull("Check Indexed Property is not null", dynaMap.get(testProperty));
    279         assertEquals("Check Indexed Property is correct type", ArrayList.class, dynaMap.get(testProperty).getClass());
    280         assertEquals("Check First Indexed Value is correct", testInteger1, dynaMap.get(testProperty, index));
    281         assertEquals("Check First Array length is correct", new Integer(index+1),  new Integer(((ArrayList)dynaMap.get(testProperty)).size()));
    282
    283         // Set a second indexed value, should automatically grow the ArrayList and set appropriate indexed value
    284         index = index + 2;
    285         dynaMap.set(testProperty, index, testString1);
    286         assertEquals("Check Second Indexed Value is correct", testString1, dynaMap.get(testProperty, index));
    287         assertEquals("Check Second Array length is correct", new Integer(index+1),  new Integer(((ArrayList)dynaMap.get(testProperty)).size()));
    288     }
    289
    290     /***
    291      * Test Getting/Setting a List 'Indexed' Property - use alternative List (LinkedList)
    292      */
    293     public void testIndexedLinkedList() {
    294
    295         int   index     = 3;
    296
    297         // Check the property & value doesn't exist
    298         assertNull("Check Indexed Property doesn't exist", dynaMap.getDynaProperty(testProperty));
    299         assertNull("Check Indexed Property is null", dynaMap.get(testProperty));
    300
    301         // Add a 'LinkedList' property to the DynaClass - should instantiate a new LinkedList
    302         dynaMap.add(testProperty, LinkedList.class);
    303         assertTrue("Check Property is indexed", dynaMap.getDynaProperty(testProperty).isIndexed());
    304         assertEquals("Check Property is correct type", LinkedList.class, dynaMap.getDynaProperty(testProperty).getType());
    305         assertEquals("Check Indexed Property now exists", LinkedList.class, dynaMap.get(testProperty).getClass());
    306
    307         // Set the Indexed property, should grow the list to the correct size
    308         dynaMap.set(testProperty, index, testString1);
    309         assertEquals("Check Property type is correct", LinkedList.class, dynaMap.get(testProperty).getClass());
    310         assertEquals("Check First Indexed Value is correct", testString1, dynaMap.get(testProperty, index));
    311         assertEquals("Check First Array length is correct", new Integer(index+1),  new Integer(((LinkedList)dynaMap.get(testProperty)).size()));
    312
    313         // Set a second indexed value, should automatically grow the LinkedList and set appropriate indexed value
    314         index = index + 2;
    315         dynaMap.set(testProperty, index, testInteger1);
    316         assertEquals("Check Second Indexed Value is correct", testInteger1, dynaMap.get(testProperty, index));
    317         assertEquals("Check Second Array length is correct", new Integer(index+1),  new Integer(((LinkedList)dynaMap.get(testProperty)).size()));
    318     }
    319
    320     /***
    321      * Test Getting/Setting a primitive array 'Indexed' Property - use int[]
    322      */
    323     public void testIndexedPrimitiveArray() {
    324
    325         int   index     = 3;
    326         int[] primitiveArray = new int[0];
    327
    328         // Check the property & value doesn't exist
    329         assertNull("Check Indexed Property doesn't exist", dynaMap.getDynaProperty(testProperty));
    330         assertNull("Check Indexed Property is null", dynaMap.get(testProperty));
    331
    332         // Add a DynaProperty of type int[]
    333         dynaMap.add(testProperty, primitiveArray.getClass());
    334         assertEquals("Check Indexed Property exists", primitiveArray.getClass(), dynaMap.getDynaProperty(testProperty).getType());
    335         assertTrue("Check Indexed Property exists", dynaMap.get(testProperty).getClass().isInstance(primitiveArray));
    336
    337         // Set an indexed value
    338         dynaMap.set(testProperty, index, testInteger1);
    339         assertNotNull("Check Indexed Property is not null", dynaMap.get(testProperty));
    340         assertEquals("Check Indexed Property is correct type", primitiveArray.getClass(), dynaMap.get(testProperty).getClass());
    341         assertEquals("Check First Indexed Value is correct(a)", testInteger1, dynaMap.get(testProperty, index));
    342         assertEquals("Check First Indexed Value is correct(b)", testInteger1, new Integer(((int[])dynaMap.get(testProperty))[index]));
    343         assertEquals("Check Array length is correct", new Integer(index+1),  new Integer(((int[])dynaMap.get(testProperty)).length));
    344
    345         // Set a second indexed value, should automatically grow the int[] and set appropriate indexed value
    346         index = index + 2;
    347         dynaMap.set(testProperty, index, testInteger2);
    348         assertEquals("Check Second Indexed Value is correct(a)", testInteger2, dynaMap.get(testProperty, index));
    349         assertEquals("Check Second Indexed Value is correct(b)", testInteger2, new Integer(((int[])dynaMap.get(testProperty))[index]));
    350         assertEquals("Check Second Array length is correct", new Integer(index+1),  new Integer(((int[])dynaMap.get(testProperty)).length));
    351
    352     }
    353
    354     /***
    355      * Test Getting/Setting an Object array 'Indexed' Property - use String[]
    356      */
    357     public void testIndexedObjectArray() {
    358
    359         int   index     = 3;
    360         Object objectArray = new String[0];
    361
    362         // Check the property & value doesn't exist
    363         assertNull("Check Indexed Property doesn't exist", dynaMap.getDynaProperty(testProperty));
    364         assertNull("Check Indexed Property is null", dynaMap.get(testProperty));
    365
    366         // Add a DynaProperty of type String[]
    367         dynaMap.add(testProperty, objectArray.getClass());
    368         assertEquals("Check Indexed Property exists", objectArray.getClass(), dynaMap.getDynaProperty(testProperty).getType());
    369         assertTrue("Check Indexed Property exists", dynaMap.get(testProperty).getClass().isInstance(objectArray));
    370
    371         // Set an indexed value
    372         dynaMap.set(testProperty, index, testString1);
    373         assertNotNull("Check Indexed Property is not null", dynaMap.get(testProperty));
    374         assertEquals("Check Indexed Property is correct type", objectArray.getClass(), dynaMap.get(testProperty).getClass());
    375         assertEquals("Check First Indexed Value is correct(a)", testString1, dynaMap.get(testProperty, index));
    376         assertEquals("Check First Indexed Value is correct(b)", testString1, ((String[])dynaMap.get(testProperty))[index]);
    377         assertEquals("Check Array length is correct", new Integer(index+1),  new Integer(((String[])dynaMap.get(testProperty)).length));
    378
    379         // Set a second indexed value, should automatically grow the String[] and set appropriate indexed value
    380         index = index + 2;
    381         dynaMap.set(testProperty, index, testString2);
    382         assertEquals("Check Second Indexed Value is correct(a)", testString2, dynaMap.get(testProperty, index));
    383         assertEquals("Check Second Indexed Value is correct(b)", testString2, ((String[])dynaMap.get(testProperty))[index]);
    384         assertEquals("Check Second Array length is correct", new Integer(index+1),  new Integer(((String[])dynaMap.get(testProperty)).length));
    385     }
    386
    387     /***
    388      * Test Getting/Setting an DynaBean[] array
    389      */
    390     public void testIndexedDynaBeanArray() {
    391
    392         int   index     = 3;
    393         Object objectArray = new LazyDynaBean[0];
    394
    395         // Check the property & value doesn't exist
    396         assertNull("Check Indexed Property doesn't exist", dynaMap.getDynaProperty(testProperty));
    397         assertNull("Check Indexed Property is null", dynaMap.get(testProperty));
    398
    399         // Add a DynaProperty of type String[]
    400         dynaMap.add(testProperty, objectArray.getClass());
    401         assertEquals("Check Indexed Property exists", objectArray.getClass(), dynaMap.getDynaProperty(testProperty).getType());
    402         assertEquals("Check Indexed Property is correct type", objectArray.getClass(), dynaMap.get(testProperty).getClass());
    403
    404         // Retrieving from Array should initialize DynaBean
    405         for (int i = index; i >= 0; i--) {
    406             assertEquals("Check Array Components initialized", LazyDynaBean.class, dynaMap.get(testProperty, index).getClass());
    407         }
    408
    409         dynaMap.add(testPropertyB, objectArray.getClass());
    410         LazyDynaBean newBean = new LazyDynaBean();
    411         newBean.set(testPropertyB, testString2);
    412         dynaMap.set(testPropertyA, index, newBean);
    413         assertEquals("Check Indexed Value is correct(a)", testString2, ((DynaBean)dynaMap.get(testPropertyA, index)).get(testPropertyB));
    414
    415     }
    416
    417     /***
    418      * Test Setting an 'Indexed' Property using PropertyUtils
    419      */
    420     public void testIndexedPropertyUtils() {
    421
    422         int   index     = 3;
    423         dynaMap.setReturnNull(false);
    424
    425         // Check the property & value doesn't exist
    426         assertFalse("Check Indexed Property doesn't exist", dynaMap.isDynaProperty(testProperty));
    427         assertNull("Check Indexed Property is null", dynaMap.get(testProperty));
    428         assertNull("Check Indexed value is null", dynaMap.get(testProperty, index));
    429
    430         // Use PropertyUtils to set the indexed value
    431         try {
    432           PropertyUtils.setProperty(dynaMap, testProperty+"["+index+"]", testString1);
    433         }
    434         catch (NoSuchMethodException ex) {
    435             fail("testIndexedPropertyUtils threw "+ex);
    436         }
    437         catch (InvocationTargetException ex) {
    438             fail("testIndexedPropertyUtils threw "+ex);
    439         }
    440         catch (IllegalAccessException ex) {
    441             fail("testIndexedPropertyUtils threw "+ex);
    442         }
    443
    444         // Check property value correctly set
    445         assertEquals("Check Indexed Bean Value is correct", testString1, dynaMap.get(testProperty, index));
    446
    447     }
    448
    449     /***
    450      * Test Setting an Indexed Property when MutableDynaClass is set to restricted
    451      */
    452     public void testIndexedPropertyRestricted() {
    453
    454         int   index     = 3;
    455
    456         // Set the MutableDyanClass to 'restricted' (i.e. no new properties cab be added
    457         dynaMap.setRestricted(true);
    458         assertTrue("Check MutableDynaClass is restricted", dynaMap.isRestricted());
    459
    460         // Check the property & value doesn't exist
    461         assertNull("Check Property doesn't exist", dynaMap.getDynaProperty(testProperty));
    462         assertNull("Check Value is null", dynaMap.get(testProperty));
    463
    464         // Set the property - should fail because property doesn't exist and MutableDynaClass is restricted
    465         try {
    466             dynaMap.set(testProperty, index, testInteger1);
    467             fail("expected IllegalArgumentException trying to add new property to restricted MutableDynaClass");
    468         } catch (IllegalArgumentException expected) {
    469             // expected result
    470         }
    471
    472     }
    473
    474     /***
    475      * Test setting indexed property for type which is not List or Array
    476      */
    477     public void testIndexedInvalidType() {
    478         int   index     = 3;
    479         dynaMap.set(testProperty, "Test String");
    480         assertFalse("Check Property is not indexed", dynaMap.getDynaProperty(testProperty).isIndexed());
    481         try {
    482             dynaMap.set(testProperty, index, testString1);
    483             fail("set(property, index, value) should have thrown IllegalArgumentException");
    484         } catch (IllegalArgumentException expected) {
    485             // expected result
    486         }
    487     }
    488
    489     /***
    490      * Test creating using DynaClass.newInstance()
    491      */
    492     public void testNewInstance() {
    493
    494         // Create LazyDynaMap using TreeMap
    495         // containing some properties
    496         LazyDynaMap orig = new LazyDynaMap(new TreeMap());
    497         orig.set("indexProp", 0, "indexVal0");
    498         orig.set("indexProp", 1, "indexVal1");
    499         assertEquals("Index prop size", 2, ((List)orig.get("indexProp")).size());
    500
    501         LazyDynaMap newOne = (LazyDynaMap)orig.newInstance();
    502         Map newMap = newOne.getMap();
    503         assertEquals("Check Map type", TreeMap.class, newMap.getClass());
    504
    505         ArrayList indexProp = (ArrayList)newMap.get("indexProp");
    506         assertNotNull("Indexed Prop missing", indexProp);
    507         assertEquals("Index prop size", 0, indexProp.size());
    508     }
    509
    510 }