/*
 * 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.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;

import org.apache.commons.beanutils2.bugs.other.Jira87BeanFactory;
import org.apache.commons.collections.BulkTest;
import org.apache.commons.collections.map.AbstractTestMap;

import junit.framework.Test;
import junit.textui.TestRunner;

/**
 * Test cases for BeanMap
 *
 * @version $Id$
 */
@SuppressWarnings("deprecation")
public class BeanMapTestCase extends AbstractTestMap {

    public BeanMapTestCase(final String testName) {
        super(testName);
    }

    public static void main(final String[] args) {
        TestRunner.run(suite());
    }

    public static Test suite() {
        return BulkTest.makeSuite(BeanMapTestCase.class);
    }

/*
  note to self.  The getter and setter methods were generated by copying the
  field declarations and using the following regular expression search and
  replace:

  From:
        private \(.*\) some\(.*\);
  To:
        public \1 getSome\2Value() {
            return some\2;
        }
        public void setSome\2Value(\1 value) {
            some\2 = value;
        }

  Also note:  The sample keys and mappings were generated manually.
*/


    public static class BeanWithProperties implements Serializable {
        private int someInt;
        private long someLong;
        private double someDouble;
        private float someFloat;
        private short someShort;
        private byte someByte;
        private char someChar;
        private Integer someInteger;
        private String someString;
        private Object someObject;

        public int getSomeIntValue() {
            return someInt;
        }
        public void setSomeIntValue(final int value) {
            someInt = value;
        }

        public long getSomeLongValue() {
            return someLong;
        }
        public void setSomeLongValue(final long value) {
            someLong = value;
        }

        public double getSomeDoubleValue() {
            return someDouble;
        }
        public void setSomeDoubleValue(final double value) {
            someDouble = value;
        }

        public float getSomeFloatValue() {
            return someFloat;
        }
        public void setSomeFloatValue(final float value) {
            someFloat = value;
        }

        public short getSomeShortValue() {
            return someShort;
        }
        public void setSomeShortValue(final short value) {
            someShort = value;
        }

        public byte getSomeByteValue() {
            return someByte;
        }
        public void setSomeByteValue(final byte value) {
            someByte = value;
        }

        public char getSomeCharValue() {
            return someChar;
        }
        public void setSomeCharValue(final char value) {
            someChar = value;
        }

        public String getSomeStringValue() {
            return someString;
        }
        public void setSomeStringValue(final String value) {
            someString = value;
        }

        public Integer getSomeIntegerValue() {
            return someInteger;
        }
        public void setSomeIntegerValue(final Integer value) {
            someInteger = value;
        }

        public Object getSomeObjectValue() {
            return someObject;
        }
        public void setSomeObjectValue(final Object value) {
            someObject = value;
        }
    }

    public static class BeanThrowingExceptions extends BeanWithProperties {
        private static final long serialVersionUID = 1L;
        public void setValueThrowingException(final String value) {
            throw new TestException();
        }
        public String getValueThrowingException() {
            throw new TestException();
        }
    }

    /**
     * Exception for testing exception handling.
     */
    public static class TestException extends RuntimeException {
        private static final long serialVersionUID = 1L;
    }

    // note to self.  The Sample keys were generated by copying the field
    // declarations and using the following regular expression search and replace:
    //
    // From:
    //    private \(.*\) some\(.*\);
    // To:
    //    "some\2Value",
    //
    // Then, I manually added the "class" key, which is a property that exists for
    // all beans (and all objects for that matter.
    @Override
    public Object[] getSampleKeys() {
        final Object[] keys = new Object[] {
            "someIntValue",
            "someLongValue",
            "someDoubleValue",
            "someFloatValue",
            "someShortValue",
            "someByteValue",
            "someCharValue",
            "someIntegerValue",
            "someStringValue",
            "someObjectValue",
            "class",
        };
        return keys;
    }

    /**
     *  An object value that will be stored in the bean map as a value.  Need
     *  to save this externally so that we can make sure the object instances
     *  are equivalent since getSampleValues() would otherwise construct a new
     *  and different Object each time.
     **/
    private final Object objectInFullMap = new Object();

    // note to self: the sample values were created manually
    @Override
    public Object[] getSampleValues() {
        final Object[] values = new Object[] {
            new Integer(1234),
            new Long(1298341928234L),
            new Double(123423.34),
            new Float(1213332.12f),
            new Short((short)134),
            new Byte((byte)10),
            new Character('a'),
            new Integer(1432),
            "SomeStringValue",
            objectInFullMap,
            BeanWithProperties.class,
        };
        return values;
    }

    @Override
    public Object[] getNewSampleValues() {
        final Object[] values = new Object[] {
            new Integer(223),
            new Long(23341928234L),
            new Double(23423.34),
            new Float(213332.12f),
            new Short((short)234),
            new Byte((byte)20),
            new Character('b'),
            new Integer(232),
            "SomeNewStringValue",
            new Object(),
            null,
        };
        return values;
    }

    /**
     * Values is a dead copy in BeanMap, so refresh each time.
     */
    @Override
    public void verifyValues() {
        values = map.values();
        super.verifyValues();
    }

    /**
     * The mappings in a BeanMap are fixed on the properties the underlying
     * bean has.  Adding and removing mappings is not possible, thus this
     * method is overridden to return false.
     */
    @Override
    public boolean isPutAddSupported() {
        return false;
    }

    /**
     * The mappings in a BeanMap are fixed on the properties the underlying
     * bean has.  Adding and removing mappings is not possible, thus this
     * method is overridden to return false.
     */
    @Override
    public boolean isRemoveSupported() {
        return false;
    }

    @Override
    public Map<Object, Object> makeFullMap() {
        // note: These values must match (i.e. .equals() must return true)
        // those returned from getSampleValues().
        final BeanWithProperties bean = new BeanWithProperties();
        bean.setSomeIntValue(1234);
        bean.setSomeLongValue(1298341928234L);
        bean.setSomeDoubleValue(123423.34);
        bean.setSomeFloatValue(1213332.12f);
        bean.setSomeShortValue((short)134);
        bean.setSomeByteValue((byte)10);
        bean.setSomeCharValue('a');
        bean.setSomeIntegerValue(new Integer(1432));
        bean.setSomeStringValue("SomeStringValue");
        bean.setSomeObjectValue(objectInFullMap);
        return new BeanMap(bean);
    }

    @Override
    public Map<Object, Object> makeEmptyMap() {
        return new BeanMap();
    }

    @Override
    public String[] ignoredTests() {
        // Ignore the serialization tests on collection views.
        return new String[] {
         "TestBeanMap.bulkTestMapEntrySet.testCanonicalEmptyCollectionExists",
         "TestBeanMap.bulkTestMapEntrySet.testCanonicalFullCollectionExists",
         "TestBeanMap.bulkTestMapKeySet.testCanonicalEmptyCollectionExists",
         "TestBeanMap.bulkTestMapKeySet.testCanonicalFullCollectionExists",
         "TestBeanMap.bulkTestMapValues.testCanonicalEmptyCollectionExists",
         "TestBeanMap.bulkTestMapValues.testCanonicalFullCollectionExists",
         "TestBeanMap.bulkTestMapEntrySet.testSimpleSerialization",
         "TestBeanMap.bulkTestMapKeySet.testSimpleSerialization",
         "TestBeanMap.bulkTestMapEntrySet.testSerializeDeserializeThenCompare",
         "TestBeanMap.bulkTestMapKeySet.testSerializeDeserializeThenCompare"
        };
    }

    /**
     * Need to override this method because the "clear()" method on the bean
     * map just returns the bean properties to their default states.  It does
     * not actually remove the mappings as per the map contract.  The default
     * testClear() methods checks that the clear method throws an
     * UnsupportedOperationException since this class is not add/remove
     * modifiable.  In our case though, we do not always throw that exception.
     */
    @Override
    public void testMapClear() {
        //TODO: make sure a call to BeanMap.clear returns the bean to its
        //default initialization values.
    }

    /**
     * Need to override this method because the "put()" method on the bean
     * doesn't work for this type of Map.
     */
    @Override
    public void testMapPut() {
        // see testBeanMapPutAllWriteable
    }

    public void testBeanMapClone() {
        final BeanMap map = (BeanMap)makeFullMap();
        try {
            final BeanMap map2 = (BeanMap)map.clone();

            // make sure containsKey is working to verify the bean was cloned
            // ok, and the read methods were properly initialized
            final Object[] keys = getSampleKeys();
            for (final Object key : keys) {
                assertTrue("Cloned BeanMap should contain the same keys",
                           map2.containsKey(key));
            }
        } catch (final CloneNotSupportedException exception) {
            fail("BeanMap.clone() should not throw a " +
                 "CloneNotSupportedException when clone should succeed.");
        }
    }

    public void testBeanMapPutAllWriteable() {
        final BeanMap map1 = (BeanMap)makeFullMap();
        final BeanMap map2 = (BeanMap)makeFullMap();
        map2.put("someIntValue", new Integer(0));
        map1.putAllWriteable(map2);
        assertEquals(map1.get("someIntValue"), new Integer(0));
    }

    public void testMethodAccessor() throws Exception {
        final BeanMap map = (BeanMap) makeFullMap();
        final Method method = BeanWithProperties.class.getDeclaredMethod("getSomeIntegerValue");
        assertEquals(method, map.getReadMethod("someIntegerValue"));
    }

    public void testMethodMutator() throws Exception {
        final BeanMap map = (BeanMap) makeFullMap();
        final Method method = BeanWithProperties.class.getDeclaredMethod("setSomeIntegerValue", new Class[] {Integer.class});
        assertEquals(method, map.getWriteMethod("someIntegerValue"));
    }

    /**
     *  Test the default transformers using the getTypeTransformer() method
     */
    public void testGetTypeTransformerMethod() {
        final BeanMap beanMap = new BeanMap();
        assertEquals("Boolean.TYPE",   Boolean.TRUE,        beanMap.getTypeTransformer(Boolean.TYPE).transform("true"));
        assertEquals("Character.TYPE", new Character('B'),  beanMap.getTypeTransformer(Character.TYPE).transform("BCD"));
        assertEquals("Byte.TYPE",      new Byte((byte)1),   beanMap.getTypeTransformer(Byte.TYPE).transform("1"));
        assertEquals("Short.TYPE",     new Short((short)2), beanMap.getTypeTransformer(Short.TYPE).transform("2"));
        assertEquals("Integer.TYPE",   new Integer(3),      beanMap.getTypeTransformer(Integer.TYPE).transform("3"));
        assertEquals("Long.TYPE",      new Long(4),         beanMap.getTypeTransformer(Long.TYPE).transform("4"));
        assertEquals("Float.TYPE",     new Float("5"),      beanMap.getTypeTransformer(Float.TYPE).transform("5"));
        assertEquals("Double.TYPE",    new Double("6"),     beanMap.getTypeTransformer(Double.TYPE).transform("6"));
    }

    /**
     * Test that the cause of exception thrown by a clone() is initialised.
     */
    public void testExceptionThrowFromClone() {

        if (BeanUtilsTestCase.isPre14JVM()) {
            System.out.println("testExceptionThrowFromClone() skipped on pre 1.4 JVM");
            return;
        }

        // Test cloning a non-public bean (instantiation exception)
        try {
            final Object bean = Jira87BeanFactory.createMappedPropertyBean();
            final BeanMap map = new BeanMap(bean);
            map.clone();
            fail("Non-public bean clone() - expected CloneNotSupportedException");
        } catch (final CloneNotSupportedException e) {
            Throwable cause = null;
            try {
                cause = (Throwable)PropertyUtils.getProperty(e, "cause");
            } catch (final Exception e2) {
                fail("Non-public bean - retrieving the cause threw " + e2);
            }
            assertNotNull("Non-public bean cause null", cause);
            assertEquals("Non-public bean cause", IllegalAccessException.class, cause.getClass());
        }

        // Test cloning a bean that throws exception
        try {
            final BeanMap map = new BeanMap(new BeanThrowingExceptions());
            map.clone();
            fail("Setter Exception clone() - expected CloneNotSupportedException");
        } catch (final CloneNotSupportedException e) {
            Throwable cause = null;
            try {
                cause = (Throwable)PropertyUtils.getProperty(e, "cause");
            } catch (final Exception e2) {
                fail("Setter Exception - retrieving the cause threw " + e2);
            }
            assertNotNull("Setter Exception cause null", cause);
            assertEquals("Setter Exception cause", IllegalArgumentException.class, cause.getClass());
        }
    }

    /**
     * Test that the cause of exception thrown by clear() is initialised.
     */
    public void testExceptionThrowFromClear() {

        if (BeanUtilsTestCase.isPre14JVM()) {
            System.out.println("testExceptionThrowFromClear() skipped on pre 1.4 JVM");
            return;
        }

        try {
            final Object bean = Jira87BeanFactory.createMappedPropertyBean();
            final BeanMap map = new BeanMap(bean);
            map.clear();
            fail("clear() - expected UnsupportedOperationException");
        } catch (final UnsupportedOperationException e) {
            Throwable cause = null;
            try {
                cause = (Throwable)PropertyUtils.getProperty(e, "cause");
            } catch (final Exception e2) {
                fail("Retrieving the cause threw " + e2);
            }
            assertNotNull("Cause null", cause);
            assertEquals("Cause", IllegalAccessException.class, cause.getClass());
        }
    }

    /**
     * Test that the cause of exception thrown by put() is initialized.
     */
    public void testExceptionThrowFromPut() {

        if (BeanUtilsTestCase.isPre14JVM()) {
            System.out.println("testExceptionThrowFromPut() skipped on pre 1.4 JVM");
            return;
        }

        try {
            final Map<Object, Object> map = new BeanMap(new BeanThrowingExceptions());
            map.put("valueThrowingException", "value");
            fail("Setter exception - expected IllegalArgumentException");
        } catch (final IllegalArgumentException e) {
            Throwable cause1 = null;
            Throwable cause2 = null;
            try {
                cause1 = (Throwable)PropertyUtils.getProperty(e, "cause");
                cause2 = (Throwable)PropertyUtils.getProperty(e, "cause.cause");
            } catch (final Exception e2) {
                fail("Setter exception - retrieving the cause threw " + e2);
            }
            assertNotNull("Setter exception cause 1 null", cause1);
            assertEquals("Setter exception cause 1", InvocationTargetException.class, cause1.getClass());
            assertNotNull("Setter exception cause 2 null", cause2);
            assertEquals("Setter exception cause 2", TestException.class, cause2.getClass());
        }
    }
}
