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.assertNotNull;
21  import static org.junit.jupiter.api.Assertions.assertNull;
22  import static org.junit.jupiter.api.Assertions.assertSame;
23  import static org.junit.jupiter.api.Assertions.assertThrows;
24  
25  import java.io.ByteArrayInputStream;
26  import java.io.ByteArrayOutputStream;
27  import java.io.IOException;
28  import java.io.NotSerializableException;
29  import java.io.ObjectInputStream;
30  import java.io.ObjectOutputStream;
31  import java.util.ArrayList;
32  import java.util.HashMap;
33  import java.util.List;
34  import java.util.Map;
35  import java.util.TreeMap;
36  
37  import org.junit.jupiter.api.AfterEach;
38  import org.junit.jupiter.api.BeforeEach;
39  import org.junit.jupiter.api.Test;
40  
41  /**
42   * Tests {@link LazyDynaList}.
43   */
44  public class LazyDynaListTest {
45  
46      private static final String BASIC_PROP1 = "BasicDynaClass_Property1";
47      private static final String BASIC_PROP2 = "BasicDynaClass_Property2";
48  
49      protected DynaProperty[] properties = { new DynaProperty(BASIC_PROP1, String.class), new DynaProperty(BASIC_PROP2, HashMap.class) };
50      protected DynaClass treeMapDynaClass = new LazyDynaMap(new TreeMap<>());
51      protected DynaClass hashMapDynaClass = new LazyDynaMap(new HashMap<>());
52  
53      protected DynaClass pojoDynaClass = new WrapDynaBean(new TestBean()).getDynaClass();
54  
55      protected DynaClass basicDynaClass = new BasicDynaClass("test", BasicDynaBean.class, properties);
56  
57      /**
58       * Test DynaBean Create
59       */
60      private void dynaBeanTest(final LazyDynaList list, final Class<?> testClass, final DynaClass testDynaClass, final Object wrongBean)
61              throws IllegalAccessException, InstantiationException {
62  
63          // Test get(index) created correct DynaBean - Second
64          Object dynaBean = list.get(1);
65          assertNotNull(dynaBean, "1. DynaBean Not Created");
66          assertEquals(testClass, dynaBean.getClass(), "2. Wrong Type");
67  
68          // Test toArray() creates correct Array - Second
69          Object array = list.toArray();
70          assertNotNull(array, "3. Array Not Created");
71          assertEquals(testClass, array.getClass().getComponentType(), "4. Not DynaBean[]");
72          DynaBean[] dynaArray = (DynaBean[]) array;
73          assertEquals(2, dynaArray.length, "5. Array Size Wrong");
74  
75          // Test get(index) created correct DynaBean - Fourth
76          dynaBean = list.get(3);
77          assertNotNull(dynaBean, "6. DynaBean Not Created");
78          assertEquals(testClass, dynaBean.getClass(), "7. Wrong type");
79  
80          // Test toArray() creates correct Array - Fourth
81          array = list.toArray();
82          assertNotNull(array, "8. Array Not Created");
83          assertEquals(testClass, array.getClass().getComponentType(), "9. Not DynaBean[]");
84          dynaArray = (DynaBean[]) array;
85          assertEquals(4, dynaArray.length, "10. Array Size Wrong");
86  
87          // Test fail if different type added
88          assertThrows(IllegalArgumentException.class, () -> list.add(2, wrongBean));
89  
90          // find a String property to set
91          final String testProperty = findStringProperty(testDynaClass);
92          assertNotNull(testProperty, "Test Property Not Found");
93          dynaArray = list.toDynaBeanArray();
94          for (int i = 0; i < dynaArray.length; i++) {
95              dynaArray[i].set(testProperty, "orig_pos" + i);
96          }
97  
98          // Create Collection
99          final List<Object> collection = new ArrayList<>();
100         collection.add(testDynaClass.newInstance());
101         collection.add(testDynaClass.newInstance());
102         collection.add(testDynaClass.newInstance());
103         final int expectedSize = dynaArray.length + collection.size();
104         final String origValue = (String) ((DynaBean) collection.get(0)).get(testProperty);
105         ((DynaBean) collection.get(0)).set(testProperty, origValue + "_updated_" + 0);
106         ((DynaBean) collection.get(1)).set(testProperty, origValue + "_updated_" + 1);
107         ((DynaBean) collection.get(2)).set(testProperty, origValue + "_updated_" + 2);
108 
109         // Test Insert - addAll(index, Collection)
110         list.addAll(1, collection);
111         dynaArray = list.toDynaBeanArray();
112 
113         // Check array after insert
114         dynaArray = list.toDynaBeanArray();
115         assertEquals(expectedSize, dynaArray.length, "11. Array Size Wrong");
116 
117         // Check Beans have inserted correctly - by checking the property values
118         assertEquals("orig_pos0", dynaArray[0].get(testProperty), "12. Wrong Value");
119         assertEquals(origValue + "_updated_" + 0, dynaArray[1].get(testProperty), "13. Wrong Value");
120         assertEquals(origValue + "_updated_" + 1, dynaArray[2].get(testProperty), "14. Wrong Value");
121         assertEquals(origValue + "_updated_" + 2, dynaArray[3].get(testProperty), "15. Wrong Value");
122         assertEquals("orig_pos1", dynaArray[4].get(testProperty), "16. Wrong Value");
123 
124         // Test Insert - add(index, Object)
125         final DynaBean extraElement = testDynaClass.newInstance();
126         extraElement.set(testProperty, "extraOne");
127         list.add(2, extraElement);
128         dynaArray = list.toDynaBeanArray();
129         assertEquals(origValue + "_updated_" + 0, dynaArray[1].get(testProperty), "17. Wrong Value");
130         assertEquals("extraOne", dynaArray[2].get(testProperty), "18. Wrong Value");
131         assertEquals(origValue + "_updated_" + 1, dynaArray[3].get(testProperty), "19. Wrong Value");
132     }
133 
134     /**
135      * Test Map Create
136      */
137     private String findStringProperty(final DynaClass dynaClass) {
138         final DynaProperty[] properties = dynaClass.getDynaProperties();
139         for (final DynaProperty property : properties) {
140             if (property.getType() == String.class) {
141                 return property.getName();
142             }
143         }
144         return null;
145     }
146 
147     /**
148      * Test Map Create
149      */
150     private void mapTest(final LazyDynaList list, final Class<?> testClass, final Object wrongBean) {
151 
152         // Test get(index) created correct DynaBean - First
153         Object dynaBean = list.get(0);
154         assertNotNull(dynaBean, "1. DynaBean Not Created");
155         assertEquals(LazyDynaMap.class, dynaBean.getClass(), "2. Not LazyDynaMap");
156 
157         // Test get(index) created correct Map - First
158         Object map = ((LazyDynaMap) dynaBean).getMap();
159         assertNotNull(map, "3. Map Not Created");
160         assertEquals(testClass, map.getClass(), "4. Wrong Map");
161 
162         // Test toArray() creates correct Array - First
163         Object array = list.toArray();
164         assertNotNull(array, "5. Array Not Created");
165         assertEquals(testClass, array.getClass().getComponentType(), "6. Not Map[]");
166         Map<?, ?>[] mapArray = (Map[]) array;
167         assertEquals(1, mapArray.length, "7. Array Size Wrong");
168 
169         // Test get(index) created correct DynaBean - Third
170         dynaBean = list.get(2);
171         assertNotNull(dynaBean, "8. DynaBean Not Created");
172         assertEquals(LazyDynaMap.class, dynaBean.getClass(), "9. Not LazyDynaMap");
173 
174         // Test get(index) created correct Map - Third
175         map = ((LazyDynaMap) dynaBean).getMap();
176         assertNotNull(map, "10. Map Not Created");
177         assertEquals(testClass, map.getClass(), "11. Wrong Map");
178 
179         // Test toArray() creates correct Array - Third
180         array = list.toArray();
181         assertNotNull(array, "12. Array Not Created");
182         assertEquals(testClass, array.getClass().getComponentType(), "13. Not Map[]");
183         mapArray = (Map[]) array;
184         assertEquals(3, mapArray.length, "14. Array Size Wrong");
185 
186         // Test fail if different type added
187         assertThrows(IllegalArgumentException.class, () -> list.add(2, wrongBean));
188 
189     }
190 
191     /**
192      * Test Pojo Create
193      */
194     private void pojoTest(final LazyDynaList list, final Class<?> testClass, final Object wrongBean) {
195 
196         // Test get(index) created correct DynaBean - First
197         Object dynaBean = list.get(0);
198         assertNotNull(dynaBean, "1. DynaBean Not Created");
199         assertEquals(WrapDynaBean.class, dynaBean.getClass(), "2. Not WrapDynaBean");
200 
201         // Test get(index) created correct POJO - First
202         Object pojoBean = ((WrapDynaBean) dynaBean).getInstance();
203         assertNotNull(pojoBean, "3. POJO Not Created");
204         assertEquals(testClass, pojoBean.getClass(), "4. Not WrapDynaBean");
205 
206         // Test toArray() creates correct Array - First
207         Object array = list.toArray();
208         assertNotNull(array, "5. Array Not Created");
209         assertEquals(testClass, array.getClass().getComponentType(), "6. Wrong array");
210         Object[] pojoArray = (Object[]) array;
211         assertEquals(1, pojoArray.length, "7. Array Size Wrong");
212 
213         // Test get(index) created correct DynaBean - Second
214         dynaBean = list.get(1);
215         assertNotNull(dynaBean, "8. DynaBean Not Created");
216         assertEquals(WrapDynaBean.class, dynaBean.getClass(), "9. Not WrapDynaBean");
217 
218         // Test get(index) created correct POJO - Second
219         pojoBean = ((WrapDynaBean) dynaBean).getInstance();
220         assertNotNull(pojoBean, "10. POJO Not Created");
221         assertEquals(testClass, pojoBean.getClass(), "11. Not WrapDynaBean");
222 
223         // Test toArray() creates correct Array - Second
224         array = list.toArray();
225         assertNotNull(array, "12. Array Not Created");
226         assertEquals(testClass, array.getClass().getComponentType(), "13. Wrong array");
227         pojoArray = (Object[]) array;
228         assertEquals(2, pojoArray.length, "14. Array Size Wrong");
229 
230         // Test fail if different type added
231         assertThrows(IllegalArgumentException.class, () -> list.add(2, wrongBean));
232 
233     }
234 
235     /**
236      * Do serialization and deserialization.
237      */
238     private Object serializeDeserialize(final Object target, final String text) throws IOException, ClassNotFoundException {
239         // Serialize the test object
240         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
241         try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
242             oos.writeObject(target);
243             oos.flush();
244         }
245         // Deserialize the test object
246         Object result = null;
247         try (ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
248                 ObjectInputStream ois = new ObjectInputStream(bais)) {
249             result = ois.readObject();
250         }
251         return result;
252     }
253 
254     /**
255      * Sets up instance variables required by this test case.
256      */
257     @BeforeEach
258     public void setUp() throws Exception {
259     }
260 
261     /**
262      * Tear down instance variables required by this test case.
263      */
264     @AfterEach
265     public void tearDown() {
266     }
267 
268     /**
269      * Test Collection
270      */
271     public void testCollection(final LazyDynaList list, final Class<?> testClass, final DynaClass testDynaClass, final Object wrongBean) {
272 
273         // Create Collection & Array of Maps
274         final int size = 5;
275         final List<Object> testList = new ArrayList<>(size);
276         final TreeMap<?, ?>[] testArray = new TreeMap[size];
277         for (int i = 0; i < size; i++) {
278             final TreeMap<String, Object> map = new TreeMap<>();
279             map.put("prop" + i, "val" + i);
280             testArray[i] = map;
281             testList.add(testArray[i]);
282         }
283 
284         // Create LazyArrayList from Collection
285         LazyDynaList lazyList = new LazyDynaList(testList);
286         assertEquals(size, lazyList.size(), "1. check size");
287 
288         DynaBean[] dynaArray = lazyList.toDynaBeanArray();
289         TreeMap<?, ?>[] mapArray = (TreeMap[]) lazyList.toArray();
290 
291         // Check values
292         assertEquals(size, dynaArray.length, "2. check size");
293         assertEquals(size, mapArray.length, "3. check size");
294         for (int i = 0; i < size; i++) {
295             assertEquals("val" + i, dynaArray[i].get("prop" + i), "4." + i + " DynaBean error ");
296             assertEquals("val" + i, mapArray[i].get("prop" + i), "5." + i + " Map error ");
297         }
298 
299         // Create LazyArrayList from Array
300         lazyList = new LazyDynaList(testArray);
301         assertEquals(size, lazyList.size(), "6. check size");
302 
303         dynaArray = lazyList.toDynaBeanArray();
304         mapArray = (TreeMap[]) lazyList.toArray();
305 
306         // Check values
307         assertEquals(size, dynaArray.length, "7. check size");
308         assertEquals(size, mapArray.length, "8. check size");
309         for (int i = 0; i < size; i++) {
310             assertEquals("val" + i, dynaArray[i].get("prop" + i), "9." + i + " DynaBean error ");
311             assertEquals("val" + i, mapArray[i].get("prop" + i), "10." + i + " Map error ");
312         }
313 
314     }
315 
316     /**
317      * Test DynaBean Create
318      */
319     @Test
320     public void testDynaBeanDynaClass() throws Exception {
321         // Create LazyArrayList for DynaBeans
322         final LazyDynaList list = new LazyDynaList(basicDynaClass);
323         // test
324         dynaBeanTest(list, BasicDynaBean.class, basicDynaClass, new BenchBean());
325     }
326 
327     /**
328      * Test DynaBean Create
329      */
330     @Test
331     public void testDynaBeanType() throws Exception {
332         // Create LazyArrayList for DynaBeans
333         final LazyDynaList list = new LazyDynaList(LazyDynaBean.class);
334         final LazyDynaBean bean = new LazyDynaBean();
335         bean.set("prop1", "val");
336         // test
337         dynaBeanTest(list, LazyDynaBean.class, bean.getDynaClass(), new BenchBean());
338     }
339 
340     /**
341      * Test Map Create
342      */
343     @Test
344     public void testMapDynaClass() {
345 
346         // Create LazyArrayList for TreeMap's
347         final LazyDynaList list = new LazyDynaList(treeMapDynaClass);
348 
349         // test
350         mapTest(list, TreeMap.class, new BenchBean());
351 
352     }
353 
354     /**
355      * Test Map Create
356      */
357     @Test
358     public void testMapType() {
359 
360         // Create LazyArrayList for HashMap's
361         final LazyDynaList list = new LazyDynaList(HashMap.class);
362 
363         // test
364         mapTest(list, HashMap.class, new BenchBean());
365 
366     }
367 
368     /**
369      * Test adding a map to List with no type set.
370      */
371     @Test
372     public void testNullType() {
373         final LazyDynaList lazyList = new LazyDynaList();
374         lazyList.add(new HashMap<>());
375     }
376 
377     /**
378      * Test Pojo Create
379      */
380     @Test
381     public void testPojoDynaClass() {
382 
383         // Create LazyArrayList for POJO's
384         final LazyDynaList list = new LazyDynaList(pojoDynaClass);
385 
386         // test
387         pojoTest(list, TestBean.class, new BenchBean());
388 
389     }
390 
391     /**
392      * Test Pojo Create
393      */
394     @Test
395     public void testPojoType() {
396 
397         // Create LazyArrayList for POJO's
398         final LazyDynaList list = new LazyDynaList(TestBean.class);
399 
400         // test
401         pojoTest(list, TestBean.class, new BenchBean());
402 
403     }
404 
405     /**
406      * Test DynaBean serialization.
407      */
408     @Test
409     public void testSerializationDynaBean() throws Exception {
410 
411         // Create LazyArrayList for DynaBeans
412         final LazyDynaList target = new LazyDynaList(basicDynaClass);
413         final BasicDynaBean bean = (BasicDynaBean) target.get(0);
414 
415         // Set a Property
416         assertNull(bean.get(BASIC_PROP1), "pre-set check");
417         bean.set(BASIC_PROP1, "value1");
418         assertEquals("value1", bean.get(BASIC_PROP1), "post-set check");
419 
420         // Serialize/Deserialize
421         assertThrows(NotSerializableException.class, () -> serializeDeserialize(target, "DynaBean"));
422 
423     }
424 
425     /**
426      * Test DynaBean serialization.
427      */
428     @Test
429     public void testSerializationLazyDynaBean() throws Exception {
430 
431         // Create LazyArrayList for DynaBeans
432         final LazyDynaList target = new LazyDynaList();
433         final LazyDynaBean bean = (LazyDynaBean) target.get(0);
434 
435         // Set a Property
436         assertNull(bean.get(BASIC_PROP1), "pre-set check");
437         bean.set(BASIC_PROP1, "value1");
438         assertEquals("value1", bean.get(BASIC_PROP1), "post-set check");
439 
440         // Serialize/Deserialize
441         assertThrows(NotSerializableException.class, () -> serializeDeserialize(target, "DynaBean"));
442 
443     }
444 
445     /**
446      * Test Map serialization.
447      */
448     @Test
449     public void testSerializationMap() throws Exception {
450 
451         // Create LazyArrayList for DynaBeans
452         final LazyDynaList target = new LazyDynaList(treeMapDynaClass);
453         final LazyDynaMap bean = (LazyDynaMap) target.get(0);
454 
455         // Set a Property
456         assertNull(bean.get(BASIC_PROP1), "pre-set check");
457         bean.set(BASIC_PROP1, "value1");
458         assertEquals("value1", bean.get(BASIC_PROP1), "post-set check");
459 
460         // Serialize/Deserialize
461         assertThrows(NotSerializableException.class, () -> serializeDeserialize(target, "Map"));
462     }
463 
464     /**
465      * Test POJO (WrapDynaBean) serialization.
466      */
467     @Test
468     public void testSerializationPojo() throws Exception {
469         // Create LazyArrayList for DynaBeans
470         final LazyDynaList target = new LazyDynaList(pojoDynaClass);
471         final WrapDynaBean bean = (WrapDynaBean) target.get(0);
472 
473         // Set a Property
474         assertEquals("This is a string", bean.get("stringProperty"), "pre-set check");
475         bean.set("stringProperty", "value1");
476         assertEquals("value1", bean.get("stringProperty"), "post-set check");
477 
478         // Serialize/Deserialize
479         assertThrows(NotSerializableException.class, () -> serializeDeserialize(target, "POJO"));
480     }
481 
482     /**
483      * Tests toArray() if the list contains DynaBean objects.
484      */
485     @Test
486     public void testToArrayDynaBeans() {
487         final LazyDynaList list = new LazyDynaList(LazyDynaBean.class);
488         final LazyDynaBean elem = new LazyDynaBean();
489         list.add(elem);
490         final LazyDynaBean[] beans = new LazyDynaBean[1];
491         assertSame(beans, list.toArray(beans), "Wrong array");
492         assertSame(elem, beans[0], "Wrong element");
493     }
494 
495     /**
496      * Tests toArray() if the list contains maps.
497      */
498     @Test
499     public void testToArrayMapType() {
500         final LazyDynaList list = new LazyDynaList(HashMap.class);
501         final HashMap<String, Object> elem = new HashMap<>();
502         list.add(elem);
503         final Map<?, ?>[] array = new Map[1];
504         assertSame(array, list.toArray(array), "Wrong array");
505         assertEquals(elem, array[0], "Wrong element");
506     }
507 
508     /**
509      * Tests toArray() for other bean elements.
510      */
511     @Test
512     public void testToArrayOtherType() {
513         final LazyDynaList list = new LazyDynaList(TestBean.class);
514         final TestBean elem = new TestBean();
515         list.add(elem);
516         final TestBean[] array = new TestBean[1];
517         assertSame(array, list.toArray(array), "Wrong array");
518         assertEquals(elem, array[0], "Wrong element");
519     }
520 
521     /**
522      * Tests toArray() if the array's size does not fit the collection size.
523      */
524     @Test
525     public void testToArrayUnsufficientSize() {
526         final LazyDynaList list = new LazyDynaList(LazyDynaBean.class);
527         final LazyDynaBean elem = new LazyDynaBean();
528         list.add(elem);
529         final LazyDynaBean[] array = list.toArray(LazyDynaBean.EMPTY_ARRAY);
530         assertEquals(1, array.length, "Wrong array size");
531         assertEquals(elem, array[0], "Wrong element");
532     }
533 }