Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/apache/commons/beanutils/PropertyUtilsTestCase.java


1   /*
2    * Copyright 2001-2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */ 
16  
17  
18  package org.apache.commons.beanutils;
19  
20  
21  import java.beans.PropertyDescriptor;
22  import java.lang.reflect.InvocationTargetException;
23  import java.lang.reflect.Method;
24  import java.util.HashMap;
25  import java.util.List;
26  import java.util.Map;
27  
28  import org.apache.commons.beanutils.priv.PrivateBeanFactory;
29  import org.apache.commons.beanutils.priv.PrivateDirect;
30  
31  import junit.framework.TestCase;
32  import junit.framework.Test;
33  import junit.framework.TestSuite;
34  
35  
36  /**
37   * <p>Test Case for the PropertyUtils class.  The majority of these tests use
38   * instances of the TestBean class, so be sure to update the tests if you
39   * change the characteristics of that class.</p>
40   *
41   * <p>So far, this test case has tests for the following methods of the
42   * <code>PropertyUtils</code> class:</p>
43   * <ul>
44   * <li>getIndexedProperty(Object,String)</li>
45   * <li>getIndexedProperty(Object,String,int)</li>
46   * <li>getMappedProperty(Object,String)</li>
47   * <li>getMappedProperty(Object,String,String</li>
48   * <li>getNestedProperty(Object,String)</li>
49   * <li>getPropertyDescriptor(Object,String)</li>
50   * <li>getPropertyDescriptors(Object)</li>
51   * <li>getPropertyType(Object,String)</li>
52   * <li>getSimpleProperty(Object,String)</li>
53   * <li>setIndexedProperty(Object,String,Object)</li>
54   * <li>setIndexedProperty(Object,String,String,Object)</li>
55   * <li>setMappedProperty(Object,String,Object)</li>
56   * <li>setMappedProperty(Object,String,String,Object)</li>
57   * <li>setNestedProperty(Object,String,Object)</li>
58   * <li>setSimpleProperty(Object,String,Object)</li>
59   * </ul>
60   *
61   * @author Craig R. McClanahan
62   * @author Jan Sorensen
63   * @version $Revision: 1.34 $ $Date: 2004/02/28 13:18:36 $
64   */
65  
66  public class PropertyUtilsTestCase extends TestCase {
67  
68  
69      // ---------------------------------------------------- Instance Variables
70  
71  
72      /**
73       * The fully qualified class name of our private directly
74       * implemented interface.
75       */
76      private static final String PRIVATE_DIRECT_CLASS =
77              "org.apache.commons.beanutils.priv.PrivateDirect";
78  
79  
80      /**
81       * The fully qualified class name of our private indirectly
82       * implemented interface.
83       */
84      private static final String PRIVATE_INDIRECT_CLASS =
85              "org.apache.commons.beanutils.priv.PrivateIndirect";
86  
87  
88      /**
89       * The fully qualified class name of our test bean class.
90       */
91      private static final String TEST_BEAN_CLASS =
92              "org.apache.commons.beanutils.TestBean";
93  
94  
95      /**
96       * The basic test bean for each test.
97       */
98      protected TestBean bean = null;
99  
100 
101     /**
102      * The "package private subclass" test bean for each test.
103      */
104     protected TestBeanPackageSubclass beanPackageSubclass = null;
105 
106 
107     /**
108      * The test bean for private access tests.
109      */
110     protected PrivateDirect beanPrivate = null;
111 
112 
113     /**
114      * The test bean for private access tests of subclasses.
115      */
116     protected PrivateDirect beanPrivateSubclass = null;
117 
118 
119     /**
120      * The "public subclass" test bean for each test.
121      */
122     protected TestBeanPublicSubclass beanPublicSubclass = null;
123 
124 
125     /**
126      * The set of properties that should be described.
127      */
128     protected String describes[] =
129     { "booleanProperty",
130       "booleanSecond",
131       "doubleProperty",
132       "floatProperty",
133       "intArray",
134       //      "intIndexed",
135       "intProperty",
136       "listIndexed",
137       "longProperty",
138       //      "mappedObjects",
139       //      "mappedProperty",
140       //      "mappedIntProperty",
141       "nested",
142       "nullProperty",
143       //      "readOnlyProperty",
144       "shortProperty",
145       "stringArray",
146       //      "stringIndexed",
147       "stringProperty"
148     };
149 
150 
151     /**
152      * The set of property names we expect to have returned when calling
153      * <code>getPropertyDescriptors()</code>.  You should update this list
154      * when new properties are added to TestBean.
155      */
156     protected final static String[] properties = {
157         "booleanProperty",
158         "booleanSecond",
159         "doubleProperty",
160         "dupProperty",
161         "floatProperty",
162         "intArray",
163         "intIndexed",
164         "intProperty",
165         "listIndexed",
166         "longProperty",
167         "nested",
168         "nullProperty",
169         "readOnlyProperty",
170         "shortProperty",
171         "stringArray",
172         "stringIndexed",
173         "stringProperty",
174         "writeOnlyProperty",
175     };
176 
177 
178     // ---------------------------------------------------------- Constructors
179 
180 
181     /**
182      * Construct a new instance of this test case.
183      *
184      * @param name Name of the test case
185      */
186     public PropertyUtilsTestCase(String name) {
187 
188         super(name);
189 
190     }
191 
192 
193     // -------------------------------------------------- Overall Test Methods
194 
195 
196     /**
197      * Set up instance variables required by this test case.
198      */
199     public void setUp() {
200 
201         bean = new TestBean();
202         beanPackageSubclass = new TestBeanPackageSubclass();
203         beanPrivate = PrivateBeanFactory.create();
204         beanPrivateSubclass = PrivateBeanFactory.createSubclass();
205         beanPublicSubclass = new TestBeanPublicSubclass();
206 
207     }
208 
209 
210     /**
211      * Return the tests included in this test suite.
212      */
213     public static Test suite() {
214 
215         return (new TestSuite(PropertyUtilsTestCase.class));
216 
217     }
218 
219 
220     /**
221      * Tear down instance variables required by this test case.
222      */
223     public void tearDown() {
224 
225         bean = null;
226         beanPackageSubclass = null;
227         beanPrivate = null;
228         beanPrivateSubclass = null;
229         beanPublicSubclass = null;
230 
231     }
232 
233 
234 
235     // ------------------------------------------------ Individual Test Methods
236 
237 
238     /**
239      * Test copyProperties() when the origin is a a <code>Map</code>.
240      */
241     public void testCopyPropertiesMap() {
242 
243         Map map = new HashMap();
244         map.put("booleanProperty", Boolean.FALSE);
245         map.put("doubleProperty", new Double(333.0));
246         map.put("dupProperty", new String[] { "New 0", "New 1", "New 2" });
247         map.put("floatProperty", new Float((float) 222.0));
248         map.put("intArray", new int[] { 0, 100, 200 });
249         map.put("intProperty", new Integer(111));
250         map.put("longProperty", new Long(444));
251         map.put("shortProperty", new Short((short) 555));
252         map.put("stringProperty", "New String Property");
253 
254         try {
255             PropertyUtils.copyProperties(bean, map);
256         } catch (Throwable t) {
257             fail("Threw " + t.toString());
258         }
259 
260         // Scalar properties
261         assertEquals("booleanProperty", false,
262                      bean.getBooleanProperty());
263         assertEquals("doubleProperty", 333.0,
264                      bean.getDoubleProperty(), 0.005);
265         assertEquals("floatProperty", (float) 222.0,
266                      bean.getFloatProperty(), (float) 0.005);
267         assertEquals("intProperty", 111,
268                      bean.getIntProperty());
269         assertEquals("longProperty", (long) 444,
270                      bean.getLongProperty());
271         assertEquals("shortProperty", (short) 555,
272                      bean.getShortProperty());
273         assertEquals("stringProperty", "New String Property",
274                      bean.getStringProperty());
275                      
276         // Indexed Properties
277         String dupProperty[] = bean.getDupProperty();
278         assertNotNull("dupProperty present", dupProperty);
279         assertEquals("dupProperty length", 3, dupProperty.length);
280         assertEquals("dupProperty[0]", "New 0", dupProperty[0]);
281         assertEquals("dupProperty[1]", "New 1", dupProperty[1]);
282         assertEquals("dupProperty[2]", "New 2", dupProperty[2]);
283         int intArray[] = bean.getIntArray();
284         assertNotNull("intArray present", intArray);
285         assertEquals("intArray length", 3, intArray.length);
286         assertEquals("intArray[0]", 0, intArray[0]);
287         assertEquals("intArray[1]", 100, intArray[1]);
288         assertEquals("intArray[2]", 200, intArray[2]);
289 
290     }
291 
292 
293     /**
294      * Test the describe() method.
295      */
296     public void testDescribe() {
297 
298         Map map = null;
299         try {
300             map = PropertyUtils.describe(bean);
301         } catch (Exception e) {
302             fail("Threw exception " + e);
303         }
304 
305         // Verify existence of all the properties that should be present
306         for (int i = 0; i < describes.length; i++) {
307             assertTrue("Property '" + describes[i] + "' is present",
308                        map.containsKey(describes[i]));
309         }
310         assertTrue("Property 'writeOnlyProperty' is not present",
311                    !map.containsKey("writeOnlyProperty"));
312 
313         // Verify the values of scalar properties
314         assertEquals("Value of 'booleanProperty'",
315                      Boolean.TRUE,
316                      (Boolean) map.get("booleanProperty"));
317         assertEquals("Value of 'doubleProperty'",
318                      new Double(321.0),
319                      (Double) map.get("doubleProperty"));
320         assertEquals("Value of 'floatProperty'",
321                      new Float((float) 123.0),
322                      (Float) map.get("floatProperty"));
323         assertEquals("Value of 'intProperty'",
324                      new Integer(123),
325                      (Integer) map.get("intProperty"));
326         assertEquals("Value of 'longProperty'",
327                      new Long(321),
328                      (Long) map.get("longProperty"));
329         assertEquals("Value of 'shortProperty'",
330                      new Short((short) 987),
331                      (Short) map.get("shortProperty"));
332         assertEquals("Value of 'stringProperty'",
333                      "This is a string",
334                      (String) map.get("stringProperty"));
335 
336     }
337 
338 
339     /**
340      * Corner cases on getPropertyDescriptor invalid arguments.
341      */
342     public void testGetDescriptorArguments() {
343 
344         try {
345             PropertyUtils.getPropertyDescriptor(null, "stringProperty");
346             fail("Should throw IllegalArgumentException 1");
347         } catch (IllegalArgumentException e) {
348             ; // Expected response
349         } catch (Throwable t) {
350             fail("Threw " + t + " instead of IllegalArgumentException 1");
351         }
352 
353         try {
354             PropertyUtils.getPropertyDescriptor(bean, null);
355             fail("Should throw IllegalArgumentException 2");
356         } catch (IllegalArgumentException e) {
357             ; // Expected response
358         } catch (Throwable t) {
359             fail("Threw " + t + " instead of IllegalArgumentException 2");
360         }
361 
362     }
363 
364 
365     /**
366      * Positive getPropertyDescriptor on property <code>booleanProperty</code>.
367      */
368     public void testGetDescriptorBoolean() {
369 
370         testGetDescriptorBase("booleanProperty", "getBooleanProperty",
371                 "setBooleanProperty");
372 
373     }
374 
375 
376     /**
377      * Positive getPropertyDescriptor on property <code>doubleProperty</code>.
378      */
379     public void testGetDescriptorDouble() {
380 
381         testGetDescriptorBase("doubleProperty", "getDoubleProperty",
382                 "setDoubleProperty");
383 
384     }
385 
386 
387     /**
388      * Positive getPropertyDescriptor on property <code>floatProperty</code>.
389      */
390     public void testGetDescriptorFloat() {
391 
392         testGetDescriptorBase("floatProperty", "getFloatProperty",
393                 "setFloatProperty");
394 
395     }
396 
397 
398     /**
399      * Positive getPropertyDescriptor on property <code>intProperty</code>.
400      */
401     public void testGetDescriptorInt() {
402 
403         testGetDescriptorBase("intProperty", "getIntProperty",
404                 "setIntProperty");
405 
406     }
407 
408 
409     /**
410      * <p>Negative tests on an invalid property with two different boolean
411      * getters (which is fine, according to the JavaBeans spec) but a
412      * String setter instead of a boolean setter.</p>
413      *
414      * <p>Although one could logically argue that this combination of method
415      * signatures should not identify a property at all, there is a sentence
416      * in Section 8.3.1 making it clear that the behavior tested for here
417      * is correct:  "If we find only one of these methods, then we regard
418      * it as defining either a read-only or write-only property called
419      * <em>&lt;property-name&gt;</em>.</p>
420      */
421     public void testGetDescriptorInvalidBoolean() throws Exception {
422 
423   PropertyDescriptor pd =
424       PropertyUtils.getPropertyDescriptor(bean, "invalidBoolean");
425   assertNotNull("invalidBoolean is a property", pd);
426   assertNotNull("invalidBoolean has a getter method",
427           pd.getReadMethod());
428   assertNull("invalidBoolean has no write method",
429        pd.getWriteMethod());
430   assertTrue("invalidBoolean getter method is isInvalidBoolean",
431        "isInvalidBoolean".equals(pd.getReadMethod().getName()));
432 
433     }
434 
435 
436     /**
437      * Positive getPropertyDescriptor on property <code>longProperty</code>.
438      */
439     public void testGetDescriptorLong() {
440 
441         testGetDescriptorBase("longProperty", "getLongProperty",
442                 "setLongProperty");
443 
444     }
445 
446 
447     /**
448      * Positive getPropertyDescriptor on property
449      * <code>readOnlyProperty</code>.
450      */
451     public void testGetDescriptorReadOnly() {
452 
453         testGetDescriptorBase("readOnlyProperty", "getReadOnlyProperty",
454                 null);
455 
456     }
457 
458 
459     /**
460      * Positive getPropertyDescriptor on property <code>booleanSecond</code>
461      * that uses an "is" method as the getter.
462      */
463     public void testGetDescriptorSecond() {
464 
465         testGetDescriptorBase("booleanSecond", "isBooleanSecond",
466                 "setBooleanSecond");
467 
468     }
469 
470 
471     /**
472      * Positive getPropertyDescriptor on property <code>shortProperty</code>.
473      */
474     public void testGetDescriptorShort() {
475 
476         testGetDescriptorBase("shortProperty", "getShortProperty",
477                 "setShortProperty");
478 
479     }
480 
481 
482     /**
483      * Positive getPropertyDescriptor on property <code>stringProperty</code>.
484      */
485     public void testGetDescriptorString() {
486 
487         testGetDescriptorBase("stringProperty", "getStringProperty",
488                 "setStringProperty");
489 
490     }
491 
492 
493     /**
494      * Negative getPropertyDescriptor on property <code>unknown</code>.
495      */
496     public void testGetDescriptorUnknown() {
497 
498         testGetDescriptorBase("unknown", null, null);
499 
500     }
501 
502 
503     /**
504      * Positive getPropertyDescriptor on property
505      * <code>writeOnlyProperty</code>.
506      */
507     public void testGetDescriptorWriteOnly() {
508 
509         testGetDescriptorBase("writeOnlyProperty", null,
510                 "setWriteOnlyProperty");
511 
512     }
513 
514 
515     /**
516      * Positive test for getPropertyDescriptors().  Each property name
517      * listed in <code>properties</code> should be returned exactly once.
518      */
519     public void testGetDescriptors() {
520 
521         PropertyDescriptor pd[] =
522                 PropertyUtils.getPropertyDescriptors(bean);
523         assertNotNull("Got descriptors", pd);
524         int count[] = new int[properties.length];
525         for (int i = 0; i < pd.length; i++) {
526             String name = pd[i].getName();
527             for (int j = 0; j < properties.length; j++) {
528                 if (name.equals(properties[j]))
529                     count[j]++;
530             }
531         }
532         for (int j = 0; j < properties.length; j++) {
533             if (count[j] < 0)
534                 fail("Missing property " + properties[j]);
535             else if (count[j] > 1)
536                 fail("Duplicate property " + properties[j]);
537         }
538 
539     }
540 
541 
542     /**
543      * Corner cases on getPropertyDescriptors invalid arguments.
544      */
545     public void testGetDescriptorsArguments() {
546 
547         try {
548             PropertyUtils.getPropertyDescriptors(null);
549             fail("Should throw IllegalArgumentException");
550         } catch (IllegalArgumentException e) {
551             ; // Expected response
552         } catch (Throwable t) {
553             fail("Threw " + t + " instead of IllegalArgumentException");
554         }
555 
556     }
557 
558 
559     /**
560      * Corner cases on getIndexedProperty invalid arguments.
561      */
562     public void testGetIndexedArguments() {
563 
564         // Use explicit index argument
565 
566         try {
567             PropertyUtils.getIndexedProperty(null, "intArray", 0);
568             fail("Should throw IllegalArgumentException 1");
569         } catch (IllegalArgumentException e) {
570             ; // Expected response
571         } catch (Throwable t) {
572             fail("Threw " + t + " instead of IllegalArgumentException 1");
573         }
574 
575         try {
576             PropertyUtils.getIndexedProperty(bean, null, 0);
577             fail("Should throw IllegalArgumentException 2");
578         } catch (IllegalArgumentException e) {
579             ; // Expected response
580         } catch (Throwable t) {
581             fail("Threw " + t + " instead of IllegalArgumentException 2");
582         }
583 
584         // Use index expression
585 
586         try {
587             PropertyUtils.getIndexedProperty(null,
588                     "intArray[0]");
589             fail("Should throw IllegalArgumentException 3");
590         } catch (IllegalArgumentException e) {
591             ; // Expected response
592         } catch (Throwable t) {
593             fail("Threw " + t + " instead of IllegalArgumentException 3");
594         }
595 
596         try {
597             PropertyUtils.getIndexedProperty(bean, "[0]");
598             fail("Should throw NoSuchMethodException 4");
599         } catch (NoSuchMethodException e) {
600             ; // Expected response
601         } catch (Throwable t) {
602             fail("Threw " + t + " instead of NoSuchMethodException 4");
603         }
604 
605         try {
606             PropertyUtils.getIndexedProperty(bean, "intArray");
607             fail("Should throw IllegalArgumentException 5");
608         } catch (IllegalArgumentException e) {
609             ; // Expected response
610         } catch (Throwable t) {
611             fail("Threw " + t + " instead of IllegalArgumentException 5");
612         }
613 
614         // Use explicit index argument
615 
616         try {
617             PropertyUtils.getIndexedProperty(null, "intIndexed", 0);
618             fail("Should throw IllegalArgumentException 1");
619         } catch (IllegalArgumentException e) {
620             ; // Expected response
621         } catch (Throwable t) {
622             fail("Threw " + t + " instead of IllegalArgumentException 1");
623         }
624 
625         try {
626             PropertyUtils.getIndexedProperty(bean, null, 0);
627             fail("Should throw IllegalArgumentException 2");
628         } catch (IllegalArgumentException e) {
629             ; // Expected response
630         } catch (Throwable t) {
631             fail("Threw " + t + " instead of IllegalArgumentException 2");
632         }
633 
634         // Use index expression
635 
636         try {
637             PropertyUtils.getIndexedProperty(null,
638                     "intIndexed[0]");
639             fail("Should throw IllegalArgumentException 3");
640         } catch (IllegalArgumentException e) {
641             ; // Expected response
642         } catch (Throwable t) {
643             fail("Threw " + t + " instead of IllegalArgumentException 3");
644         }
645 
646         try {
647             PropertyUtils.getIndexedProperty(bean, "[0]");
648             fail("Should throw NoSuchMethodException 4");
649         } catch (NoSuchMethodException e) {
650             ; // Expected response
651         } catch (Throwable t) {
652             fail("Threw " + t + " instead of NoSuchMethodException 4");
653         }
654 
655         try {
656             PropertyUtils.getIndexedProperty(bean, "intIndexed");
657             fail("Should throw IllegalArgumentException 5");
658         } catch (IllegalArgumentException e) {
659             ; // Expected response
660         } catch (Throwable t) {
661             fail("Threw " + t + " instead of IllegalArgumentException 5");
662         }
663 
664     }
665 
666 
667     /**
668      * Positive and negative tests on getIndexedProperty valid arguments.
669      */
670     public void testGetIndexedValues() {
671 
672         Object value = null;
673 
674         // Use explicit key argument
675 
676         for (int i = 0; i < 5; i++) {
677 
678             try {
679                 value = PropertyUtils.getIndexedProperty
680                     (bean, "dupProperty", i);
681                 assertNotNull("dupProperty returned value " + i, value);
682                 assertTrue("dupProperty returned String " + i,
683                         value instanceof String);
684                 assertEquals("dupProperty returned correct " + i,
685                              "Dup " + i,
686                              (String) value);
687             } catch (Throwable t) {
688                 fail("dupProperty " + i + " threw " + t);
689             }
690 
691             try {
692                 value =
693                         PropertyUtils.getIndexedProperty(bean, "intArray", i);
694                 assertNotNull("intArray returned value " + i, value);
695                 assertTrue("intArray returned Integer " + i,
696                         value instanceof Integer);
697                 assertEquals("intArray returned correct " + i, i * 10,
698                         ((Integer) value).intValue());
699             } catch (Throwable t) {
700                 fail("intArray " + i + " threw " + t);
701             }
702 
703             try {
704                 value =
705                         PropertyUtils.getIndexedProperty(bean, "intIndexed", i);
706                 assertNotNull("intIndexed returned value " + i, value);
707                 assertTrue("intIndexed returned Integer " + i,
708                         value instanceof Integer);
709                 assertEquals("intIndexed returned correct " + i, i * 10,
710                         ((Integer) value).intValue());
711             } catch (Throwable t) {
712                 fail("intIndexed " + i + " threw " + t);
713             }
714 
715             try {
716                 value =
717                         PropertyUtils.getIndexedProperty(bean, "listIndexed", i);
718                 assertNotNull("listIndexed returned value " + i, value);
719                 assertTrue("list returned String " + i,
720                         value instanceof String);
721                 assertEquals("listIndexed returned correct " + i,
722                         "String " + i, (String) value);
723             } catch (Throwable t) {
724                 fail("listIndexed " + i + " threw " + t);
725             }
726 
727             try {
728                 value =
729                         PropertyUtils.getIndexedProperty(bean, "stringArray", i);
730                 assertNotNull("stringArray returned value " + i, value);
731                 assertTrue("stringArray returned String " + i,
732                         value instanceof String);
733                 assertEquals("stringArray returned correct " + i,
734                         "String " + i, (String) value);
735             } catch (Throwable t) {
736                 fail("stringArray " + i + " threw " + t);
737             }
738 
739             try {
740                 value =
741                         PropertyUtils.getIndexedProperty(bean, "stringIndexed", i);
742                 assertNotNull("stringIndexed returned value " + i, value);
743                 assertTrue("stringIndexed returned String " + i,
744                         value instanceof String);
745                 assertEquals("stringIndexed returned correct " + i,
746                         "String " + i, (String) value);
747             } catch (Throwable t) {
748                 fail("stringIndexed " + i + " threw " + t);
749             }
750 
751         }
752 
753         // Use key expression
754 
755         for (int i = 0; i < 5; i++) {
756 
757             try {
758                 value = PropertyUtils.getIndexedProperty
759                     (bean, "dupProperty[" + i + "]");
760                 assertNotNull("dupProperty returned value " + i, value);
761                 assertTrue("dupProperty returned String " + i,
762                         value instanceof String);
763                 assertEquals("dupProperty returned correct " + i,
764                              "Dup " + i,
765                              (String) value);
766             } catch (Throwable t) {
767                 fail("dupProperty " + i + " threw " + t);
768             }
769 
770             try {
771                 value =
772                         PropertyUtils.getIndexedProperty(bean,
773                                 "intArray[" + i + "]");
774                 assertNotNull("intArray returned value " + i, value);
775                 assertTrue("intArray returned Integer " + i,
776                         value instanceof Integer);
777                 assertEquals("intArray returned correct " + i, i * 10,
778                         ((Integer) value).intValue());
779             } catch (Throwable t) {
780                 fail("intArray " + i + " threw " + t);
781             }
782 
783             try {
784                 value =
785                         PropertyUtils.getIndexedProperty(bean,
786                                 "intIndexed[" + i + "]");
787                 assertNotNull("intIndexed returned value " + i, value);
788                 assertTrue("intIndexed returned Integer " + i,
789                         value instanceof Integer);
790                 assertEquals("intIndexed returned correct " + i, i * 10,
791                         ((Integer) value).intValue());
792             } catch (Throwable t) {
793                 fail("intIndexed " + i + " threw " + t);
794             }
795 
796             try {
797                 value =
798                         PropertyUtils.getIndexedProperty(bean,
799                                 "listIndexed[" + i + "]");
800                 assertNotNull("listIndexed returned value " + i, value);
801                 assertTrue("listIndexed returned String " + i,
802                         value instanceof String);
803                 assertEquals("listIndexed returned correct " + i,
804                         "String " + i, (String) value);
805             } catch (Throwable t) {
806                 fail("listIndexed " + i + " threw " + t);
807             }
808 
809             try {
810                 value =
811                         PropertyUtils.getIndexedProperty(bean,
812                                 "stringArray[" + i + "]");
813                 assertNotNull("stringArray returned value " + i, value);
814                 assertTrue("stringArray returned String " + i,
815                         value instanceof String);
816                 assertEquals("stringArray returned correct " + i,
817                         "String " + i, (String) value);
818             } catch (Throwable t) {
819                 fail("stringArray " + i + " threw " + t);
820             }
821 
822             try {
823                 value =
824                         PropertyUtils.getIndexedProperty(bean,
825                                 "stringIndexed[" + i + "]");
826                 assertNotNull("stringIndexed returned value " + i, value);
827                 assertTrue("stringIndexed returned String " + i,
828                         value instanceof String);
829                 assertEquals("stringIndexed returned correct " + i,
830                         "String " + i, (String) value);
831             } catch (Throwable t) {
832                 fail("stringIndexed " + i + " threw " + t);
833             }
834 
835         }
836 
837         // Index out of bounds tests
838 
839         try {
840             value =
841                     PropertyUtils.getIndexedProperty(bean,
842                             "dupProperty", -1);
843             fail("Should have thrown ArrayIndexOutOfBoundsException");
844         } catch (ArrayIndexOutOfBoundsException t) {
845             ; // Expected results
846         } catch (Throwable t) {
847             fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
848         }
849 
850         try {
851             value =
852                     PropertyUtils.getIndexedProperty(bean,
853                             "dupProperty", 5);
854             fail("Should have thrown ArrayIndexOutOfBoundsException");
855         } catch (ArrayIndexOutOfBoundsException t) {
856             ; // Expected results
857         } catch (Throwable t) {
858             fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
859         }
860 
861         try {
862             value =
863                     PropertyUtils.getIndexedProperty(bean,
864                             "intArray", -1);
865             fail("Should have thrown ArrayIndexOutOfBoundsException");
866         } catch (ArrayIndexOutOfBoundsException t) {
867             ; // Expected results
868         } catch (Throwable t) {
869             fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
870         }
871 
872         try {
873             value =
874                     PropertyUtils.getIndexedProperty(bean,
875                             "intArray", 5);
876             fail("Should have thrown ArrayIndexOutOfBoundsException");
877         } catch (ArrayIndexOutOfBoundsException t) {
878             ; // Expected results
879         } catch (Throwable t) {
880             fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
881         }
882 
883         try {
884             value =
885                     PropertyUtils.getIndexedProperty(bean,
886                             "intIndexed", -1);
887             fail("Should have thrown ArrayIndexOutOfBoundsException");
888         } catch (ArrayIndexOutOfBoundsException t) {
889             ; // Expected results
890         } catch (Throwable t) {
891             fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
892         }
893 
894         try {
895             value =
896                     PropertyUtils.getIndexedProperty(bean,
897                             "intIndexed", 5);
898             fail("Should have thrown ArrayIndexOutOfBoundsException");
899         } catch (ArrayIndexOutOfBoundsException t) {
900             ; // Expected results
901         } catch (Throwable t) {
902             fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
903         }
904 
905         try {
906             value =
907                     PropertyUtils.getIndexedProperty(bean,
908                             "listIndexed", -1);
909             fail("Should have thrown IndexOutOfBoundsException");
910         } catch (IndexOutOfBoundsException t) {
911             ; // Expected results
912         } catch (Throwable t) {
913             fail("Threw " + t + " instead of IndexOutOfBoundsException");
914         }
915 
916         try {
917             value =
918                     PropertyUtils.getIndexedProperty(bean,
919                             "listIndexed", 5);
920             fail("Should have thrown IndexOutOfBoundsException");
921         } catch (IndexOutOfBoundsException t) {
922             ; // Expected results
923         } catch (Throwable t) {
924             fail("Threw " + t + " instead of IndexOutOfBoundsException");
925         }
926 
927         try {
928             value =
929                     PropertyUtils.getIndexedProperty(bean,
930                             "stringArray", -1);
931             fail("Should have thrown ArrayIndexOutOfBoundsException");
932         } catch (ArrayIndexOutOfBoundsException t) {
933             ; // Expected results
934         } catch (Throwable t) {
935             fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
936         }
937 
938         try {
939             value =
940                     PropertyUtils.getIndexedProperty(bean,
941                             "stringArray", 5);
942             fail("Should have thrown ArrayIndexOutOfBoundsException");
943         } catch (ArrayIndexOutOfBoundsException t) {
944             ; // Expected results
945         } catch (Throwable t) {
946             fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
947         }
948 
949         try {
950             value =
951                     PropertyUtils.getIndexedProperty(bean,
952                             "stringIndexed", -1);
953             fail("Should have thrown ArrayIndexOutOfBoundsException");
954         } catch (ArrayIndexOutOfBoundsException t) {
955             ; // Expected results
956         } catch (Throwable t) {
957             fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
958         }
959 
960         try {
961             value =
962                     PropertyUtils.getIndexedProperty(bean,
963                             "stringIndexed", 5);
964             fail("Should have thrown ArrayIndexOutOfBoundsException");
965         } catch (ArrayIndexOutOfBoundsException t) {
966             ; // Expected results
967         } catch (Throwable t) {
968             fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
969         }
970 
971     }
972 
973 
974     /**
975      * Corner cases on getMappedProperty invalid arguments.
976      */
977     public void testGetMappedArguments() {
978 
979         // Use explicit key argument
980 
981         try {
982             PropertyUtils.getMappedProperty(null, "mappedProperty",
983                     "First Key");
984             fail("Should throw IllegalArgumentException 1");
985         } catch (IllegalArgumentException e) {
986             ; // Expected response
987         } catch (Throwable t) {
988             fail("Threw " + t + " instead of IllegalArgumentException 1");
989         }
990 
991         try {
992             PropertyUtils.getMappedProperty(bean, null, "First Key");
993             fail("Should throw IllegalArgumentException 2");
994         } catch (IllegalArgumentException e) {
995             ; // Expected response
996         } catch (Throwable t) {
997             fail("Threw " + t + " instead of IllegalArgumentException 2");
998         }
999 
1000        try {
1001            PropertyUtils.getMappedProperty(bean, "mappedProperty", null);
1002            fail("Should throw IllegalArgumentException 3");
1003        } catch (IllegalArgumentException e) {
1004            ; // Expected response
1005        } catch (Throwable t) {
1006            fail("Threw " + t + " instead of IllegalArgumentException 3");
1007        }
1008
1009        // Use key expression
1010
1011        try {
1012            PropertyUtils.getMappedProperty(null,
1013                    "mappedProperty(First Key)");
1014            fail("Should throw IllegalArgumentException 4");
1015        } catch (IllegalArgumentException e) {
1016            ; // Expected response
1017        } catch (Throwable t) {
1018            fail("Threw " + t + " instead of IllegalArgumentException 4");
1019        }
1020
1021        try {
1022            PropertyUtils.getMappedProperty(bean, "(Second Key)");
1023            fail("Should throw IllegalArgumentException 5");
1024        } catch (NoSuchMethodException e) {
1025            ; // Expected response
1026        } catch (Throwable t) {
1027            fail("Threw " + t + " instead of NoSuchMethodException 5");
1028        }
1029
1030        try {
1031            PropertyUtils.getMappedProperty(bean, "mappedProperty");
1032            fail("Should throw IllegalArgumentException 6");
1033        } catch (IllegalArgumentException e) {
1034            ; // Expected response
1035        } catch (Throwable t) {
1036            fail("Threw " + t + " instead of IllegalArgumentException 6");
1037        }
1038
1039    }
1040
1041
1042    /**
1043     * Test getting mapped values with periods in the key.
1044     */
1045    public void testGetMappedPeriods() {
1046
1047        bean.setMappedProperty("key.with.a.dot", "Special Value");
1048        assertEquals("Can retrieve directly",
1049                     "Special Value",
1050                     bean.getMappedProperty("key.with.a.dot"));
1051        try {
1052            assertEquals("Can retrieve via getMappedProperty",
1053                         "Special Value",
1054                         PropertyUtils.getMappedProperty
1055                         (bean, "mappedProperty", "key.with.a.dot"));
1056        } catch (Exception e) {
1057            fail("Thew exception: " + e);
1058        }
1059        try {
1060            assertEquals("Can retrieve via getNestedProperty",
1061                         "Special Value",
1062                         PropertyUtils.getNestedProperty
1063                         (bean, "mappedProperty(key.with.a.dot)"));
1064        } catch (Exception e) {
1065            fail("Thew exception: " + e);
1066        }
1067
1068        bean.setMappedObjects("nested.property", new TestBean());
1069        assertNotNull("Can retrieve directly",
1070                      bean.getMappedObjects("nested.property"));
1071        try {
1072            assertEquals("Can retrieve nested",
1073                         "This is a string",
1074                         PropertyUtils.getNestedProperty
1075                         (bean,
1076                          "mappedObjects(nested.property).stringProperty"));
1077        } catch (Exception e) {
1078            fail("Thew exception: " + e);
1079        }
1080
1081        try 
1082        {
1083            assertEquals("Can't retrieved nested with mapped property",
1084                         "Mapped Value",
1085                         PropertyUtils.getNestedProperty(
1086                             bean,"mappedNested.value(Mapped Key)"));
1087        } catch (Exception e) 
1088        {
1089            fail("Thew exception: " + e);
1090        } 
1091    }
1092
1093
1094    /**
1095     * Test getting mapped values with slashes in the key.  This is different
1096     * from periods because slashes are not syntactically significant.
1097     */
1098    public void testGetMappedSlashes() {
1099
1100        bean.setMappedProperty("key/with/a/slash", "Special Value");
1101        assertEquals("Can retrieve directly",
1102                     "Special Value",
1103                     bean.getMappedProperty("key/with/a/slash"));
1104        try {
1105            assertEquals("Can retrieve via getMappedProperty",
1106                         "Special Value",
1107                         PropertyUtils.getMappedProperty
1108                         (bean, "mappedProperty", "key/with/a/slash"));
1109        } catch (Exception e) {
1110            fail("Thew exception: " + e);
1111        }
1112        try {
1113            assertEquals("Can retrieve via getNestedProperty",
1114                         "Special Value",
1115                         PropertyUtils.getNestedProperty
1116                         (bean, "mappedProperty(key/with/a/slash)"));
1117        } catch (Exception e) {
1118            fail("Thew exception: " + e);
1119        }
1120
1121        bean.setMappedObjects("nested/property", new TestBean());
1122        assertNotNull("Can retrieve directly",
1123                      bean.getMappedObjects("nested/property"));
1124        try {
1125            assertEquals("Can retrieve nested",
1126                         "This is a string",
1127                         PropertyUtils.getNestedProperty
1128                         (bean,
1129                          "mappedObjects(nested/property).stringProperty"));
1130        } catch (Exception e) {
1131            fail("Thew exception: " + e);
1132        }
1133
1134    }
1135
1136
1137    /**
1138     * Positive and negative tests on getMappedProperty valid arguments.
1139     */
1140    public void testGetMappedValues() {
1141
1142        Object value = null;
1143
1144        // Use explicit key argument
1145
1146        try {
1147            value = PropertyUtils.getMappedProperty(bean, "mappedProperty",
1148                    "First Key");
1149            assertEquals("Can find first value", "First Value", value);
1150        } catch (Throwable t) {
1151            fail("Finding first value threw " + t);
1152        }
1153
1154        try {
1155            value = PropertyUtils.getMappedProperty(bean, "mappedProperty",
1156                    "Second Key");
1157            assertEquals("Can find second value", "Second Value", value);
1158        } catch (Throwable t) {
1159            fail("Finding second value threw " + t);
1160        }
1161
1162        try {
1163            value = PropertyUtils.getMappedProperty(bean, "mappedProperty",
1164                    "Third Key");
1165            assertNull("Can not find third value", value);
1166        } catch (Throwable t) {
1167            fail("Finding third value threw " + t);
1168        }
1169
1170        // Use key expression with parentheses
1171
1172        try {
1173            value =
1174                    PropertyUtils.getMappedProperty(bean,
1175                            "mappedProperty(First Key)");
1176            assertEquals("Can find first value", "First Value", value);
1177        } catch (Throwable t) {
1178            fail("Finding first value threw " + t);
1179        }
1180
1181        try {
1182            value =
1183                    PropertyUtils.getMappedProperty(bean,
1184                            "mappedProperty(Second Key)");
1185            assertEquals("Can find second value", "Second Value", value);
1186        } catch (Throwable t) {
1187            fail("Finding second value threw " + t);
1188        }
1189
1190        try {
1191            value =
1192                    PropertyUtils.getMappedProperty(bean,
1193                            "mappedProperty(Third Key)");
1194            assertNull("Can not find third value", value);
1195        } catch (Throwable t) {
1196            fail("Finding third value threw " + t);
1197        }
1198
1199        // Use key expression with dotted syntax
1200
1201        try {
1202            value =
1203                    PropertyUtils.getNestedProperty(bean,
1204                            "mapProperty.First Key");
1205            assertEquals("Can find first value", "First Value", value);
1206        } catch (Throwable t) {
1207            fail("Finding first value threw " + t);
1208        }
1209
1210        try {
1211            value =
1212                    PropertyUtils.getNestedProperty(bean,
1213                            "mapProperty.Second Key");
1214            assertEquals("Can find second value", "Second Value", value);
1215        } catch (Throwable t) {
1216            fail("Finding second value threw " + t);
1217        }
1218
1219        try {
1220            value =
1221                    PropertyUtils.getNestedProperty(bean,
1222                            "mapProperty.Third Key");
1223            assertNull("Can not find third value", value);
1224        } catch (Throwable t) {
1225            fail("Finding third value threw " + t);
1226        }
1227
1228    }
1229
1230
1231    /**
1232     * Corner cases on getNestedProperty invalid arguments.
1233     */
1234    public void testGetNestedArguments() {
1235
1236        try {
1237            PropertyUtils.getNestedProperty(null, "stringProperty");
1238            fail("Should throw IllegalArgumentException 1");
1239        } catch (IllegalArgumentException e) {
1240            ; // Expected response
1241        } catch (Throwable t) {
1242            fail("Threw " + t + " instead of IllegalArgumentException 1");
1243        }
1244
1245        try {
1246            PropertyUtils.getNestedProperty(bean, null);
1247            fail("Should throw IllegalArgumentException 2");
1248        } catch (IllegalArgumentException e) {
1249            ; // Expected response
1250        } catch (Throwable t) {
1251            fail("Threw " + t + " instead of IllegalArgumentException 2");
1252        }
1253
1254    }
1255
1256
1257    /**
1258     * Test getNestedProperty on a boolean property.
1259     */
1260    public void testGetNestedBoolean() {
1261
1262        try {
1263            Object value =
1264                    PropertyUtils.getNestedProperty
1265                    (bean, "nested.booleanProperty");
1266            assertNotNull("Got a value", value);
1267            assertTrue("Got correct type", (value instanceof Boolean));
1268            assertTrue("Got correct value",
1269                    ((Boolean) value).booleanValue() ==
1270                    bean.getNested().getBooleanProperty());
1271        } catch (IllegalAccessException e) {
1272            fail("IllegalAccessException");
1273        } catch (IllegalArgumentException e) {
1274            fail("IllegalArgumentException");
1275        } catch (InvocationTargetException e) {
1276            fail("InvocationTargetException");
1277        } catch (NoSuchMethodException e) {
1278            fail("NoSuchMethodException");
1279        }
1280
1281    }
1282
1283
1284    /**
1285     * Test getNestedProperty on a double property.
1286     */
1287    public void testGetNestedDouble() {
1288
1289        try {
1290            Object value =
1291                    PropertyUtils.getNestedProperty