/*
 * 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.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.TreeMap;

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

/**
 * <p>Test Case for the {@code LazyDynaBean} implementation class.</p>
 *
 */
public class LazyDynaBeanTestCase extends TestCase {

    protected LazyDynaBean  bean      = null;
    protected LazyDynaClass dynaClass = null;
    protected String testProperty     = "myProperty";
    protected String testPropertyA    = "myProperty-A";
    protected String testPropertyB    = "myProperty-B";
    protected String testString1      = "myStringValue-1";
    protected String testString2      = "myStringValue-2";
    protected Integer testInteger1    = new Integer(30);
    protected Integer testInteger2    = new Integer(40);
    protected String testKey          = "myKey";

    

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

    

    /**
     * Run thus Test
     */
    public static void main(final String[] args) {
        junit.textui.TestRunner.run(suite());
    }

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

    /**
     * Set up instance variables required by this test case.
     */
    @Override
    public void setUp() throws Exception {
        bean = new LazyDynaBean();
        dynaClass = (LazyDynaClass)bean.getDynaClass();
        dynaClass.setReturnNull(true);
    }

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

    

    /**
     * Test Getting/Setting a Simple Property
     */
    public void testSimpleProperty() {

        // Check the property & value doesn't exist
        assertNull("Check Property doesn't exist", dynaClass.getDynaProperty(testProperty));
        assertNull("Check Value is null", bean.get(testProperty));

        // Set a new property - should add new property and set value
        bean.set(testProperty, testInteger1);
        assertEquals("Check First Value is correct", testInteger1, bean.get(testProperty));
        assertEquals("Check Property type is correct", Integer.class, dynaClass.getDynaProperty(testProperty).getType());

        // Set the property again - should set the new value
        bean.set(testProperty, testInteger2);
        assertEquals("Check Second Value is correct", testInteger2, bean.get(testProperty));

        // Set the property again - with a different type, should fail
        try {
            bean.set(testProperty, testString1);
            fail("expected ConversionException trying to set an Integer property to a String");
        } catch (final ConversionException expected) {
            // expected result
        }

    }

    /**
     * Test Getting/Setting a 'null' Property
     */
    public void testNullProperty() {

        // Check the property & value doesn't exist
        assertNull("Check Property doesn't exist", dynaClass.getDynaProperty(testProperty));
        assertNull("Check Value is null", bean.get(testProperty));

        // Set a new property to null
        bean.set(testProperty, null);
        assertNull("Check Value is still null", bean.get(testProperty));

    }

    /**
     * Test Setting a Simple Property when MutableDynaClass is set to restricted
     */
    public void testSimplePropertyRestricted() {

        // Set the MutableDyanClass to 'restricted' (i.e. no new properties cab be added
        dynaClass.setRestricted(true);
        assertTrue("Check MutableDynaClass is restricted", dynaClass.isRestricted());

        // Check the property & value doesn't exist
        assertNull("Check Property doesn't exist", dynaClass.getDynaProperty(testProperty));
        assertNull("Check Value is null", bean.get(testProperty));

        // Set the property - should fail because property doesn't exist and MutableDynaClass is restricted
        try {
            bean.set(testProperty, testString1);
            fail("expected IllegalArgumentException trying to add new property to restricted DynaClass");
        } catch (final IllegalArgumentException expected) {
            // expected result
        }

    }

    /**
     * Test Getting/Setting a 'Mapped' Property - default HashMap property
     */
    public void testMappedPropertyDefault() {

        // Check the property & value doesn't exist
        assertNull("Check Mapped Property doesn't exist", dynaClass.getDynaProperty(testProperty));
        assertNull("Check Map is null", bean.get(testProperty));
        assertNull("Check Mapped Value is null", bean.get(testProperty, testKey));

        // Set a new mapped property - should add new HashMap property and set the mapped value
        bean.set(testProperty, testKey, testInteger1);
        assertEquals("Check Mapped Property exists", HashMap.class, bean.get(testProperty).getClass());
        assertEquals("Check First Mapped Value is correct(a)", testInteger1, bean.get(testProperty, testKey));
        assertEquals("Check First Mapped Value is correct(b)", testInteger1, ((HashMap<?, ?>)bean.get(testProperty)).get(testKey));

        // Set the property again - should set the new value
        bean.set(testProperty, testKey, testInteger2);
        assertEquals("Check Second Mapped Value is correct(a)", testInteger2, bean.get(testProperty, testKey));
        assertEquals("Check Second Mapped Value is correct(b)", testInteger2, ((HashMap<?, ?>)bean.get(testProperty)).get(testKey));
    }

    /**
     * Test Getting/Setting a 'Mapped' Property - use TreeMap property
     */
    public void testMappedPropertyTreeMap() {

        // Check the property & value doesn't exist
        assertNull("Check Mapped Property doesn't exist", dynaClass.getDynaProperty(testProperty));

        // Add a 'TreeMap' property to the DynaClass
        dynaClass.add(testProperty, TreeMap.class);
        assertTrue("Check Property is mapped", dynaClass.getDynaProperty(testProperty).isMapped());
        assertEquals("Check Property is correct type", TreeMap.class, dynaClass.getDynaProperty(testProperty).getType());
        assertEquals("Check Mapped Property exists", TreeMap.class, bean.get(testProperty).getClass());
//        assertNull("Check mapped property is null", bean.get(testProperty));

        // Set a new mapped property - should instatiate a new TreeMap property and set the mapped value
        bean.set(testProperty, testKey, testInteger1);
        assertEquals("Check Mapped Property exists", TreeMap.class, bean.get(testProperty).getClass());
        assertEquals("Check First Mapped Value is correct(a)", testInteger1, bean.get(testProperty, testKey));
        assertEquals("Check First Mapped Value is correct(b)", testInteger1, ((TreeMap<?, ?>)bean.get(testProperty)).get(testKey));

        // Set the property again - should set the new value
        bean.set(testProperty, testKey, testInteger2);
        assertEquals("Check Second Mapped Value is correct(a)", testInteger2, bean.get(testProperty, testKey));
        assertEquals("Check Second Mapped Value is correct(b)", testInteger2, ((TreeMap<?, ?>)bean.get(testProperty)).get(testKey));
    }

    /**
     * Test Setting a 'Mapped' Property using PropertyUtils
     */
    public void testMappedPropertyUtils() {

        dynaClass.setReturnNull(false);

        // Check the property & value doesn't exist
        assertFalse("Check Mapped Property doesn't exist", dynaClass.isDynaProperty(testProperty));
        assertNull("Check Map is null", bean.get(testProperty));
        assertNull("Check Mapped Value is null", bean.get(testProperty, testKey));

        // Set the mapped property using PropertyUtils
        try {
          PropertyUtils.setProperty(bean, testProperty+"("+testKey+")", testString1);
        }
        catch (final NoSuchMethodException ex) {
            fail("testIndexedPropertyUtils threw "+ex);
        }
        catch (final InvocationTargetException ex) {
            fail("testIndexedPropertyUtils threw "+ex);
        }
        catch (final IllegalAccessException ex) {
            fail("testIndexedPropertyUtils threw "+ex);
        }

        // Check property value correctly set
        assertEquals("Check Mapped Bean Value is correct", testString1, bean.get(testProperty, testKey));

    }

    /**
     * Test Setting a Mapped Property when MutableDynaClass is set to restricted
     */
    public void testMappedPropertyRestricted() {

        // Set the MutableDyanClass to 'restricted' (i.e. no new properties cab be added
        dynaClass.setRestricted(true);
        assertTrue("Check MutableDynaClass is restricted", dynaClass.isRestricted());

        // Check the property & value doesn't exist
        assertNull("Check Property doesn't exist", dynaClass.getDynaProperty(testProperty));
        assertNull("Check Value is null", bean.get(testProperty));

        // Set the property - should fail because property doesn't exist and MutableDynaClass is restricted
        try {
            bean.set(testProperty, testKey, testInteger1);
            fail("expected IllegalArgumentException trying to add new property to restricted MutableDynaClass");
        } catch (final IllegalArgumentException expected) {
            // expected result
        }

    }

    /**
     * Test setting mapped property for type which is not Map
     */
    public void testMappedInvalidType() {
        dynaClass.add(testProperty, String.class);
        assertFalse("Check Property is not mapped", dynaClass.getDynaProperty(testProperty).isMapped());
        try {
            bean.set(testProperty, testKey, testInteger1);
            fail("set(property, key, value) should have thrown IllegalArgumentException");
        } catch (final IllegalArgumentException expected) {
            // expected result
        }
    }

    /**
     * Test Getting/Setting an 'Indexed' Property - default ArrayList property
     */
    public void testIndexedPropertyDefault() {

        int index = 3;

        // Check the property & value doesn't exist
        assertNull("Check Indexed Property doesn't exist", dynaClass.getDynaProperty(testProperty));
        assertNull("Check Indexed Property is null", bean.get(testProperty));
        assertNull("Check Indexed value is null", bean.get(testProperty, index));

        // Set the property, should create new ArrayList and set appropriate indexed value
        bean.set(testProperty, index, testInteger1);
        assertNotNull("Check Indexed Property is not null", bean.get(testProperty));
        assertEquals("Check Indexed Property is correct type", ArrayList.class, bean.get(testProperty).getClass());
        assertEquals("Check First Indexed Value is correct", testInteger1, bean.get(testProperty, index));
        assertEquals("Check First Array length is correct", new Integer(index+1),  new Integer(((ArrayList<?>)bean.get(testProperty)).size()));

        // Set a second indexed value, should automatically grow the ArrayList and set appropriate indexed value
        index = index + 2;
        bean.set(testProperty, index, testString1);
        assertEquals("Check Second Indexed Value is correct", testString1, bean.get(testProperty, index));
        assertEquals("Check Second Array length is correct", new Integer(index+1),  new Integer(((ArrayList<?>)bean.get(testProperty)).size()));
    }

    /**
     * Test Getting/Setting a List 'Indexed' Property - use alternative List (LinkedList)
     */
    public void testIndexedLinkedList() {

        int   index     = 3;

        // Check the property & value doesn't exist
        assertNull("Check Indexed Property doesn't exist", dynaClass.getDynaProperty(testProperty));
        assertNull("Check Indexed Property is null", bean.get(testProperty));

        // Add a 'LinkedList' property to the DynaClass
        dynaClass.add(testProperty, LinkedList.class);
        assertTrue("Check Property is indexed", dynaClass.getDynaProperty(testProperty).isIndexed());
        assertEquals("Check Property is correct type", LinkedList.class, dynaClass.getDynaProperty(testProperty).getType());
        assertEquals("Check Property type is correct", LinkedList.class, bean.get(testProperty).getClass());

        // Set the property, should instantiate a new LinkedList and set appropriate indexed value
        bean.set(testProperty, index, testString1);
        assertEquals("Check Property type is correct", LinkedList.class, bean.get(testProperty).getClass());
        assertEquals("Check First Indexed Value is correct", testString1, bean.get(testProperty, index));
        assertEquals("Check First Array length is correct", new Integer(index+1),  new Integer(((LinkedList<?>)bean.get(testProperty)).size()));

        // Set a second indexed value, should automatically grow the LinkedList and set appropriate indexed value
        index = index + 2;
        bean.set(testProperty, index, testInteger1);
        assertEquals("Check Second Indexed Value is correct", testInteger1, bean.get(testProperty, index));
        assertEquals("Check Second Array length is correct", new Integer(index+1),  new Integer(((LinkedList<?>)bean.get(testProperty)).size()));
    }

    /**
     * Test Getting/Setting a primitive array 'Indexed' Property - use int[]
     */
    public void testIndexedPrimitiveArray() {

        int   index     = 3;
        final int[] primitiveArray = new int[0];

        // Check the property & value doesn't exist
        assertNull("Check Indexed Property doesn't exist", dynaClass.getDynaProperty(testProperty));
        assertNull("Check Indexed Property is null", bean.get(testProperty));

        // Add a DynaProperty of type int[]
        dynaClass.add(testProperty, primitiveArray.getClass());
        assertEquals("Check Indexed Property exists", primitiveArray.getClass(), dynaClass.getDynaProperty(testProperty).getType());
        assertEquals("Check Indexed Property is correct type", primitiveArray.getClass(), bean.get(testProperty).getClass());

        // Set an indexed value
        bean.set(testProperty, index, testInteger1);
        assertNotNull("Check Indexed Property is not null", bean.get(testProperty));
        assertEquals("Check Indexed Property is correct type", primitiveArray.getClass(), bean.get(testProperty).getClass());
        assertEquals("Check First Indexed Value is correct(a)", testInteger1, bean.get(testProperty, index));
        assertEquals("Check First Indexed Value is correct(b)", testInteger1, new Integer(((int[])bean.get(testProperty))[index]));
        assertEquals("Check Array length is correct", new Integer(index+1),  new Integer(((int[])bean.get(testProperty)).length));

        // Set a second indexed value, should automatically grow the int[] and set appropriate indexed value
        index = index + 2;
        bean.set(testProperty, index, testInteger2);
        assertEquals("Check Second Indexed Value is correct(a)", testInteger2, bean.get(testProperty, index));
        assertEquals("Check Second Indexed Value is correct(b)", testInteger2, new Integer(((int[])bean.get(testProperty))[index]));
        assertEquals("Check Second Array length is correct", new Integer(index+1),  new Integer(((int[])bean.get(testProperty)).length));

    }

    /**
     * Test Getting/Setting an Object array 'Indexed' Property - use String[]
     */
    public void testIndexedObjectArray() {

        int   index     = 3;
        final Object objectArray = new String[0];

        // Check the property & value doesn't exist
        assertNull("Check Indexed Property doesn't exist", dynaClass.getDynaProperty(testProperty));
        assertNull("Check Indexed Property is null", bean.get(testProperty));

        // Add a DynaProperty of type String[]
        dynaClass.add(testProperty, objectArray.getClass());
        assertEquals("Check Indexed Property exists", objectArray.getClass(), dynaClass.getDynaProperty(testProperty).getType());
        assertEquals("Check Indexed Property is correct type", objectArray.getClass(), bean.get(testProperty).getClass());

        // Set an indexed value
        bean.set(testProperty, index, testString1);
        assertNotNull("Check Indexed Property is not null", bean.get(testProperty));
        assertEquals("Check Indexed Property is correct type", objectArray.getClass(), bean.get(testProperty).getClass());
        assertEquals("Check First Indexed Value is correct(a)", testString1, bean.get(testProperty, index));
        assertEquals("Check First Indexed Value is correct(b)", testString1, ((String[])bean.get(testProperty))[index]);
        assertEquals("Check Array length is correct", new Integer(index+1),  new Integer(((String[])bean.get(testProperty)).length));

        // Set a second indexed value, should automatically grow the String[] and set appropriate indexed value
        index = index + 2;
        bean.set(testProperty, index, testString2);
        assertEquals("Check Second Indexed Value is correct(a)", testString2, bean.get(testProperty, index));
        assertEquals("Check Second Indexed Value is correct(b)", testString2, ((String[])bean.get(testProperty))[index]);
        assertEquals("Check Second Array length is correct", new Integer(index+1),  new Integer(((String[])bean.get(testProperty)).length));
    }

    /**
     * Test Getting/Setting an DynaBean[] array
     */
    public void testIndexedDynaBeanArray() {

        final int   index     = 3;
        final Object objectArray = new LazyDynaMap[0];

        // Check the property & value doesn't exist
        assertNull("Check Indexed Property doesn't exist", dynaClass.getDynaProperty(testProperty));
        assertNull("Check Indexed Property is null", bean.get(testProperty));

        // Add a DynaProperty of type String[]
        dynaClass.add(testProperty, objectArray.getClass());
        assertEquals("Check Indexed Property exists", objectArray.getClass(), dynaClass.getDynaProperty(testProperty).getType());
        assertEquals("Check Indexed Property is correct type", objectArray.getClass(), bean.get(testProperty).getClass());

        // Retrieving from Array should initialize DynaBean
        for (int i = index; i >= 0; i--) {
            assertEquals("Check Array Components initialized", LazyDynaMap.class, bean.get(testProperty, index).getClass());
        }

        dynaClass.add(testPropertyB, objectArray.getClass());
        final LazyDynaMap newMap = new LazyDynaMap();
        newMap.set(testPropertyB, testString2);
        bean.set(testPropertyA, index, newMap);
        assertEquals("Check Indexed Value is correct(a)", testString2, ((DynaBean)bean.get(testPropertyA, index)).get(testPropertyB));

    }

    /**
     * Test Setting an 'Indexed' Property using PropertyUtils
     */
    public void testIndexedPropertyUtils() {

        final int   index     = 3;
        dynaClass.setReturnNull(false);

        // Check the property & value doesn't exist
        assertFalse("Check Indexed Property doesn't exist", dynaClass.isDynaProperty(testProperty));
        assertNull("Check Indexed Property is null", bean.get(testProperty));
        assertNull("Check Indexed value is null", bean.get(testProperty, index));

        // Use PropertyUtils to set the indexed value
        try {
          PropertyUtils.setProperty(bean, testProperty+"["+index+"]", testString1);
        }
        catch (final NoSuchMethodException ex) {
            fail("testIndexedPropertyUtils threw "+ex);
        }
        catch (final InvocationTargetException ex) {
            fail("testIndexedPropertyUtils threw "+ex);
        }
        catch (final IllegalAccessException ex) {
            fail("testIndexedPropertyUtils threw "+ex);
        }

        // Check property value correctly set
        assertEquals("Check Indexed Bean Value is correct", testString1, bean.get(testProperty, index));

    }

    /**
     * Test Setting an Indexed Property when MutableDynaClass is set to restricted
     */
    public void testIndexedPropertyRestricted() {

        final int   index     = 3;

        // Set the MutableDyanClass to 'restricted' (i.e. no new properties cab be added
        dynaClass.setRestricted(true);
        assertTrue("Check MutableDynaClass is restricted", dynaClass.isRestricted());

        // Check the property & value doesn't exist
        assertNull("Check Property doesn't exist", dynaClass.getDynaProperty(testProperty));
        assertNull("Check Value is null", bean.get(testProperty));

        // Set the property - should fail because property doesn't exist and MutableDynaClass is restricted
        try {
            bean.set(testProperty, index, testInteger1);
            fail("expected IllegalArgumentException trying to add new property to restricted MutableDynaClass");
        } catch (final IllegalArgumentException expected) {
            // expected result
        }

    }

    /**
     * Test setting indexed property for type which is not List or Array
     */
    public void testIndexedInvalidType() {
        final int   index     = 3;
        dynaClass.add(testProperty, String.class);
        assertFalse("Check Property is not indexed", dynaClass.getDynaProperty(testProperty).isIndexed());
        try {
            bean.set(testProperty, index, testString1);
            fail("set(property, index, value) should have thrown IllegalArgumentException");
        } catch (final IllegalArgumentException expected) {
            // expected result
        }
    }

}