/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.commons.beanutils2;

import java.lang.reflect.InvocationTargetException;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.StringTokenizer;

import org.apache.commons.beanutils2.converters.ArrayConverter;
import org.apache.commons.beanutils2.converters.DateConverter;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

/**
 * <p>
 *  Test Case for the BeanUtils class.  The majority of these tests use
 *  instances of the TestBean class, so be sure to update the tests if you
 *  change the characteristics of that class.
 * </p>
 *
 * <p>
 *  Template for this stolen from Craigs PropertyUtilsTestCase
 * </p>
 *
 * <p>
 *   Note that the tests are dependant upon the static aspects
 *   (such as array sizes...) of the TestBean.java class, so ensure
 *   than all changes to TestBean are reflected here.
 * </p>
 *
 * <p>
 *  So far, this test case has tests for the following methods of the
 *  {@code BeanUtils} class:
 * </p>
 * <ul>
 *   <li>getArrayProperty(Object bean, String name)</li>
 * </ul>
 *
 */

public class BeanUtilsTestCase extends TestCase {



    /**
     * The test bean for each test.
     */
    protected TestBean bean = null;

    /**
     * The set of properties that should be described.
     */
    protected String describes[] =
    { "booleanProperty",
      "booleanSecond",
      "byteProperty",
      "doubleProperty",
      "dupProperty",
      "floatProperty",
      "intArray",
      //      "intIndexed",
      "longProperty",
      "listIndexed",
      "longProperty",
      //      "mappedProperty",
      //      "mappedIntProperty",
      "nested",
      "nullProperty",
      "readOnlyProperty",
      "shortProperty",
      "stringArray",
      //      "stringIndexed",
      "stringProperty"
    };

    /** Test Calendar value */
    protected java.util.Calendar testCalendar;

    /** Test java.util.Date value */
    protected java.util.Date testUtilDate;

    /** Test String Date value */
    protected String testStringDate;



    /**
     * Construct a new instance of this test case.
     *
     * @param name Name of the test case
     */
    public BeanUtilsTestCase(final String name) {
        super(name);
    }



    /**
     * Set up instance variables required by this test case.
     */
    @Override
    public void setUp() {
        ConvertUtils.deregister();
        BeanUtilsBean.setInstance(new BeanUtilsBean());
        setUpShared();
    }

    /**
     * Shared Set up.
     */
    protected void setUpShared() {
        bean = new TestBean();

        final DateConverter dateConverter = new DateConverter(null);
        dateConverter.setLocale(Locale.US);
        dateConverter.setPattern("dd.MM.yyyy");
        ConvertUtils.register(dateConverter, java.util.Date.class);

        final ArrayConverter dateArrayConverter =
            new ArrayConverter(java.util.Date[].class, dateConverter, 0);
        ConvertUtils.register(dateArrayConverter, java.util.Date[].class);

        testCalendar = Calendar.getInstance();
        testCalendar.set(1992, 11, 28, 0, 0, 0);
        testCalendar.set(Calendar.MILLISECOND, 0);
        testUtilDate = testCalendar.getTime();
        testStringDate = "28.12.1992";
    }

    /**
     * Return the tests included in this test suite.
     */
    public static Test suite() {
        return new TestSuite(BeanUtilsTestCase.class);
    }

    /**
     * Tear down instance variables required by this test case.
     */
    @Override
    public void tearDown() {
        bean = null;
    }



    /**
     * Test the copyProperties() method from a DynaBean.
     */
    public void testCopyPropertiesDynaBean() {

        // Set up an origin bean with customized properties
        final DynaClass dynaClass = DynaBeanUtilsTestCase.createDynaClass();
        DynaBean orig = null;
        try {
            orig = dynaClass.newInstance();
        } catch (final Exception e) {
            fail("newInstance(): " + e);
        }
        orig.set("booleanProperty", Boolean.FALSE);
        orig.set("byteProperty", new Byte((byte) 111));
        orig.set("doubleProperty", new Double(333.33));
        orig.set("dupProperty",
                 new String[] { "New 0", "New 1", "New 2" });
        orig.set("intArray", new int[] { 100, 200, 300 });
        orig.set("intProperty", new Integer(333));
        orig.set("longProperty", new Long(3333));
        orig.set("shortProperty", new Short((short) 33));
        orig.set("stringArray", new String[] { "New 0", "New 1" });
        orig.set("stringProperty", "Custom string");

        // Copy the origin bean to our destination test bean
        try {
            BeanUtils.copyProperties(bean, orig);
        } catch (final Exception e) {
            fail("Threw exception: " + e);
        }

        // Validate the results for scalar properties
        assertEquals("Copied boolean property",
                     false,
                     bean.getBooleanProperty());
        assertEquals("Copied byte property",
                     (byte) 111,
                     bean.getByteProperty());
        assertEquals("Copied double property",
                     333.33,
                     bean.getDoubleProperty(),
                     0.005);
        assertEquals("Copied int property",
                     333,
                     bean.getIntProperty());
        assertEquals("Copied long property",
                     3333,
                     bean.getLongProperty());
        assertEquals("Copied short property",
                     (short) 33,
                     bean.getShortProperty());
        assertEquals("Copied string property",
                     "Custom string",
                     bean.getStringProperty());

        // Validate the results for array properties
        final String dupProperty[] = bean.getDupProperty();
        assertNotNull("dupProperty present", dupProperty);
        assertEquals("dupProperty length", 3, dupProperty.length);
        assertEquals("dupProperty[0]", "New 0", dupProperty[0]);
        assertEquals("dupProperty[1]", "New 1", dupProperty[1]);
        assertEquals("dupProperty[2]", "New 2", dupProperty[2]);
        final int intArray[] = bean.getIntArray();
        assertNotNull("intArray present", intArray);
        assertEquals("intArray length", 3, intArray.length);
        assertEquals("intArray[0]", 100, intArray[0]);
        assertEquals("intArray[1]", 200, intArray[1]);
        assertEquals("intArray[2]", 300, intArray[2]);
        final String stringArray[] = bean.getStringArray();
        assertNotNull("stringArray present", stringArray);
        assertEquals("stringArray length", 2, stringArray.length);
        assertEquals("stringArray[0]", "New 0", stringArray[0]);
        assertEquals("stringArray[1]", "New 1", stringArray[1]);

    }

    /**
     * Test copyProperties() when the origin is a a {@code Map}.
     */
    public void testCopyPropertiesMap() {

        final Map<String, Object> map = new HashMap<>();
        map.put("booleanProperty", "false");
        map.put("byteProperty", "111");
        map.put("doubleProperty", "333.0");
        map.put("dupProperty", new String[] { "New 0", "New 1", "New 2" });
        map.put("floatProperty", "222.0");
        map.put("intArray", new String[] { "0", "100", "200" });
        map.put("intProperty", "111");
        map.put("longProperty", "444");
        map.put("shortProperty", "555");
        map.put("stringProperty", "New String Property");

        try {
            BeanUtils.copyProperties(bean, map);
        } catch (final Throwable t) {
            fail("Threw " + t.toString());
        }

        // Scalar properties
        assertEquals("booleanProperty", false,
                     bean.getBooleanProperty());
        assertEquals("byteProperty", (byte) 111,
                     bean.getByteProperty());
        assertEquals("doubleProperty", 333.0,
                     bean.getDoubleProperty(), 0.005);
        assertEquals("floatProperty", (float) 222.0,
                     bean.getFloatProperty(), (float) 0.005);
        assertEquals("longProperty", 111,
                     bean.getIntProperty());
        assertEquals("longProperty", 444,
                     bean.getLongProperty());
        assertEquals("shortProperty", (short) 555,
                     bean.getShortProperty());
        assertEquals("stringProperty", "New String Property",
                     bean.getStringProperty());

        // Indexed Properties
        final String dupProperty[] = bean.getDupProperty();
        assertNotNull("dupProperty present", dupProperty);
        assertEquals("dupProperty length", 3, dupProperty.length);
        assertEquals("dupProperty[0]", "New 0", dupProperty[0]);
        assertEquals("dupProperty[1]", "New 1", dupProperty[1]);
        assertEquals("dupProperty[2]", "New 2", dupProperty[2]);
        final int intArray[] = bean.getIntArray();
        assertNotNull("intArray present", intArray);
        assertEquals("intArray length", 3, intArray.length);
        assertEquals("intArray[0]", 0, intArray[0]);
        assertEquals("intArray[1]", 100, intArray[1]);
        assertEquals("intArray[2]", 200, intArray[2]);

    }

    /**
     * Test the copyProperties() method from a standard JavaBean.
     */
    public void testCopyPropertiesStandard() {

        // Set up an origin bean with customized properties
        final TestBean orig = new TestBean();
        orig.setBooleanProperty(false);
        orig.setByteProperty((byte) 111);
        orig.setDoubleProperty(333.33);
        orig.setDupProperty(new String[] { "New 0", "New 1", "New 2" });
        orig.setIntArray(new int[] { 100, 200, 300 });
        orig.setIntProperty(333);
        orig.setLongProperty(3333);
        orig.setShortProperty((short) 33);
        orig.setStringArray(new String[] { "New 0", "New 1" });
        orig.setStringProperty("Custom string");

        // Copy the origin bean to our destination test bean
        try {
            BeanUtils.copyProperties(bean, orig);
        } catch (final Exception e) {
            fail("Threw exception: " + e);
        }

        // Validate the results for scalar properties
        assertEquals("Copied boolean property",
                     false,
                     bean.getBooleanProperty());
        assertEquals("Copied byte property",
                     (byte) 111,
                     bean.getByteProperty());
        assertEquals("Copied double property",
                     333.33,
                     bean.getDoubleProperty(),
                     0.005);
        assertEquals("Copied int property",
                     333,
                     bean.getIntProperty());
        assertEquals("Copied long property",
                     3333,
                     bean.getLongProperty());
        assertEquals("Copied short property",
                     (short) 33,
                     bean.getShortProperty());
        assertEquals("Copied string property",
                     "Custom string",
                     bean.getStringProperty());

        // Validate the results for array properties
        final String dupProperty[] = bean.getDupProperty();
        assertNotNull("dupProperty present", dupProperty);
        assertEquals("dupProperty length", 3, dupProperty.length);
        assertEquals("dupProperty[0]", "New 0", dupProperty[0]);
        assertEquals("dupProperty[1]", "New 1", dupProperty[1]);
        assertEquals("dupProperty[2]", "New 2", dupProperty[2]);
        final int intArray[] = bean.getIntArray();
        assertNotNull("intArray present", intArray);
        assertEquals("intArray length", 3, intArray.length);
        assertEquals("intArray[0]", 100, intArray[0]);
        assertEquals("intArray[1]", 200, intArray[1]);
        assertEquals("intArray[2]", 300, intArray[2]);
        final String stringArray[] = bean.getStringArray();
        assertNotNull("stringArray present", stringArray);
        assertEquals("stringArray length", 2, stringArray.length);
        assertEquals("stringArray[0]", "New 0", stringArray[0]);
        assertEquals("stringArray[1]", "New 1", stringArray[1]);

    }

    /**
     * Test the describe() method.
     */
    public void testDescribe() {

        Map<String, String> map = null;
        try {
            map = BeanUtils.describe(bean);
        } catch (final Exception e) {
            fail("Threw exception " + e);
        }

        // Verify existence of all the properties that should be present
        for (final String describe : describes) {
            assertTrue("Property '" + describe + "' is present",
                       map.containsKey(describe));
        }
        assertTrue("Property 'writeOnlyProperty' is not present",
                   !map.containsKey("writeOnlyProperty"));

        // Verify the values of scalar properties
        assertEquals("Value of 'booleanProperty'",
                     "true",
                     map.get("booleanProperty"));
        assertEquals("Value of 'byteProperty'",
                     "121",
                     map.get("byteProperty"));
        assertEquals("Value of 'doubleProperty'",
                     "321.0",
                     map.get("doubleProperty"));
        assertEquals("Value of 'floatProperty'",
                     "123.0",
                     map.get("floatProperty"));
        assertEquals("Value of 'intProperty'",
                     "123",
                     map.get("intProperty"));
        assertEquals("Value of 'longProperty'",
                     "321",
                     map.get("longProperty"));
        assertEquals("Value of 'shortProperty'",
                     "987",
                     map.get("shortProperty"));
        assertEquals("Value of 'stringProperty'",
                     "This is a string",
                     map.get("stringProperty"));

    }

    /**
     *  tests the string and int arrays of TestBean
     */
    public void testGetArrayProperty() {
        try {
            String arr[] = BeanUtils.getArrayProperty(bean, "stringArray");
            final String comp[] = bean.getStringArray();

            assertTrue("String array length = " + comp.length,
                    comp.length == arr.length);

            arr = BeanUtils.getArrayProperty(bean, "intArray");
            final int iarr[] = bean.getIntArray();

            assertTrue("String array length = " + iarr.length,
                    iarr.length == arr.length);

            // Test property which isn't array or collection
            arr = BeanUtils.getArrayProperty(bean, "shortProperty");
            final String shortAsString = "" + bean.getShortProperty();
            assertEquals("Short List Test lth", 1, arr.length);
            assertEquals("Short Test value", shortAsString, arr[0]);

            // Test comma delimited list
            bean.setStringProperty("ABC");
            arr = BeanUtils.getArrayProperty(bean, "stringProperty");
            assertEquals("Delimited List Test lth", 1, arr.length);
            assertEquals("Delimited List Test value1", "ABC", arr[0]);

        } catch (final IllegalAccessException e) {
            fail("IllegalAccessException");
        } catch (final InvocationTargetException e) {
            fail("InvocationTargetException");
        } catch (final NoSuchMethodException e) {
            fail("NoSuchMethodException");
        }

    }

    /**
     * Test {@code getArrayProperty()} converting to a String.
     */
    public void testGetArrayPropertyDate() {
        String[] value = null;
        try {
            bean.setDateArrayProperty(new java.util.Date[] {testUtilDate});
            value = BeanUtils.getArrayProperty(bean, "dateArrayProperty");
        } catch (final Throwable t) {
            fail("Threw " + t);
        }
        assertEquals("java.util.Date[] --> String[] length", 1, value.length);
        assertEquals("java.util.Date[] --> String[] value ", testUtilDate.toString(), value[0]);
    }

    /**
     *  tests getting an indexed property
     */
    public void testGetIndexedProperty1() {
        try {
            String val = BeanUtils.getIndexedProperty(bean, "intIndexed[3]");
            String comp = String.valueOf(bean.getIntIndexed(3));
            assertTrue("intIndexed[3] == " + comp, val.equals(comp));

            val = BeanUtils.getIndexedProperty(bean, "stringIndexed[3]");
            comp = bean.getStringIndexed(3);
            assertTrue("stringIndexed[3] == " + comp, val.equals(comp));
        } catch (final IllegalAccessException e) {
            fail("IllegalAccessException");
        } catch (final InvocationTargetException e) {
            fail("InvocationTargetException");
        } catch (final NoSuchMethodException e) {
            fail("NoSuchMethodException");
        }
    }

    /**
     * Test {@code getArrayProperty()} converting to a String.
     */
    public void testGetIndexedPropertyDate() {
        String value = null;
        try {
            bean.setDateArrayProperty(new java.util.Date[] {testUtilDate});
            value = BeanUtils.getIndexedProperty(bean, "dateArrayProperty[0]");
        } catch (final Throwable t) {
            fail("Threw " + t);
        }
        assertEquals("java.util.Date[0] --> String", testUtilDate.toString(), value);
    }

    /**
     *  tests getting an indexed property
     */
    public void testGetIndexedProperty2() {
        try {
            String val = BeanUtils.getIndexedProperty(bean, "intIndexed", 3);
            String comp = String.valueOf(bean.getIntIndexed(3));

            assertTrue("intIndexed,3 == " + comp, val.equals(comp));

            val = BeanUtils.getIndexedProperty(bean, "stringIndexed", 3);
            comp = bean.getStringIndexed(3);

            assertTrue("stringIndexed,3 == " + comp, val.equals(comp));

        } catch (final IllegalAccessException e) {
            fail("IllegalAccessException");
        } catch (final InvocationTargetException e) {
            fail("InvocationTargetException");
        } catch (final NoSuchMethodException e) {
            fail("NoSuchMethodException");
        }
    }

    /**
     *  tests getting a nested property
     */
    public void testGetNestedProperty() {
        try {
            final String val = BeanUtils.getNestedProperty(bean, "nested.stringProperty");
            final String comp = bean.getNested().getStringProperty();
            assertTrue("nested.StringProperty == " + comp,
                    val.equals(comp));
        } catch (final IllegalAccessException e) {
            fail("IllegalAccessException");
        } catch (final InvocationTargetException e) {
            fail("InvocationTargetException");
        } catch (final NoSuchMethodException e) {
            fail("NoSuchMethodException");
        }
    }

    /**
     *  tests getting a 'whatever' property
     */
    public void testGetGeneralProperty() {
        try {
            final String val = BeanUtils.getProperty(bean, "nested.intIndexed[2]");
            final String comp = String.valueOf(bean.getIntIndexed(2));

            assertTrue("nested.intIndexed[2] == " + comp,
                    val.equals(comp));
        } catch (final IllegalAccessException e) {
            fail("IllegalAccessException");
        } catch (final InvocationTargetException e) {
            fail("InvocationTargetException");
        } catch (final NoSuchMethodException e) {
            fail("NoSuchMethodException");
        }
    }

    /**
     *  tests getting a 'whatever' property
     */
    public void testGetSimpleProperty() {
        try {
            final String val = BeanUtils.getSimpleProperty(bean, "shortProperty");
            final String comp = String.valueOf(bean.getShortProperty());

            assertTrue("shortProperty == " + comp,
                    val.equals(comp));
        } catch (final IllegalAccessException e) {
            fail("IllegalAccessException");
        } catch (final InvocationTargetException e) {
            fail("InvocationTargetException");
        } catch (final NoSuchMethodException e) {
            fail("NoSuchMethodException");
        }
    }

    /**
     * Test {@code getSimpleProperty()} converting to a String.
     */
    public void testGetSimplePropertyDate() {
        String value = null;
        try {
            bean.setDateProperty(testUtilDate);
            value = BeanUtils.getSimpleProperty(bean, "dateProperty");
        } catch (final Throwable t) {
            fail("Threw " + t);
        }
        assertEquals("java.util.Date --> String", testUtilDate.toString(), value);
    }

    /**
     * Test populate() method on individual array elements.
     */
    public void testPopulateArrayElements() {

        try {

            final HashMap<String, Object> map = new HashMap<>();
            map.put("intIndexed[0]", "100");
            map.put("intIndexed[2]", "120");
            map.put("intIndexed[4]", "140");

            BeanUtils.populate(bean, map);

            assertEquals("intIndexed[0] is 100",
                         100, bean.getIntIndexed(0));
            assertEquals("intIndexed[1] is 10",
                         10, bean.getIntIndexed(1));
            assertEquals("intIndexed[2] is 120",
                         120, bean.getIntIndexed(2));
            assertEquals("intIndexed[3] is 30",
                         30, bean.getIntIndexed(3));
            assertEquals("intIndexed[4] is 140",
                         140, bean.getIntIndexed(4));

            map.clear();
            map.put("stringIndexed[1]", "New String 1");
            map.put("stringIndexed[3]", "New String 3");

            BeanUtils.populate(bean, map);

            assertEquals("stringIndexed[0] is \"String 0\"",
                         "String 0", bean.getStringIndexed(0));
            assertEquals("stringIndexed[1] is \"New String 1\"",
                         "New String 1", bean.getStringIndexed(1));
            assertEquals("stringIndexed[2] is \"String 2\"",
                         "String 2", bean.getStringIndexed(2));
            assertEquals("stringIndexed[3] is \"New String 3\"",
                         "New String 3", bean.getStringIndexed(3));
            assertEquals("stringIndexed[4] is \"String 4\"",
                         "String 4", bean.getStringIndexed(4));

        } catch (final IllegalAccessException e) {
            fail("IllegalAccessException");
        } catch (final InvocationTargetException e) {
            fail("InvocationTargetException");
        }

    }

    /**
     * Test populate() method on array properties as a whole.
     */
    public void testPopulateArrayProperties() {

        try {

            final HashMap<String, Object> map = new HashMap<>();
            int intArray[] = new int[] { 123, 456, 789 };
            map.put("intArray", intArray);
            String stringArray[] = new String[]
                { "New String 0", "New String 1" };
            map.put("stringArray", stringArray);

            BeanUtils.populate(bean, map);

            intArray = bean.getIntArray();
            assertNotNull("intArray is present", intArray);
            assertEquals("intArray length",
                         3, intArray.length);
            assertEquals("intArray[0]", 123, intArray[0]);
            assertEquals("intArray[1]", 456, intArray[1]);
            assertEquals("intArray[2]", 789, intArray[2]);
            stringArray = bean.getStringArray();
            assertNotNull("stringArray is present", stringArray);
            assertEquals("stringArray length", 2, stringArray.length);
            assertEquals("stringArray[0]", "New String 0", stringArray[0]);
            assertEquals("stringArray[1]", "New String 1", stringArray[1]);

        } catch (final IllegalAccessException e) {
            fail("IllegalAccessException");
        } catch (final InvocationTargetException e) {
            fail("InvocationTargetException");
        }

    }

    /**
     * Test populate() on mapped properties.
     */
    public void testPopulateMapped() {

        try {

            final HashMap<String, Object> map = new HashMap<>();
            map.put("mappedProperty(First Key)", "New First Value");
            map.put("mappedProperty(Third Key)", "New Third Value");

            BeanUtils.populate(bean, map);

            assertEquals("mappedProperty(First Key)",
                         "New First Value",
                         bean.getMappedProperty("First Key"));
            assertEquals("mappedProperty(Second Key)",
                         "Second Value",
                         bean.getMappedProperty("Second Key"));
            assertEquals("mappedProperty(Third Key)",
                         "New Third Value",
                         bean.getMappedProperty("Third Key"));
            assertNull("mappedProperty(Fourth Key",
                       bean.getMappedProperty("Fourth Key"));

        } catch (final IllegalAccessException e) {
            fail("IllegalAccessException");
        } catch (final InvocationTargetException e) {
            fail("InvocationTargetException");
        }

    }

    /**
     * Test populate() method on nested properties.
     */
    public void testPopulateNested() {

        try {

            final HashMap<String, Object> map = new HashMap<>();
            map.put("nested.booleanProperty", "false");
            // booleanSecond is left at true
            map.put("nested.doubleProperty", "432.0");
            // floatProperty is left at 123.0
            map.put("nested.intProperty", "543");
            // longProperty is left at 321
            map.put("nested.shortProperty", "654");
            // stringProperty is left at "This is a string"
            map.put("nested.writeOnlyProperty", "New writeOnlyProperty value");

            BeanUtils.populate(bean, map);

            assertTrue("booleanProperty is false",
                       !bean.getNested().getBooleanProperty());
            assertTrue("booleanSecond is true",
                       bean.getNested().isBooleanSecond());
            assertEquals("doubleProperty is 432.0",
                         432.0,
                         bean.getNested().getDoubleProperty(),
                         0.005);
            assertEquals("floatProperty is 123.0",
                         (float) 123.0,
                         bean.getNested().getFloatProperty(),
                         (float) 0.005);
            assertEquals("intProperty is 543",
                         543, bean.getNested().getIntProperty());
            assertEquals("longProperty is 321",
                         321, bean.getNested().getLongProperty());
            assertEquals("shortProperty is 654",
                         (short) 654, bean.getNested().getShortProperty());
            assertEquals("stringProperty is \"This is a string\"",
                         "This is a string",
                         bean.getNested().getStringProperty());
            assertEquals("writeOnlyProperty is \"New writeOnlyProperty value\"",
                         "New writeOnlyProperty value",
                         bean.getNested().getWriteOnlyPropertyValue());

        } catch (final IllegalAccessException e) {
            fail("IllegalAccessException");
        } catch (final InvocationTargetException e) {
            fail("InvocationTargetException");
        }

    }

    /**
     * Test populate() method on scalar properties.
     */
    public void testPopulateScalar() {

        try {

            bean.setNullProperty("Non-null value");

            final HashMap<String, Object> map = new HashMap<>();
            map.put("booleanProperty", "false");
            // booleanSecond is left at true
            map.put("byteProperty", "111");
            map.put("doubleProperty", "432.0");
            // floatProperty is left at 123.0
            map.put("intProperty", "543");
            map.put("longProperty", "");
            map.put("nullProperty", null);
            map.put("shortProperty", "654");
            // stringProperty is left at "This is a string"
            map.put("writeOnlyProperty", "New writeOnlyProperty value");
            map.put("readOnlyProperty", "New readOnlyProperty value");

            BeanUtils.populate(bean, map);

            assertTrue("booleanProperty is false", !bean.getBooleanProperty());
            assertTrue("booleanSecond is true", bean.isBooleanSecond());
            assertEquals("byteProperty is 111",
                         (byte) 111, bean.getByteProperty());
            assertEquals("doubleProperty is 432.0",
                         432.0, bean.getDoubleProperty(),
                         0.005);
            assertEquals("floatProperty is 123.0",
                         (float) 123.0, bean.getFloatProperty(),
                         (float) 0.005);
            assertEquals("intProperty is 543",
                         543, bean.getIntProperty());
            assertEquals("longProperty is 0",
                         0, bean.getLongProperty());
            assertNull("nullProperty is null",
                       bean.getNullProperty());
            assertEquals("shortProperty is 654",
                         (short) 654, bean.getShortProperty());
            assertEquals("stringProperty is \"This is a string\"",
                         "This is a string", bean.getStringProperty());
            assertEquals("writeOnlyProperty is \"New writeOnlyProperty value\"",
                         "New writeOnlyProperty value",
                         bean.getWriteOnlyPropertyValue());
            assertEquals("readOnlyProperty is \"Read Only String Property\"",
                         "Read Only String Property",
                         bean.getReadOnlyProperty());

        } catch (final IllegalAccessException e) {
            fail("IllegalAccessException");
        } catch (final InvocationTargetException e) {
            fail("InvocationTargetException");
        }

    }

    /**
     * Test calling setProperty() with null property values.
     */
    public void testSetPropertyNullValues() throws Exception {

        Object oldValue = null;
        Object newValue = null;

        // Scalar value into array
        oldValue = PropertyUtils.getSimpleProperty(bean, "stringArray");
        BeanUtils.setProperty(bean, "stringArray", (String) null);
        newValue = PropertyUtils.getSimpleProperty(bean, "stringArray");
        assertNotNull("stringArray is not null", newValue);
        assertTrue("stringArray of correct type",
                   newValue instanceof String[]);
        assertEquals("stringArray length",
                     1, ((String[]) newValue).length);
        PropertyUtils.setProperty(bean, "stringArray", oldValue);

        // Indexed value into array
        oldValue = PropertyUtils.getSimpleProperty(bean, "stringArray");
        BeanUtils.setProperty(bean, "stringArray[2]", (String) null);
        newValue = PropertyUtils.getSimpleProperty(bean, "stringArray");
        assertNotNull("stringArray is not null", newValue);
        assertTrue("stringArray of correct type",
                   newValue instanceof String[]);
        assertEquals("stringArray length",
                     5, ((String[]) newValue).length);
        assertTrue("stringArray[2] is null",
                   ((String[]) newValue)[2] == null);
        PropertyUtils.setProperty(bean, "stringArray", oldValue);

        // Value into scalar
        BeanUtils.setProperty(bean, "stringProperty", null);
        assertTrue("stringProperty is now null",
                   BeanUtils.getProperty(bean, "stringProperty") == null);

    }

    /**
     * Test converting to and from primitive wrapper types.
     */
    public void testSetPropertyOnPrimitiveWrappers() throws Exception {

        BeanUtils.setProperty(bean,"intProperty", new Integer(1));
        assertEquals(1,bean.getIntProperty());
        BeanUtils.setProperty(bean,"stringProperty", new Integer(1));
        assertEquals(1, Integer.parseInt(bean.getStringProperty()));

    }

    /**
     * Test narrowing and widening conversions on byte.
     */
    public void testSetPropertyByte() throws Exception {

        BeanUtils.setProperty(bean, "byteProperty", new Byte((byte) 123));
        assertEquals((byte) 123, bean.getByteProperty());
/*
        BeanUtils.setProperty(bean, "byteProperty", new Double((double) 123));
        assertEquals((byte) 123, bean.getByteProperty());
        BeanUtils.setProperty(bean, "byteProperty", new Float((float) 123));
        assertEquals((byte) 123, bean.getByteProperty());
*/
        BeanUtils.setProperty(bean, "byteProperty", new Integer(123));
        assertEquals((byte) 123, bean.getByteProperty());
        BeanUtils.setProperty(bean, "byteProperty", new Long(123));
        assertEquals((byte) 123, bean.getByteProperty());
        BeanUtils.setProperty(bean, "byteProperty", new Short((short) 123));
        assertEquals((byte) 123, bean.getByteProperty());

    }

    /**
     * Test {@code setProperty()} conversion.
     */
    public void testSetPropertyConvert() {
        try {
            BeanUtils.setProperty(bean, "dateProperty", testCalendar);
        } catch (final Throwable t) {
            fail("Threw " + t);
        }
        assertEquals("Calendar --> java.util.Date", testUtilDate, bean.getDateProperty());
    }

    /**
     * Test {@code setProperty()} converting from a String.
     */
    public void testSetPropertyConvertFromString() {
        try {
            BeanUtils.setProperty(bean, "dateProperty", testStringDate);
        } catch (final Throwable t) {
            fail("Threw " + t);
        }
        assertEquals("String --> java.util.Date", testUtilDate, bean.getDateProperty());
    }

    /**
     * Test {@code setProperty()} converting to a String.
     */
    public void testSetPropertyConvertToString() {
        try {
            BeanUtils.setProperty(bean, "stringProperty", testUtilDate);
        } catch (final Throwable t) {
            fail("Threw " + t);
        }
        assertEquals("java.util.Date --> String", testUtilDate.toString(), bean.getStringProperty());
    }

    /**
     * Test {@code setProperty()} converting to a String array.
     */
    public void testSetPropertyConvertToStringArray() {
        try {
            bean.setStringArray(null);
            BeanUtils.setProperty(bean, "stringArray", new java.util.Date[] {testUtilDate});
        } catch (final Throwable t) {
            fail("Threw " + t);
        }
        assertEquals("java.util.Date[] --> String[] length", 1, bean.getStringArray().length);
        assertEquals("java.util.Date[] --> String[] value ", testUtilDate.toString(), bean.getStringArray()[0]);
    }

    /**
     * Test {@code setProperty()} converting to a String on indexed property
     */
    public void testSetPropertyConvertToStringIndexed() {
        try {
            bean.setStringArray(new String[1]);
            BeanUtils.setProperty(bean, "stringArray[0]", testUtilDate);
        } catch (final Throwable t) {
            fail("Threw " + t);
        }
        assertEquals("java.util.Date --> String[]", testUtilDate.toString(), bean.getStringArray()[0]);
    }

    /**
     * Test narrowing and widening conversions on double.
     */
    public void testSetPropertyDouble() throws Exception {

        BeanUtils.setProperty(bean, "doubleProperty", new Byte((byte) 123));
        assertEquals(123, bean.getDoubleProperty(), 0.005);
        BeanUtils.setProperty(bean, "doubleProperty", new Double(123));
        assertEquals(123, bean.getDoubleProperty(), 0.005);
        BeanUtils.setProperty(bean, "doubleProperty", new Float(123));
        assertEquals(123, bean.getDoubleProperty(), 0.005);
        BeanUtils.setProperty(bean, "doubleProperty", new Integer(123));
        assertEquals(123, bean.getDoubleProperty(), 0.005);
        BeanUtils.setProperty(bean, "doubleProperty", new Long(123));
        assertEquals(123, bean.getDoubleProperty(), 0.005);
        BeanUtils.setProperty(bean, "doubleProperty", new Short((short) 123));
        assertEquals(123, bean.getDoubleProperty(), 0.005);

    }

    /**
     * Test narrowing and widening conversions on float.
     */
    public void testSetPropertyFloat() throws Exception {

        BeanUtils.setProperty(bean, "floatProperty", new Byte((byte) 123));
        assertEquals(123, bean.getFloatProperty(), 0.005);
        BeanUtils.setProperty(bean, "floatProperty", new Double(123));
        assertEquals(123, bean.getFloatProperty(), 0.005);
        BeanUtils.setProperty(bean, "floatProperty", new Float(123));
        assertEquals(123, bean.getFloatProperty(), 0.005);
        BeanUtils.setProperty(bean, "floatProperty", new Integer(123));
        assertEquals(123, bean.getFloatProperty(), 0.005);
        BeanUtils.setProperty(bean, "floatProperty", new Long(123));
        assertEquals(123, bean.getFloatProperty(), 0.005);
        BeanUtils.setProperty(bean, "floatProperty", new Short((short) 123));
        assertEquals(123, bean.getFloatProperty(), 0.005);

    }

    /**
     * Test narrowing and widening conversions on int.
     */
    public void testSetPropertyInteger() throws Exception {

        BeanUtils.setProperty(bean, "longProperty", new Byte((byte) 123));
        assertEquals(123, bean.getIntProperty());
/*
        BeanUtils.setProperty(bean, "longProperty", new Double((double) 123));
        assertEquals((int) 123, bean.getIntProperty());
        BeanUtils.setProperty(bean, "longProperty", new Float((float) 123));
        assertEquals((int) 123, bean.getIntProperty());
*/
        BeanUtils.setProperty(bean, "longProperty", new Integer(123));
        assertEquals(123, bean.getIntProperty());
        BeanUtils.setProperty(bean, "longProperty", new Long(123));
        assertEquals(123, bean.getIntProperty());
        BeanUtils.setProperty(bean, "longProperty", new Short((short) 123));
        assertEquals(123, bean.getIntProperty());

    }

    /**
     * Test narrowing and widening conversions on long.
     */
    public void testSetPropertyLong() throws Exception {

        BeanUtils.setProperty(bean, "longProperty", new Byte((byte) 123));
        assertEquals(123, bean.getLongProperty());
/*
        BeanUtils.setProperty(bean, "longProperty", new Double((double) 123));
        assertEquals((long) 123, bean.getLongProperty());
        BeanUtils.setProperty(bean, "longProperty", new Float((float) 123));
        assertEquals((long) 123, bean.getLongProperty());
*/
        BeanUtils.setProperty(bean, "longProperty", new Integer(123));
        assertEquals(123, bean.getLongProperty());
        BeanUtils.setProperty(bean, "longProperty", new Long(123));
        assertEquals(123, bean.getLongProperty());
        BeanUtils.setProperty(bean, "longProperty", new Short((short) 123));
        assertEquals(123, bean.getLongProperty());

    }

    /**
     * Test setting a null property value.
     */
    public void testSetPropertyNull() throws Exception {

        bean.setNullProperty("non-null value");
        BeanUtils.setProperty(bean, "nullProperty", null);
        assertNull("nullProperty is null", bean.getNullProperty());

    }

    /**
     * Test narrowing and widening conversions on short.
     */
    public void testSetPropertyShort() throws Exception {

        BeanUtils.setProperty(bean, "shortProperty", new Byte((byte) 123));
        assertEquals((short) 123, bean.getShortProperty());
/*
        BeanUtils.setProperty(bean, "shortProperty", new Double((double) 123));
        assertEquals((short) 123, bean.getShortProperty());
        BeanUtils.setProperty(bean, "shortProperty", new Float((float) 123));
        assertEquals((short) 123, bean.getShortProperty());
*/
        BeanUtils.setProperty(bean, "shortProperty", new Integer(123));
        assertEquals((short) 123, bean.getShortProperty());
        BeanUtils.setProperty(bean, "shortProperty", new Long(123));
        assertEquals((short) 123, bean.getShortProperty());
        BeanUtils.setProperty(bean, "shortProperty", new Short((short) 123));
        assertEquals((short) 123, bean.getShortProperty());

    }

    /**
     * Test setting a String value to a String array property
     */
    public void testSetPropertyStringToArray() throws Exception {
        BeanUtils.setProperty(bean, "stringArray", "ABC,DEF,GHI");
        final String[] strArray =  bean.getStringArray();
        assertEquals("length", 3, strArray.length);
        assertEquals("value[0]", "ABC", strArray[0]);
        assertEquals("value[1]", "DEF", strArray[1]);
        assertEquals("value[2]", "GHI", strArray[2]);

        BeanUtils.setProperty(bean, "intArray", "0, 10, 20, 30, 40");
        final int[] intArray =  bean.getIntArray();
        assertEquals("length", 5, intArray.length);
        assertEquals("value[0]", 0, intArray[0]);
        assertEquals("value[1]", 10, intArray[1]);
        assertEquals("value[2]", 20, intArray[2]);
        assertEquals("value[3]", 30, intArray[3]);
        assertEquals("value[4]", 40, intArray[4]);
    }

    /**
     * Test narrowing and widening conversions on byte.
     */
    public void testCopyPropertyByte() throws Exception {

        BeanUtils.copyProperty(bean, "byteProperty", new Byte((byte) 123));
        assertEquals((byte) 123, bean.getByteProperty());
        BeanUtils.copyProperty(bean, "byteProperty", new Double(123));
        assertEquals((byte) 123, bean.getByteProperty());
        BeanUtils.copyProperty(bean, "byteProperty", new Float(123));
        assertEquals((byte) 123, bean.getByteProperty());
        BeanUtils.copyProperty(bean, "byteProperty", new Integer(123));
        assertEquals((byte) 123, bean.getByteProperty());
        BeanUtils.copyProperty(bean, "byteProperty", new Long(123));
        assertEquals((byte) 123, bean.getByteProperty());
        BeanUtils.copyProperty(bean, "byteProperty", new Short((short) 123));
        assertEquals((byte) 123, bean.getByteProperty());

    }

    /**
     * Test {@code copyProperty()} conversion.
     */
    public void testCopyPropertyConvert() {
        try {
            BeanUtils.copyProperty(bean, "dateProperty", testCalendar);
        } catch (final Throwable t) {
            fail("Threw " + t);
        }
        assertEquals("Calendar --> java.util.Date", testUtilDate, bean.getDateProperty());
    }

    /**
     * Test {@code copyProperty()} converting from a String.
     */
    public void testCopyPropertyConvertFromString() {
        try {
            BeanUtils.copyProperty(bean, "dateProperty", testStringDate);
        } catch (final Throwable t) {
            fail("Threw " + t);
        }
        assertEquals("String --> java.util.Date", testUtilDate, bean.getDateProperty());
    }

    /**
     * Test {@code copyProperty()} converting to a String.
     */
    public void testCopyPropertyConvertToString() {
        try {
            BeanUtils.copyProperty(bean, "stringProperty", testUtilDate);
        } catch (final Throwable t) {
            fail("Threw " + t);
        }
        assertEquals("java.util.Date --> String", testUtilDate.toString(), bean.getStringProperty());
    }

    /**
     * Test {@code copyProperty()} converting to a String.
     */
    public void testCopyPropertyConvertToStringArray() {
        try {
            bean.setStringArray(null);
            BeanUtils.copyProperty(bean, "stringArray", new java.util.Date[] {testUtilDate});
        } catch (final Throwable t) {
            fail("Threw " + t);
        }
        assertEquals("java.util.Date[] --> String[] length", 1, bean.getStringArray().length);
        assertEquals("java.util.Date[] --> String[] value ", testUtilDate.toString(), bean.getStringArray()[0]);
    }

    /**
     * Test {@code copyProperty()} converting to a String on indexed property
     */
    public void testCopyPropertyConvertToStringIndexed() {
        try {
            bean.setStringArray(new String[1]);
            BeanUtils.copyProperty(bean, "stringArray[0]", testUtilDate);
        } catch (final Throwable t) {
            fail("Threw " + t);
        }
        assertEquals("java.util.Date --> String[]", testUtilDate.toString(), bean.getStringArray()[0]);
    }

    /**
     * Test narrowing and widening conversions on double.
     */
    public void testCopyPropertyDouble() throws Exception {

        BeanUtils.copyProperty(bean, "doubleProperty", new Byte((byte) 123));
        assertEquals(123, bean.getDoubleProperty(), 0.005);
        BeanUtils.copyProperty(bean, "doubleProperty", new Double(123));
        assertEquals(123, bean.getDoubleProperty(), 0.005);
        BeanUtils.copyProperty(bean, "doubleProperty", new Float(123));
        assertEquals(123, bean.getDoubleProperty(), 0.005);
        BeanUtils.copyProperty(bean, "doubleProperty", new Integer(123));
        assertEquals(123, bean.getDoubleProperty(), 0.005);
        BeanUtils.copyProperty(bean, "doubleProperty", new Long(123));
        assertEquals(123, bean.getDoubleProperty(), 0.005);
        BeanUtils.copyProperty(bean, "doubleProperty", new Short((short) 123));
        assertEquals(123, bean.getDoubleProperty(), 0.005);

    }

    /**
     * Test narrowing and widening conversions on float.
     */
    public void testCopyPropertyFloat() throws Exception {

        BeanUtils.copyProperty(bean, "floatProperty", new Byte((byte) 123));
        assertEquals(123, bean.getFloatProperty(), 0.005);
        BeanUtils.copyProperty(bean, "floatProperty", new Double(123));
        assertEquals(123, bean.getFloatProperty(), 0.005);
        BeanUtils.copyProperty(bean, "floatProperty", new Float(123));
        assertEquals(123, bean.getFloatProperty(), 0.005);
        BeanUtils.copyProperty(bean, "floatProperty", new Integer(123));
        assertEquals(123, bean.getFloatProperty(), 0.005);
        BeanUtils.copyProperty(bean, "floatProperty", new Long(123));
        assertEquals(123, bean.getFloatProperty(), 0.005);
        BeanUtils.copyProperty(bean, "floatProperty", new Short((short) 123));
        assertEquals(123, bean.getFloatProperty(), 0.005);

    }

    /**
     * Test narrowing and widening conversions on int.
     */
    public void testCopyPropertyInteger() throws Exception {

        BeanUtils.copyProperty(bean, "longProperty", new Byte((byte) 123));
        assertEquals(123, bean.getIntProperty());
        BeanUtils.copyProperty(bean, "longProperty", new Double(123));
        assertEquals(123, bean.getIntProperty());
        BeanUtils.copyProperty(bean, "longProperty", new Float(123));
        assertEquals(123, bean.getIntProperty());
        BeanUtils.copyProperty(bean, "longProperty", new Integer(123));
        assertEquals(123, bean.getIntProperty());
        BeanUtils.copyProperty(bean, "longProperty", new Long(123));
        assertEquals(123, bean.getIntProperty());
        BeanUtils.copyProperty(bean, "longProperty", new Short((short) 123));
        assertEquals(123, bean.getIntProperty());

    }

    /**
     * Test narrowing and widening conversions on long.
     */
    public void testCopyPropertyLong() throws Exception {

        BeanUtils.copyProperty(bean, "longProperty", new Byte((byte) 123));
        assertEquals(123, bean.getLongProperty());
        BeanUtils.copyProperty(bean, "longProperty", new Double(123));
        assertEquals(123, bean.getLongProperty());
        BeanUtils.copyProperty(bean, "longProperty", new Float(123));
        assertEquals(123, bean.getLongProperty());
        BeanUtils.copyProperty(bean, "longProperty", new Integer(123));
        assertEquals(123, bean.getLongProperty());
        BeanUtils.copyProperty(bean, "longProperty", new Long(123));
        assertEquals(123, bean.getLongProperty());
        BeanUtils.copyProperty(bean, "longProperty", new Short((short) 123));
        assertEquals(123, bean.getLongProperty());

    }

    /**
     * Test narrowing and widening conversions on short.
     */
    public void testCopyPropertyShort() throws Exception {

        BeanUtils.copyProperty(bean, "shortProperty", new Byte((byte) 123));
        assertEquals((short) 123, bean.getShortProperty());
        BeanUtils.copyProperty(bean, "shortProperty", new Double(123));
        assertEquals((short) 123, bean.getShortProperty());
        BeanUtils.copyProperty(bean, "shortProperty", new Float(123));
        assertEquals((short) 123, bean.getShortProperty());
        BeanUtils.copyProperty(bean, "shortProperty", new Integer(123));
        assertEquals((short) 123, bean.getShortProperty());
        BeanUtils.copyProperty(bean, "shortProperty", new Long(123));
        assertEquals((short) 123, bean.getShortProperty());
        BeanUtils.copyProperty(bean, "shortProperty", new Short((short) 123));
        assertEquals((short) 123, bean.getShortProperty());

    }

    /**
     * Test copying a property using a nested indexed array expression,
     * with and without conversions.
     */
    public void testCopyPropertyNestedIndexedArray() throws Exception {

        final int origArray[] = { 0, 10, 20, 30, 40 };
        final int intArray[] = { 0, 0, 0 };
        bean.getNested().setIntArray(intArray);
        final int intChanged[] = { 0, 0, 0 };

        // No conversion required
        BeanUtils.copyProperty(bean, "nested.intArray[1]", new Integer(1));
        checkIntArray(bean.getIntArray(), origArray);
        intChanged[1] = 1;
        checkIntArray(bean.getNested().getIntArray(), intChanged);

        // Widening conversion required
        BeanUtils.copyProperty(bean, "nested.intArray[1]", new Byte((byte) 2));
        checkIntArray(bean.getIntArray(), origArray);
        intChanged[1] = 2;
        checkIntArray(bean.getNested().getIntArray(), intChanged);

        // Narrowing conversion required
        BeanUtils.copyProperty(bean, "nested.intArray[1]", new Long(3));
        checkIntArray(bean.getIntArray(), origArray);
        intChanged[1] = 3;
        checkIntArray(bean.getNested().getIntArray(), intChanged);

        // String conversion required
        BeanUtils.copyProperty(bean, "nested.intArray[1]", "4");
        checkIntArray(bean.getIntArray(), origArray);
        intChanged[1] = 4;
        checkIntArray(bean.getNested().getIntArray(), intChanged);

    }

    /**
     * Test copying a property using a nested mapped map property.
     */
    public void testCopyPropertyNestedMappedMap() throws Exception {

        final Map<String, Object> origMap = new HashMap<>();
        origMap.put("First Key", "First Value");
        origMap.put("Second Key", "Second Value");
        final Map<String, Object> changedMap = new HashMap<>();
        changedMap.put("First Key", "First Value");
        changedMap.put("Second Key", "Second Value");

        // No conversion required
        BeanUtils.copyProperty(bean, "nested.mapProperty(Second Key)",
                               "New Second Value");
        checkMap(bean.getMapProperty(), origMap);
        changedMap.put("Second Key", "New Second Value");
        checkMap(bean.getNested().getMapProperty(), changedMap);

    }

    /**
     * Test copying a property using a nested simple expression, with and
     * without conversions.
     */
    public void testCopyPropertyNestedSimple() throws Exception {

        bean.setIntProperty(0);
        bean.getNested().setIntProperty(0);

        // No conversion required
        BeanUtils.copyProperty(bean, "nested.intProperty", new Integer(1));
        assertNotNull(bean.getNested());
        assertEquals(0, bean.getIntProperty());
        assertEquals(1, bean.getNested().getIntProperty());

        // Widening conversion required
        BeanUtils.copyProperty(bean, "nested.intProperty", new Byte((byte) 2));
        assertNotNull(bean.getNested());
        assertEquals(0, bean.getIntProperty());
        assertEquals(2, bean.getNested().getIntProperty());

        // Narrowing conversion required
        BeanUtils.copyProperty(bean, "nested.intProperty", new Long(3));
        assertNotNull(bean.getNested());
        assertEquals(0, bean.getIntProperty());
        assertEquals(3, bean.getNested().getIntProperty());

        // String conversion required
        BeanUtils.copyProperty(bean, "nested.intProperty", "4");
        assertNotNull(bean.getNested());
        assertEquals(0, bean.getIntProperty());
        assertEquals(4, bean.getNested().getIntProperty());

    }

    /**
     * Test copying a null property value.
     */
    public void testCopyPropertyNull() throws Exception {

        bean.setNullProperty("non-null value");
        BeanUtils.copyProperty(bean, "nullProperty", null);
        assertNull("nullProperty is null", bean.getNullProperty());

    }

    /**
     * Test copying a new value to a write-only property, with and without
     * conversions.
     */
    public void testCopyPropertyWriteOnly() throws Exception {

        bean.setWriteOnlyProperty("Original value");

        // No conversion required
        BeanUtils.copyProperty(bean, "writeOnlyProperty", "New value");
        assertEquals("New value", bean.getWriteOnlyPropertyValue());

        // Integer->String conversion required
        BeanUtils.copyProperty(bean, "writeOnlyProperty", new Integer(123));
        assertEquals("123", bean.getWriteOnlyPropertyValue());

    }

    /**
     * Test setting a new value to a write-only property, with and without
     * conversions.
     */
    public void testSetPropertyWriteOnly() throws Exception {

        bean.setWriteOnlyProperty("Original value");

        // No conversion required
        BeanUtils.setProperty(bean, "writeOnlyProperty", "New value");
        assertEquals("New value", bean.getWriteOnlyPropertyValue());

        // Integer->String conversion required
        BeanUtils.setProperty(bean, "writeOnlyProperty", new Integer(123));
        assertEquals("123", bean.getWriteOnlyPropertyValue());

    }

    /**
     * Test setting a value out of a mapped Map
     */
    public void testSetMappedMap() {
        final TestBean bean = new TestBean();
        final Map<String, Object> map = new HashMap<>();
        map.put("sub-key-1", "sub-value-1");
        map.put("sub-key-2", "sub-value-2");
        map.put("sub-key-3", "sub-value-3");
        bean.getMapProperty().put("mappedMap", map);

        assertEquals("BEFORE", "sub-value-3", ((Map<?, ?>)bean.getMapProperty().get("mappedMap")).get("sub-key-3"));
        try {
            BeanUtils.setProperty(bean, "mapProperty(mappedMap)(sub-key-3)", "SUB-KEY-3-UPDATED");
        } catch (final Throwable t) {
            fail("Threw " + t + "");
        }
        assertEquals("AFTER", "SUB-KEY-3-UPDATED", ((Map<?, ?>)bean.getMapProperty().get("mappedMap")).get("sub-key-3"));
    }

    /** Tests that separate instances can register separate instances */
    public void testSeparateInstances() throws Exception {
        final BeanUtilsBean utilsOne = new BeanUtilsBean(
                                                new ConvertUtilsBean(),
                                                new PropertyUtilsBean());
        final BeanUtilsBean utilsTwo = new BeanUtilsBean(
                                                new ConvertUtilsBean(),
                                                new PropertyUtilsBean());

        final TestBean bean = new TestBean();

        // Make sure what we're testing works
        bean.setBooleanProperty(false);
        utilsOne.setProperty(bean, "booleanProperty", "true");
        assertEquals("Set property failed (1)", bean.getBooleanProperty(), true);

        bean.setBooleanProperty(false);
        utilsTwo.setProperty(bean, "booleanProperty", "true");
        assertEquals("Set property failed (2)", bean.getBooleanProperty(), true);

        // now change the registered conversion

        utilsOne.getConvertUtils().register(new ThrowExceptionConverter(), Boolean.TYPE);
        try {

            bean.setBooleanProperty(false);
            utilsOne.setProperty(bean, "booleanProperty", "true");
            fail("Registered conversion not used.");

        } catch (final PassTestException e) { /* Do nothing */ }

        // make sure that this conversion has no been registered in the other instance
        try {

            bean.setBooleanProperty(false);
            utilsTwo.setProperty(bean, "booleanProperty", "true");
            assertEquals("Set property failed (3)", bean.getBooleanProperty(), true);

        } catch (final PassTestException e) {
            fail("Registed converter is used by other instances");
        }
    }

    public void testArrayPropertyConversion() throws Exception {
        final BeanUtilsBean beanUtils = new BeanUtilsBean(
                                                    new ConvertUtilsBean(),
                                                    new PropertyUtilsBean());

        final TestBean bean = new TestBean();
        final String [] results = beanUtils.getArrayProperty(bean, "intArray");

        final int[] values = bean.getIntArray();
        assertEquals(
                    "Converted array size not equal to property array size.",
                    results.length,
                    values.length);
        for (int i=0, size=values.length ;  i<size; i++) {
            assertEquals(
                    "Value " + i + " incorrectly converted ",
                    values[i] + "",
                    results[i]);
        }
    }

    // Ensure that the actual int[] matches the expected int[]
    protected void checkIntArray(final int actual[], final int expected[]) {
        assertNotNull("actual array not null", actual);
        assertEquals("actual array length", expected.length, actual.length);
        for (int i = 0; i < actual.length; i++) {
            assertEquals("actual array value[" + i + "]",
                         expected[i], actual[i]);
        }
    }

    // Ensure that the actual Map matches the expected Map
    protected void checkMap(final Map<?, ?> actual, final Map<?, ?> expected) {
        assertNotNull("actual map not null", actual);
        assertEquals("actual map size", expected.size(), actual.size());
        final Iterator<?> keys = expected.keySet().iterator();
        while (keys.hasNext()) {
            final Object key = keys.next();
            assertEquals("actual map value(" + key + ")",
                         expected.get(key), actual.get(key));
        }
    }

    public void testMappedProperty() throws Exception {
        final MappedPropertyTestBean bean = new MappedPropertyTestBean();

        BeanUtils.setProperty(bean, "mapproperty(this.that.the-other)", "some.dotty.value");

        assertEquals(
                        "Mapped property set correctly",
                        "some.dotty.value",
                        bean.getMapproperty("this.that.the-other"));
    }

    /**
     * Test for {@link BeanUtilsBean#initCause(Throwable, Throwable)} method.
     */
    public void testInitCause() {
        if (isPre14JVM()) {
            return;
        }
        final String parentMsg = "PARENT-THROWABLE";
        final String causeMsg  = "THROWABLE-CAUSE";
        try {
            initCauseAndThrowException(parentMsg, causeMsg);
        } catch (final Throwable thrownParent) {
            assertEquals("Parent", parentMsg, thrownParent.getMessage());
            try {
                assertEquals("Parent", parentMsg, thrownParent.getMessage());
                final Throwable thrownCause = getCause(thrownParent);
                assertNotNull("Cause Null", thrownCause);
                assertEquals("Cause", causeMsg, thrownCause.getMessage());
            } catch (final Throwable testError) {
                fail("If you're running JDK 1.3 then don't worry this should fail," +
                        " if not then needs checking out: " + testError);
            }
        }
    }

    /**
     * Use reflection to get the cause
     */
    private Throwable getCause(final Throwable t) throws Throwable {
        return (Throwable)PropertyUtils.getProperty(t, "cause");
    }

    /**
     * Catch a cause, initialize using BeanUtils.initCause() and throw new exception
     */
    private void initCauseAndThrowException(final String parent, final String cause) throws Throwable {
        try {
            throwException(cause);
        } catch (final Throwable e) {
            final Throwable t = new Exception(parent);
            BeanUtils.initCause(t, e);
            throw t;
        }
    }

    /**
     * Throw an exception with the specified message.
     */
    private void throwException(final String msg) throws Throwable {
        throw new Exception(msg);
    }

    /**
     * Test for JDK 1.4
     */
    public static boolean isPre14JVM() {
        final String version = System.getProperty("java.specification.version");
        final StringTokenizer tokenizer = new StringTokenizer(version,".");
        if (tokenizer.nextToken().equals("1")) {
            final String minorVersion = tokenizer.nextToken();
            if (minorVersion.equals("0")) {
                return true;
            }
            if (minorVersion.equals("1")) {
                return true;
            }
            if (minorVersion.equals("2")) {
                return true;
            }
            if (minorVersion.equals("3")) {
                return true;
            }
        }
        return false;
    }
}
