/*
 * 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.pivot.beans;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Locale;
import java.util.NoSuchElementException;

import org.apache.pivot.annotations.UnsupportedOperation;
import org.apache.pivot.collections.Map;
import org.apache.pivot.collections.MapListener;
import org.apache.pivot.util.ListenerList;
import org.apache.pivot.util.Utils;

/**
 * Exposes Java bean properties of an object via the {@link Map} interface. A
 * call to {@link Map#get(Object)} invokes the getter for the corresponding
 * property, and a call to {@link Map#put(Object, Object)} invokes the
 * property's setter. <p> Properties may provide multiple setters; the
 * appropriate setter to invoke is determined by the type of the value being
 * set. If the value is <tt>null</tt>, the return type of the getter method is
 * used. <p> Getter methods must be named "getProperty" where "property" is the
 * property name. If there is no "get" method, then an "isProperty" method can
 * also be used. Setter methods (if present) must be named "setProperty". <p>
 * Getter and setter methods are checked before straight fields named "property"
 * in order to support proper data encapsulation. And only <code>public</code>
 * and non-<code>static</code> methods and fields can be accessed.
 */
public class BeanAdapter implements Map<String, Object> {
    /**
     * Property iterator. Returns a value for each getter method and public,
     * non-final field defined by the bean.
     */
    private class PropertyIterator implements Iterator<String> {
        private Method[] methods = null;
        private Field[] fields = null;

        private int i = 0;
        private int j = 0;
        private String nextProperty = null;

        public PropertyIterator() {
            Class<?> type = bean.getClass();
            methods = type.getMethods();
            fields = type.getFields();
            nextProperty();
        }

        @Override
        public boolean hasNext() {
            return (nextProperty != null);
        }

        @Override
        public String next() {
            if (!hasNext()) {
                throw new NoSuchElementException();
            }

            String nextPropertyLocal = this.nextProperty;
            nextProperty();

            return nextPropertyLocal;
        }

        private void nextProperty() {
            nextProperty = null;

            while (i < methods.length && nextProperty == null) {
                Method method = methods[i++];

                if (method.getParameterTypes().length == 0
                    && (method.getModifiers() & Modifier.STATIC) == 0) {
                    String methodName = method.getName();

                    String prefix = null;
                    if (methodName.startsWith(GET_PREFIX)) {
                        prefix = GET_PREFIX;
                    } else {
                        if (methodName.startsWith(IS_PREFIX)) {
                            prefix = IS_PREFIX;
                        }
                    }

                    if (prefix != null) {
                        int propertyOffset = prefix.length();
                        nextProperty = Character.toLowerCase(methodName.charAt(propertyOffset))
                            + methodName.substring(propertyOffset + 1);

                        if (nextProperty.equals("class")) {
                            nextProperty = null;
                        }
                    }

                    if (nextProperty != null && ignoreReadOnlyProperties
                        && isReadOnly(nextProperty)) {
                        nextProperty = null;
                    }
                }
            }

            if (nextProperty == null) {
                while (j < fields.length && nextProperty == null) {
                    Field field = fields[j++];

                    int modifiers = field.getModifiers();
                    if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & Modifier.STATIC) == 0) {
                        nextProperty = field.getName();
                    }

                    if (nextProperty != null && ignoreReadOnlyProperties
                        && (modifiers & Modifier.FINAL) != 0) {
                        nextProperty = null;
                    }
                }
            }
        }

        @Override
        @UnsupportedOperation
        public void remove() {
            throw new UnsupportedOperationException();
        }
    }

    private Object bean;
    private boolean ignoreReadOnlyProperties;

    private MapListener.Listeners<String, Object> mapListeners = new MapListener.Listeners<>();

    public static final String GET_PREFIX = "get";
    public static final String IS_PREFIX = "is";
    public static final String SET_PREFIX = "set";

    private static final String ENUM_VALUE_OF_METHOD_NAME = "valueOf";

    private static final String ILLEGAL_ACCESS_EXCEPTION_MESSAGE_FORMAT =
            "Unable to access property \"%s\" for type %s.";
    private static final String ENUM_COERCION_EXCEPTION_MESSAGE =
            "Unable to coerce %s (\"%s\") to %s.\nValid enum constants - %s";

    /**
     * Creates a new bean dictionary.
     *
     * @param bean The bean object to wrap.
     */
    public BeanAdapter(final Object bean) {
        this(bean, false);
    }

    /**
     * Creates a new bean dictionary which can ignore readonly fields (that is,
     * straight fields marked as <code>final</code> or bean properties where
     * there is a "get" method but no corresponding "set" method).
     *
     * @param bean The bean object to wrap.
     * @param ignoreReadOnlyProperties <tt>true</tt> if {@code final} or non-settable
     * fields should be excluded from the dictionary, <tt>false</tt> to include all fields.
     */
    public BeanAdapter(final Object bean, final boolean ignoreReadOnlyProperties) {
        Utils.checkNull(bean, "bean object");

        this.bean = bean;
        this.ignoreReadOnlyProperties = ignoreReadOnlyProperties;
    }

    /**
     * Returns the bean object this dictionary wraps.
     *
     * @return The bean object, or <tt>null</tt> if no bean has been set.
     */
    public Object getBean() {
        return bean;
    }

    /**
     * Invokes the getter method for the given property.
     *
     * @param key The property name.
     * @return The value returned by the method, or <tt>null</tt> if no such
     * method exists.
     */
    @Override
    public Object get(final String key) {
        Utils.checkNullOrEmpty(key, "key");

        Object value = null;

        Method getterMethod = getGetterMethod(key);

        if (getterMethod == null) {
            Field field = getField(key);

            if (field != null) {
                try {
                    value = field.get(bean);
                } catch (IllegalAccessException exception) {
                    throw new RuntimeException(String.format(
                        ILLEGAL_ACCESS_EXCEPTION_MESSAGE_FORMAT, key, bean.getClass().getName()),
                        exception);
                }
            }
        } else {
            try {
                value = getterMethod.invoke(bean, new Object[] {});
            } catch (IllegalAccessException exception) {
                throw new RuntimeException(String.format(ILLEGAL_ACCESS_EXCEPTION_MESSAGE_FORMAT,
                    key, bean.getClass().getName()), exception);
            } catch (InvocationTargetException exception) {
                throw new RuntimeException(String.format(
                    "Error getting property \"%s\" for type %s.", key, bean.getClass().getName()),
                    exception.getCause());
            }
        }

        return value;
    }

    /**
     * Invokes the setter method for the given property. The method signature is
     * determined by the type of the value. If the value is <tt>null</tt>, the
     * return type of the getter method is used.
     *
     * @param key The property name.
     * @param value The new property value.
     * @return Returns <tt>null</tt>, since returning the previous value would
     * require a call to the getter method, which may not be an efficient
     * operation.
     * @throws PropertyNotFoundException If the given property does not exist or
     * is read-only.
     */
    @Override
    public Object put(final String key, final Object value) {
        Utils.checkNullOrEmpty(key, "key");

        Method setterMethod = null;
        Object valueUpdated = value;

        if (valueUpdated != null) {
            // Get the setter method for the value type
            setterMethod = getSetterMethod(key, valueUpdated.getClass());
        }

        if (setterMethod == null) {
            // Get the property type and attempt to coerce the value to it
            Class<?> propertyType = getType(key);

            if (propertyType != null) {
                setterMethod = getSetterMethod(key, propertyType);
                valueUpdated = coerce(valueUpdated, propertyType, key);
            }
        }

        if (setterMethod == null) {
            Field field = getField(key);

            if (field == null) {
                throw new PropertyNotFoundException("Property \"" + key + "\""
                    + " does not exist or is read-only.");
            }

            Class<?> fieldType = field.getType();
            if (valueUpdated != null) {
                Class<?> valueType = valueUpdated.getClass();
                if (!fieldType.isAssignableFrom(valueType)) {
                    valueUpdated = coerce(valueUpdated, fieldType, key);
                }
            }

            try {
                field.set(bean, valueUpdated);
            } catch (IllegalAccessException exception) {
                throw new RuntimeException(String.format(ILLEGAL_ACCESS_EXCEPTION_MESSAGE_FORMAT,
                    key, bean.getClass().getName()), exception);
            }
        } else {
            try {
                setterMethod.invoke(bean, new Object[] {valueUpdated});
            } catch (IllegalAccessException exception) {
                throw new RuntimeException(String.format(ILLEGAL_ACCESS_EXCEPTION_MESSAGE_FORMAT,
                    key, bean.getClass().getName()), exception);
            } catch (InvocationTargetException exception) {
                throw new RuntimeException(String.format(
                    "Error setting property \"%s\" for type %s to value \"%s\"", key,
                    bean.getClass().getName(), "" + valueUpdated), exception.getCause());
            }

        }

        Object previousValue = null;
        mapListeners.valueUpdated(this, key, previousValue);

        return previousValue;
    }

    /**
     * Invokes the setter methods for all the given properties that are present
     * in the map. The method signatures are determined by the type of the
     * values. If any value is <tt>null</tt>, the return type of the getter
     * method is used.
     *
     * @param valueMap The map of keys and values to be set.
     * @throws PropertyNotFoundException If any of the given properties do not
     * exist or are read-only.
     */
    @Override
    public void putAll(final Map<String, Object> valueMap) {
        for (String key : valueMap) {
            put(key, valueMap.get(key));
        }
    }

    /**
     * Invokes the setter methods for all the given properties that are present
     * in the map. The method signatures are determined by the type of the
     * values. If any value is <tt>null</tt>, the return type of the getter
     * method is used. There is an option to ignore (that is, not throw)
     * exceptions during the process, but to return status if any exceptions
     * were caught and ignored.
     *
     * @param valueMap The map of keys and values to be set.
     * @param ignoreErrors If <code>true</code> then any
     * {@link PropertyNotFoundException} thrown by the {@link #put put()} method
     * will be caught and ignored.
     * @return <code>true</code> if any exceptions were caught,
     * <code>false</code> if not.
     */
    public boolean putAll(final Map<String, ?> valueMap, final boolean ignoreErrors) {
        boolean anyErrors = false;
        for (String key : valueMap) {
            try {
                put(key, valueMap.get(key));
            } catch (PropertyNotFoundException ex) {
                if (!ignoreErrors) {
                    throw ex;
                }
                anyErrors = true;
            }
        }
        return anyErrors;
    }

    /**
     * @throws UnsupportedOperationException This operation is not supported.
     */
    @Override
    @UnsupportedOperation
    public Object remove(final String key) {
        throw new UnsupportedOperationException();
    }

    /**
     * @throws UnsupportedOperationException This operation is not supported.
     */
    @Override
    @UnsupportedOperation
    public synchronized void clear() {
        throw new UnsupportedOperationException();
    }

    /**
     * Verifies the existence of a property. The property must have a getter
     * method; write-only properties are not supported.
     *
     * @param key The property name.
     * @return <tt>true</tt> if the property exists; <tt>false</tt>, otherwise.
     */
    @Override
    public boolean containsKey(final String key) {
        Utils.checkNullOrEmpty(key, "key");

        boolean containsKey = (getGetterMethod(key) != null);

        if (!containsKey) {
            containsKey = (getField(key) != null);
        }

        return containsKey;
    }

    /**
     * @throws UnsupportedOperationException This operation is not supported.
     */
    @Override
    @UnsupportedOperation
    public boolean isEmpty() {
        throw new UnsupportedOperationException();
    }

    /**
     * @throws UnsupportedOperationException This operation is not supported.
     */
    @Override
    @UnsupportedOperation
    public int getCount() {
        throw new UnsupportedOperationException();
    }

    @Override
    public Comparator<String> getComparator() {
        return null;
    }

    /**
     * @throws UnsupportedOperationException This operation is not supported.
     */
    @Override
    @UnsupportedOperation
    public void setComparator(final Comparator<String> comparator) {
        throw new UnsupportedOperationException();
    }

    /**
     * Tests the read-only state of a property.
     *
     * @param key The property name.
     * @return <tt>true</tt> if the property is read-only; <tt>false</tt>,
     * otherwise.
     */
    public boolean isReadOnly(final String key) {
        return isReadOnly(bean.getClass(), key);
    }

    /**
     * Returns the type of a property.
     *
     * @param key The property name.
     * @return The real class type of this property.
     * @see #getType(Class, String)
     */
    public Class<?> getType(final String key) {
        return getType(bean.getClass(), key);
    }

    /**
     * Returns the generic type of a property.
     *
     * @param key The property name.
     * @return The generic type of this property.
     * @see #getGenericType(Class, String)
     */
    public Type getGenericType(final String key) {
        return getGenericType(bean.getClass(), key);
    }

    /**
     * Returns an iterator over the bean's properties.
     *
     * @return A property iterator for this bean.
     */
    @Override
    public Iterator<String> iterator() {
        return new PropertyIterator();
    }

    @Override
    public ListenerList<MapListener<String, Object>> getMapListeners() {
        return mapListeners;
    }

    /**
     * Returns the getter method for a property.
     *
     * @param key The property name.
     * @return The getter method, or <tt>null</tt> if the method does not exist.
     */
    private Method getGetterMethod(final String key) {
        return getGetterMethod(bean.getClass(), key);
    }

    /**
     * Returns the setter method for a property.
     *
     * @param key The property name.
     * @param valueType The value type of the property in question.
     * @return The getter method, or <tt>null</tt> if the method does not exist.
     */
    private Method getSetterMethod(final String key, final Class<?> valueType) {
        return getSetterMethod(bean.getClass(), key, valueType);
    }

    /**
     * Returns the public, non-static field for a property. Note that fields
     * will only be consulted for bean properties after bean methods.
     *
     * @param key The property name
     * @return The field, or <tt>null</tt> if the field does not exist, or is
     * non-public or static
     */
    private Field getField(final String key) {
        return getField(bean.getClass(), key);
    }

    /**
     * Tests the read-only state of a property. Note that if no such property
     * exists, this method will return <tt>true</tt> (it will <u>not</u> throw
     * an exception).
     *
     * @param beanClass The bean class.
     * @param key The property name.
     * @return <tt>true</tt> if the property is read-only; <tt>false</tt>,
     * otherwise.
     */
    public static boolean isReadOnly(final Class<?> beanClass, final String key) {
        Utils.checkNull(beanClass, "beanClass");
        Utils.checkNullOrEmpty(key, "key");

        boolean isReadOnly = true;

        Method getterMethod = getGetterMethod(beanClass, key);
        if (getterMethod == null) {
            Field field = getField(beanClass, key);
            if (field != null) {
                isReadOnly = ((field.getModifiers() & Modifier.FINAL) != 0);
            }
        } else {
            Method setterMethod = getSetterMethod(beanClass, key, getType(beanClass, key));
            isReadOnly = (setterMethod == null);
        }

        return isReadOnly;
    }

    /**
     * Returns the type of a property.
     *
     * @param beanClass The bean class.
     * @param key The property name.
     * @return The type of the property, or <tt>null</tt> if no such bean
     * property exists.
     */
    public static Class<?> getType(final Class<?> beanClass, final String key) {
        Utils.checkNull(beanClass, "beanClass");
        Utils.checkNullOrEmpty(key, "key");

        Class<?> type = null;

        Method getterMethod = getGetterMethod(beanClass, key);

        if (getterMethod == null) {
            Field field = getField(beanClass, key);

            if (field != null) {
                type = field.getType();
            }
        } else {
            type = getterMethod.getReturnType();
        }

        return type;
    }

    /**
     * Returns the generic type of a property.
     *
     * @param beanClass The bean class.
     * @param key The property name.
     * @return The generic type of the property, or <tt>null</tt> if no such bean
     * property exists. If the type is a generic, an instance of
     * {@link java.lang.reflect.ParameterizedType} will be returned. Otherwise,
     * an instance of {@link java.lang.Class} will be returned.
     */
    public static Type getGenericType(final Class<?> beanClass, final String key) {
        Utils.checkNull(beanClass, "beanClass");
        Utils.checkNullOrEmpty(key, "key");

        Type genericType = null;

        Method getterMethod = getGetterMethod(beanClass, key);

        if (getterMethod == null) {
            Field field = getField(beanClass, key);

            if (field != null) {
                genericType = field.getGenericType();
            }
        } else {
            genericType = getterMethod.getGenericReturnType();
        }

        return genericType;
    }

    /**
     * Returns the public, non-static fields for a property. Note that fields
     * will only be consulted for bean properties after bean methods.
     *
     * @param beanClass The bean class.
     * @param key The property name.
     * @return The field, or <tt>null</tt> if the field does not exist, or is
     * non-public or static.
     */
    public static Field getField(final Class<?> beanClass, final String key) {
        Utils.checkNull(beanClass, "beanClass");
        Utils.checkNullOrEmpty(key, "key");

        Field field = null;

        try {
            field = beanClass.getField(key);

            int modifiers = field.getModifiers();

            // Exclude non-public and static fields
            if ((modifiers & Modifier.PUBLIC) == 0 || (modifiers & Modifier.STATIC) > 0) {
                field = null;
            }
        } catch (NoSuchFieldException exception) {
            // No-op
        }

        return field;
    }

    /**
     * Returns the getter method for a property.
     *
     * @param beanClass The bean class.
     * @param key The property name.
     * @return The getter method, or <tt>null</tt> if the method does not exist.
     */
    public static Method getGetterMethod(final Class<?> beanClass, final String key) {
        Utils.checkNull(beanClass, "beanClass");
        Utils.checkNullOrEmpty(key, "key");

        // Upper-case the first letter
        String keyUpdated = Character.toUpperCase(key.charAt(0)) + key.substring(1);
        Method getterMethod = null;

        try {
            getterMethod = beanClass.getMethod(GET_PREFIX + keyUpdated);
        } catch (NoSuchMethodException exception) {
            // No-op
        }

        if (getterMethod == null) {
            try {
                getterMethod = beanClass.getMethod(IS_PREFIX + keyUpdated);
            } catch (NoSuchMethodException exception) {
                // No-op
            }
        }

        return getterMethod;
    }

    /**
     * Returns the setter method for a property.
     *
     * @param beanClass The bean class.
     * @param key The property name.
     * @param valueType The type of the property.
     * @return The getter method, or <tt>null</tt> if the method does not exist.
     */
    public static Method getSetterMethod(final Class<?> beanClass, final String key,
            final Class<?> valueType) {
        Utils.checkNull(beanClass, "beanClass");
        Utils.checkNullOrEmpty(key, "key");

        Method setterMethod = null;

        if (valueType != null) {
            // Upper-case the first letter and prepend the "set" prefix to
            // determine the method name
            String keyUpdated = Character.toUpperCase(key.charAt(0)) + key.substring(1);
            final String methodName = SET_PREFIX + keyUpdated;

            try {
                setterMethod = beanClass.getMethod(methodName, valueType);
            } catch (NoSuchMethodException exception) {
                // No-op
            }

            if (setterMethod == null) {
                // Look for a match on the value's super type
                Class<?> superType = valueType.getSuperclass();
                setterMethod = getSetterMethod(beanClass, key, superType);
            }

            if (setterMethod == null) {
                // If value type is a primitive wrapper, look for a method
                // signature with the corresponding primitive type
                try {
                    Field primitiveTypeField = valueType.getField("TYPE");
                    Class<?> primitiveValueType = (Class<?>) primitiveTypeField.get(null);

                    try {
                        setterMethod = beanClass.getMethod(methodName, primitiveValueType);
                    } catch (NoSuchMethodException exception) {
                        // No-op
                    }
                } catch (NoSuchFieldException exception) {
                    // No-op
                } catch (IllegalAccessException exception) {
                    throw new RuntimeException(String.format(
                        ILLEGAL_ACCESS_EXCEPTION_MESSAGE_FORMAT, keyUpdated, beanClass.getName()),
                        exception);
                }
            }

            if (setterMethod == null) {
                // Walk the interface graph to find a matching method
                Class<?>[] interfaces = valueType.getInterfaces();

                int i = 0, n = interfaces.length;
                while (setterMethod == null && i < n) {
                    Class<?> interfaceType = interfaces[i++];
                    setterMethod = getSetterMethod(beanClass, key, interfaceType);
                }
            }
        }

        return setterMethod;
    }

    /**
     * Coerces a value to a given type.
     *
     * @param <T> The parametric type to coerce to.
     * @param value The object to be coerced.
     * @param type The type to coerce it to.
     * @param key The property name in question.
     * @return The coerced value.
     * @throws IllegalArgumentException for all the possible other exceptions.
     */
    @SuppressWarnings("unchecked")
    public static <T> T coerce(final Object value, final Class<? extends T> type, final String key) {
        Utils.checkNull(type, "type");

        Object coercedValue;

        if (value == null) {
            // Null values can only be coerced to null
            coercedValue = null;
        } else {
            if (type.isAssignableFrom(value.getClass())) {
                // Value doesn't need coercion
                coercedValue = value;
            } else if (type.isEnum()) {
                // Find and invoke the valueOf(String) method using an upper
                // case conversion of the supplied Object's toString() value
                try {
                    String valueString = value.toString().toUpperCase(Locale.ENGLISH);
                    Method valueOfMethod = type.getMethod(ENUM_VALUE_OF_METHOD_NAME, String.class);
                    coercedValue = valueOfMethod.invoke(null, valueString);
                } catch (IllegalAccessException | InvocationTargetException
                        | SecurityException | NoSuchMethodException e) {
                    // Nothing to be gained by handling the getMethod() & invoke() exceptions separately
                    throw new IllegalArgumentException(String.format(
                        ENUM_COERCION_EXCEPTION_MESSAGE, value.getClass().getName(), value, type,
                        Arrays.toString(type.getEnumConstants())), e);
                }
            } else {
                // Coerce the value to the requested type
                if (type == String.class) {
                    coercedValue = value.toString();
                } else if (type == Boolean.class || type == Boolean.TYPE) {
                    coercedValue = Boolean.parseBoolean(value.toString());
                } else if (type == Character.class || type == Character.TYPE) {
                    coercedValue = value.toString().charAt(0);
                } else if (type == Byte.class || type == Byte.TYPE) {
                    if (value instanceof Number) {
                        coercedValue = ((Number) value).byteValue();
                    } else {
                        coercedValue = Byte.parseByte(value.toString());
                    }
                } else if (type == Short.class || type == Short.TYPE) {
                    if (value instanceof Number) {
                        coercedValue = ((Number) value).shortValue();
                    } else {
                        coercedValue = Short.parseShort(value.toString());
                    }
                } else if (type == Integer.class || type == Integer.TYPE) {
                    if (value instanceof Number) {
                        coercedValue = ((Number) value).intValue();
                    } else {
                        coercedValue = Integer.parseInt(value.toString());
                    }
                } else if (type == Long.class || type == Long.TYPE) {
                    if (value instanceof Number) {
                        coercedValue = ((Number) value).longValue();
                    } else {
                        coercedValue = Long.parseLong(value.toString());
                    }
                } else if (type == Float.class || type == Float.TYPE) {
                    if (value instanceof Number) {
                        coercedValue = ((Number) value).floatValue();
                    } else {
                        coercedValue = Float.parseFloat(value.toString());
                    }
                } else if (type == Double.class || type == Double.TYPE) {
                    if (value instanceof Number) {
                        coercedValue = ((Number) value).doubleValue();
                    } else {
                        coercedValue = Double.parseDouble(value.toString());
                    }
                } else if (type == BigInteger.class) {
                    if (value instanceof Number) {
                        coercedValue = new BigInteger(((Number) value).toString());
                    } else {
                        coercedValue = new BigInteger(value.toString());
                    }
                } else if (type == BigDecimal.class) {
                    if (value instanceof Number) {
                        coercedValue = new BigDecimal(((Number) value).toString());
                    } else {
                        coercedValue = new BigDecimal(value.toString());
                    }
                } else {
                    throw new IllegalArgumentException("Unable to coerce "
                        + value.getClass().getName() + " to " + type + " for \"" + key + "\" property.");
                }
            }
        }

        return (T) coercedValue;
    }
}
