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