/*
 * 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.4
 */
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");
        }

        // 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 MockValueExpression(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);

    }


}
