/*
 * 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 static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assume.assumeTrue;

import java.beans.IndexedPropertyDescriptor;
import java.beans.PropertyDescriptor;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.beanutils2.bugs.other.Jira492IndexedListsSupport;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;


/**
 * <p>Test Case for the Indexed Properties.</p>
 *
 */

public class IndexedPropertyTestCase {

    

    /**
     * The test bean for each test.
     */
    private IndexedTestBean bean = null;
    private BeanUtilsBean beanUtilsBean;
    private PropertyUtilsBean propertyUtilsBean;
    private String[] testArray;
    private String[] newArray;
    private List<String> testList;
    private List<Object> newList;
    private ArrayList<Object> arrayList;


    


    /**
     * Set up instance variables required by this test case.
     */
    @Before
    public void setUp() {

        // BeanUtils
        beanUtilsBean = new BeanUtilsBean();
        propertyUtilsBean = beanUtilsBean.getPropertyUtils();

        // initialize Arrays and Lists
        testArray= new String[] {"array-0", "array-1", "array-2"};
        newArray = new String[]  {"newArray-0", "newArray-1", "newArray-2"};

        testList = new ArrayList<>();
        testList.add("list-0");
        testList.add("list-1");
        testList.add("list-2");

        newList = new ArrayList<>();
        newList.add("newList-0");
        newList.add("newList-1");
        newList.add("newList-2");

        arrayList = new ArrayList<>();
        arrayList.add("arrayList-0");
        arrayList.add("arrayList-1");
        arrayList.add("arrayList-2");

        // initialize Test Bean  properties
        bean = new IndexedTestBean();
        bean.setStringArray(testArray);
        bean.setStringList(testList);
        bean.setArrayList(arrayList);
    }

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


    

    /**
     * Test IndexedPropertyDescriptor for an Array
     */
    @Test
    public void testArrayIndexedPropertyDescriptor() throws Exception {
        final PropertyDescriptor descriptor = propertyUtilsBean.getPropertyDescriptor(bean, "stringArray");
        assertNotNull("No Array Descriptor", descriptor);
        assertEquals("Not IndexedPropertyDescriptor",
                     IndexedPropertyDescriptor.class,
                     descriptor.getClass());
        assertEquals("PropertDescriptor Type invalid",
                     testArray.getClass(),
                     descriptor.getPropertyType());
    }

    /**
     * Test IndexedPropertyDescriptor for a List
     */
    @Test
    public void testListIndexedPropertyDescriptor() throws Exception {
        final PropertyDescriptor descriptor = propertyUtilsBean.getPropertyDescriptor(bean, "stringList");
        assertNotNull("No List Descriptor", descriptor);
        if (Jira492IndexedListsSupport.supportsIndexedLists()) {
            // BEANUTILS-492 - can't assume lists are handled as arrays in Java 8+
            assertEquals("Not IndexedPropertyDescriptor",
                         IndexedPropertyDescriptor.class, descriptor.getClass());
        }
        assertEquals("PropertDescriptor Type invalid",
                     List.class,
                     descriptor.getPropertyType());
    }

    /**
     * Test IndexedPropertyDescriptor for an ArrayList
     */
    @Test
    public void testArrayListIndexedPropertyDescriptor() throws Exception {
        final PropertyDescriptor descriptor = propertyUtilsBean.getPropertyDescriptor(bean, "arrayList");
        assertNotNull("No ArrayList Descriptor", descriptor);
        if (Jira492IndexedListsSupport.supportsIndexedLists()) {
            assertEquals("Not IndexedPropertyDescriptor",
                    IndexedPropertyDescriptor.class, descriptor.getClass());
        }
        assertEquals("PropertDescriptor Type invalid",
                     ArrayList.class,
                     descriptor.getPropertyType());
    }

    /**
     * Test Read Method for an Array
     */
    @Test
    public void testArrayReadMethod() throws Exception {
        final PropertyDescriptor descriptor =
             propertyUtilsBean.getPropertyDescriptor(bean, "stringArray");
        assertNotNull("No Array Read Method", descriptor.getReadMethod());
    }

    /**
     * Test Write Method for an Array
     */
    @Test
    public void testArrayWriteMethod() throws Exception {
        final PropertyDescriptor descriptor =
             propertyUtilsBean.getPropertyDescriptor(bean, "stringArray");
        assertNotNull("No Array Write Method", descriptor.getWriteMethod());
    }

    /**
     * Test Indexed Read Method for an Array
     */
    @Test
    public void testArrayIndexedReadMethod() throws Exception {
        final IndexedPropertyDescriptor descriptor =
             (IndexedPropertyDescriptor)propertyUtilsBean.getPropertyDescriptor(bean, "stringArray");
        assertNotNull("No Array Indexed Read Method", descriptor.getIndexedReadMethod());
    }

    /**
     * Test Indexed Write Method for an Array
     */
    @Test
    public void testArrayIndexedWriteMethod() throws Exception {
        final IndexedPropertyDescriptor descriptor =
             (IndexedPropertyDescriptor)propertyUtilsBean.getPropertyDescriptor(bean, "stringArray");
        assertNotNull("No Array Indexed Write Method", descriptor.getIndexedWriteMethod());
    }

    /**
     * Test Read Method for a List
     *
     * JDK 1.3.1_04: Test Passes
     * JDK 1.4.2_05: Test Fails - getter which returns java.util.List not returned
     *                            by IndexedPropertyDescriptor.getReadMethod();
     */
    @Test
    public void testListReadMethod() throws Exception {
        final PropertyDescriptor descriptor =
             propertyUtilsBean.getPropertyDescriptor(bean, "stringList");
        assertNotNull("No List Read Method", descriptor.getReadMethod());
    }

    /**
     * Test Write Method for a List
     *
     * JDK 1.3.1_04: Test Passes
     * JDK 1.4.2_05: Test Fails - setter whith java.util.List argument not returned
     *                            by IndexedPropertyDescriptor.getWriteMethod();
     */
    @Test
    public void testListWriteMethod() throws Exception {
        final PropertyDescriptor descriptor =
             propertyUtilsBean.getPropertyDescriptor(bean, "stringList");
        assertNotNull("No List Write Method", descriptor.getWriteMethod());
    }

    /**
     * Test Indexed Read Method for a List
     */
    @Test
    public void testListIndexedReadMethod() throws Exception {
        final PropertyDescriptor descriptor = propertyUtilsBean.getPropertyDescriptor(bean, "stringList");
        assertNotNull("stringList descriptor not found", descriptor);
        assumeTrue("JDK does not support index bean properties on java.util.List",
                Jira492IndexedListsSupport.supportsIndexedLists());
        assertNotNull("No List Indexed Read Method",  ((IndexedPropertyDescriptor)descriptor).getIndexedReadMethod());
    }

    /**
     * Test Indexed Write Method for a List
     */
    @Test
    public void testListIndexedWriteMethod() throws Exception {
        final PropertyDescriptor descriptor = propertyUtilsBean.getPropertyDescriptor(bean, "stringList");
        assertNotNull("stringList descriptor not found", descriptor);
        assumeTrue("JDK does not support index bean properties on java.util.List",
                Jira492IndexedListsSupport.supportsIndexedLists());
        assertNotNull("No List Indexed Write Method", ((IndexedPropertyDescriptor)descriptor).getIndexedWriteMethod());
    }

    /**
     * Test Read Method for an ArrayList
     */
    @Test
    public void testArrayListReadMethod() throws Exception {
        final PropertyDescriptor descriptor =
             propertyUtilsBean.getPropertyDescriptor(bean, "arrayList");
        assertNotNull("No ArrayList Read Method", descriptor.getReadMethod());
    }

    /**
     * Test Write Method for an ArrayList
     */
    @Test
    public void testArrayListWriteMethod() throws Exception {
        final PropertyDescriptor descriptor =
             propertyUtilsBean.getPropertyDescriptor(bean, "arrayList");
        assertNotNull("No ArrayList Write Method", descriptor.getWriteMethod());
    }

    /**
     * Test getting an array property
     */
    @Test
    public void testGetArray() throws Exception {
        assertEquals(testArray,
                     propertyUtilsBean.getProperty(bean, "stringArray"));
    }

    /**
     * Test getting an array property as a String
     *
     * NOTE: Why does retrieving array just return the first element in the array, whereas
     *       retrieveing a List returns a comma separated list of all the elements?
     */
    @Test
    public void testGetArrayAsString() throws Exception {
        assertEquals("array-0",
                     beanUtilsBean.getProperty(bean, "stringArray"));
    }

    /**
     * Test getting an indexed item of an Array using getProperty("name[x]")
     */
    @Test
    public void testGetArrayItemA() throws Exception {
        assertEquals("array-1",
                     beanUtilsBean.getProperty(bean, "stringArray[1]"));
    }

    /**
     * Test getting an indexed item of an Array using getIndexedProperty("name")
     */
    @Test
    public void testGetArrayItemB() throws Exception {
        assertEquals("array-1",
                     beanUtilsBean.getIndexedProperty(bean, "stringArray", 1));
    }

    /**
     * Test getting a List
     *
     * JDK 1.3.1_04: Test Passes
     * JDK 1.4.2_05: Test Fails - fails NoSuchMethodException, i.e. reason as testListReadMethod()
     *                            failed.
     */
    @Test
    public void testGetList() throws Exception {
        assertEquals(testList,
                     propertyUtilsBean.getProperty(bean, "stringList"));
    }

    /**
     * Test getting a List property as a String
     *
     * JDK 1.3.1_04: Test Passes
     * JDK 1.4.2_05: Test Fails - fails NoSuchMethodException, i.e. reason as testListReadMethod()
     *                            failed.
     */
    @Test
    public void testGetListAsString() throws Exception {
        assertEquals("list-0",
                     beanUtilsBean.getProperty(bean, "stringList"));
    }

    /**
     * Test getting an indexed item of a List using getProperty("name[x]")
     */
    @Test
    public void testGetListItemA() throws Exception {
        assertEquals("list-1",
                     beanUtilsBean.getProperty(bean, "stringList[1]"));
    }

    /**
     * Test getting an indexed item of a List using getIndexedProperty("name")
     */
    @Test
    public void testGetListItemB() throws Exception {
        assertEquals("list-1",
                     beanUtilsBean.getIndexedProperty(bean, "stringList", 1));
    }

    /**
     * Test setting an Array property
     *
     * JDK 1.3.1_04 and 1.4.2_05: Test Fails - IllegalArgumentException can't invoke setter, argument type mismatch
     *
     * Fails because of a bug in BeanUtilsBean.setProperty() method. Value is always converted to the array's component
     * type which in this case is a String. Then it calls the setStringArray(String[]) passing a String rather than
     * String[] causing this exception. If there isn't an "index" value then the PropertyType (rather than
     * IndexedPropertyType) should be used.
     *
     */
    @Test
    public void testSetArray() throws Exception {
        beanUtilsBean.setProperty(bean, "stringArray", newArray);
        final Object value = bean.getStringArray();
        assertEquals("Type is different", newArray.getClass(), value.getClass());
        final String[] array = (String[])value;
        assertEquals("Array Length is different", newArray.length, array.length);
        for (int i = 0; i < array.length; i++) {
            assertEquals("Element " + i + " is different", newArray[i], array[i]);
        }
    }


    /**
     * Test setting an indexed item of an Array using setProperty("name[x]", value)
     */
    @Test
    public void testSetArrayItemA() throws Exception {
        beanUtilsBean.setProperty(bean, "stringArray[1]", "modified-1");
        assertEquals("modified-1", bean.getStringArray(1));
    }

    /**
     * Test setting an indexed item of an Array using setIndexedProperty("name", value)
     */
    @Test
    public void testSetArrayItemB() throws Exception {
        propertyUtilsBean.setIndexedProperty(bean, "stringArray", 1, "modified-1");
        assertEquals("modified-1", bean.getStringArray(1));
    }

    /**
     * Test setting a List property
     *
     * JDK 1.3.1_04: Test Passes
     * JDK 1.4.2_05: Test Fails - setter which returns java.util.List not returned
     *                            by IndexedPropertyDescriptor.getWriteMethod() - therefore
     *                            setProperty does nothing and values remain unchanged.
     */
    @Test
    public void testSetList() throws Exception {
        beanUtilsBean.setProperty(bean, "stringList", newList);
        final Object value = bean.getStringList();
        assertEquals("Type is different", newList.getClass(), value.getClass());
        final List<?> list  = (List<?>)value;
        assertEquals("List size is different", newList.size(), list.size());
        for (int i = 0; i < list.size(); i++) {
            assertEquals("Element " + i + " is different", newList.get(i), list.get(i));
        }
    }


    /**
     * Test setting an indexed item of a List using setProperty("name[x]", value)
     */
    @Test
    public void testSetListItemA() throws Exception {
        beanUtilsBean.setProperty(bean, "stringList[1]", "modified-1");
        assertEquals("modified-1", bean.getStringList(1));
    }

    /**
     * Test setting an indexed item of a List using setIndexedProperty("name", value)
     */
    @Test
    public void testSetListItemB() throws Exception {
        propertyUtilsBean.setIndexedProperty(bean, "stringList", 1, "modified-1");
        assertEquals("modified-1", bean.getStringList(1));
    }


    /**
     * Test getting an ArrayList
     */
    @Test
    public void testGetArrayList() throws Exception {
        assertEquals(arrayList,
                     propertyUtilsBean.getProperty(bean, "arrayList"));
    }

    /**
     * Test setting an ArrayList property
     */
    @Test
    public void testSetArrayList() throws Exception {
        beanUtilsBean.setProperty(bean, "arrayList", newList);
        final Object value = bean.getArrayList();
        assertEquals("Type is different", newList.getClass(), value.getClass());
        final List<?> list  = (List<?>)value;
        assertEquals("List size is different", newList.size(), list.size());
        for (int i = 0; i < list.size(); i++) {
            assertEquals("Element " + i + " is different", newList.get(i), list.get(i));
        }
    }

}
