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