/*
 * 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.myfaces.test.el;

import java.math.BigDecimal;
import java.math.BigInteger;
import javax.el.ELContext;
import javax.el.ExpressionFactory;
import javax.el.MethodExpression;
import javax.el.ValueExpression;

/**
 * <p>Mock implementation of <code>ExpressionFactory</code>.</p>
 *
 * @since 1.0.0
 */
public class MockExpressionFactory extends ExpressionFactory
{

    // ------------------------------------------------------------ Constructors

    /** Creates a new instance of MockExpressionFactory */
    public MockExpressionFactory()
    {
    }

    // ------------------------------------------------------ Instance Variables

    /**
     * <p>Literal numeric value for zero.</p>
     */
    private static final Integer ZERO = new Integer(0);

    // ----------------------------------------------------- Mock Object Methods

    // ----------------------------------------------- ExpressionFactory Methods

    /** {@inheritDoc} */
    public Object coerceToType(Object object, Class targetType)
    {

        // Check for no conversion necessary
        if ((targetType == null) || Object.class.equals(targetType))
        {
            return object;
        }

        // Coerce to String if appropriate
        if (String.class.equals(targetType))
        {
            if (object == null)
            {
                return "";
            }
            else if (object instanceof String)
            {
                return (String) object;
            }
            else
            {
                return object.toString();
            }
        }

        // Coerce to Number (or a subclass of Number) if appropriate
        if (isNumeric(targetType))
        {
            if (object == null)
            {
                return coerce(ZERO, targetType);
            }
            else if ("".equals(object))
            {
                return coerce(ZERO, targetType);
            }
            else if (object instanceof String)
            {
                return coerce((String) object, targetType);
            }
            else if (isNumeric(object.getClass()))
            {
                return coerce((Number) object, targetType);
            }
            throw new IllegalArgumentException("Cannot convert " + object
                    + " to Number");
        }

        // Coerce to Boolean if appropriate
        if (Boolean.class.equals(targetType) || (Boolean.TYPE == targetType))
        {
            if (object == null)
            {
                return Boolean.FALSE;
            }
            else if ("".equals(object))
            {
                return Boolean.FALSE;
            }
            else if ((object instanceof Boolean)
                    || (object.getClass() == Boolean.TYPE))
            {
                return (Boolean) object;
            }
            else if (object instanceof String)
            {
                return Boolean.valueOf((String) object);
            }
            throw new IllegalArgumentException("Cannot convert " + object
                    + " to Boolean");
        }

        // Coerce to Character if appropriate
        if (Character.class.equals(targetType)
                || (Character.TYPE == targetType))
        {
            if (object == null)
            {
                return new Character((char) 0);
            }
            else if ("".equals(object))
            {
                return new Character((char) 0);
            }
            else if (object instanceof String)
            {
                return new Character(((String) object).charAt(0));
            }
            else if (isNumeric(object.getClass()))
            {
                return new Character((char) ((Number) object).shortValue());
            }
            else if ((object instanceof Character)
                    || (object.getClass() == Character.TYPE))
            {
                return (Character) object;
            }
            throw new IllegalArgumentException("Cannot convert " + object
                    + " to Character");
        }
        
        if (targetType.isEnum())
        {
            if (object == null || "".equals(object))
            {
                return null;
            }
            if (targetType.isAssignableFrom(object.getClass()))
            {
                return (Enum) object;
            }
            
            if (!(object instanceof String))
            {
                throw new IllegalArgumentException("Cannot convert " + object + " to Enum");
            }

            Enum<?> result;
            try
            {
                 result = Enum.valueOf(targetType, (String) object);
                 return result;
            }
            catch (IllegalArgumentException iae)
            {
                throw new IllegalArgumentException("Cannot convert " + object + " to Enum");
            }
        }

        // Is the specified value type-compatible already?
        if ((object != null) && targetType.isAssignableFrom(object.getClass()))
        {
            return object;
        }

        // new to spec
        if (object == null)
        {
            return null;
        }

        // We do not know how to perform this conversion
        throw new IllegalArgumentException("Cannot convert " + object + " to "
                + targetType.getName());

    }

    /** {@inheritDoc} */
    public MethodExpression createMethodExpression(ELContext context,
            String expression, Class expectedType, Class[] signature)
    {

        return new MockMethodExpression(expression, signature, expectedType);

    }

    /** {@inheritDoc} */
    public ValueExpression createValueExpression(ELContext context,
            String expression, Class expectedType)
    {

        return new MockCompositeValueExpression(expression, expectedType);

    }

    /** {@inheritDoc} */
    public ValueExpression createValueExpression(Object instance,
            Class expectedType)
    {

        return new MockVariableValueExpression(instance, expectedType);

    }

    // --------------------------------------------------------- Private Methods

    /**
     * <p>Coerce the specified value to the specified Number subclass.</p>
     *
     * @param value Value to be coerced
     * @param type Destination type
     */
    private Number coerce(Number value, Class type)
    {

        if ((type == Byte.TYPE) || (type == Byte.class))
        {
            return new Byte(value.byteValue());
        }
        else if ((type == Double.TYPE) || (type == Double.class))
        {
            return new Double(value.doubleValue());
        }
        else if ((type == Float.TYPE) || (type == Float.class))
        {
            return new Float(value.floatValue());
        }
        else if ((type == Integer.TYPE) || (type == Integer.class))
        {
            return new Integer(value.intValue());
        }
        else if ((type == Long.TYPE) || (type == Long.class))
        {
            return new Long(value.longValue());
        }
        else if ((type == Short.TYPE) || (type == Short.class))
        {
            return new Short(value.shortValue());
        }
        else if (type == BigDecimal.class)
        {
            if (value instanceof BigDecimal)
            {
                return (BigDecimal) value;
            }
            else if (value instanceof BigInteger)
            {
                return new BigDecimal((BigInteger) value);
            }
            else
            {
                return new BigDecimal(((Number) value).doubleValue());
            }
        }
        else if (type == BigInteger.class)
        {
            if (value instanceof BigInteger)
            {
                return (BigInteger) value;
            }
            else if (value instanceof BigDecimal)
            {
                return ((BigDecimal) value).toBigInteger();
            }
            else
            {
                return BigInteger.valueOf(((Number) value).longValue());
            }
        }
        throw new IllegalArgumentException("Cannot convert " + value + " to "
                + type.getName());

    }

    /**
     * <p>Coerce the specified value to the specified Number subclass.</p>
     *
     * @param value Value to be coerced
     * @param type Destination type
     */
    private Number coerce(String value, Class type)
    {

        if ((type == Byte.TYPE) || (type == Byte.class))
        {
            return Byte.valueOf(value);
        }
        else if ((type == Double.TYPE) || (type == Double.class))
        {
            return Double.valueOf(value);
        }
        else if ((type == Float.TYPE) || (type == Float.class))
        {
            return Float.valueOf(value);
        }
        else if ((type == Integer.TYPE) || (type == Integer.class))
        {
            return Integer.valueOf(value);
        }
        else if ((type == Long.TYPE) || (type == Long.class))
        {
            return Long.valueOf(value);
        }
        else if ((type == Short.TYPE) || (type == Short.class))
        {
            return Short.valueOf(value);
        }
        else if (type == BigDecimal.class)
        {
            return new BigDecimal(value);
        }
        else if (type == BigInteger.class)
        {
            return new BigInteger(value);
        }
        throw new IllegalArgumentException("Cannot convert " + value + " to "
                + type.getName());

    }

    /**
     * <p>Return <code>true</code> if the specified type is numeric.</p>
     *
     * @param type Type to check
     */
    private boolean isNumeric(Class type)
    {

        return (type == Byte.TYPE) || (type == Byte.class)
                || (type == Double.TYPE) || (type == Double.class)
                || (type == Float.TYPE) || (type == Float.class)
                || (type == Integer.TYPE) || (type == Integer.class)
                || (type == Long.TYPE) || (type == Long.class)
                || (type == Short.TYPE) || (type == Short.class)
                || (type == BigDecimal.class) || (type == BigInteger.class);

    }

}
