/*
 * 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.
 */
/* Generated By:JJTree: Do not edit this line. AstValue.java */

package org.apache.el.parser;

import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import javax.el.ELException;
import javax.el.ELResolver;
import javax.el.LambdaExpression;
import javax.el.MethodInfo;
import javax.el.PropertyNotFoundException;
import javax.el.ValueReference;

import org.apache.el.lang.ELSupport;
import org.apache.el.lang.EvaluationContext;
import org.apache.el.stream.Optional;
import org.apache.el.util.MessageFactory;
import org.apache.el.util.ReflectionUtil;


/**
 * @author Jacob Hookom [jacob@hookom.net]
 */
public final class AstValue extends SimpleNode {

    private static final Object[] EMPTY_ARRAY = new Object[0];

    protected static class Target {
        protected Object base;

        protected Object property;
    }

    public AstValue(int id) {
        super(id);
    }

    @Override
    public Class<?> getType(EvaluationContext ctx) throws ELException {
        Target t = getTarget(ctx);
        ctx.setPropertyResolved(false);
        Class<?> result = ctx.getELResolver().getType(ctx, t.base, t.property);
        if (!ctx.isPropertyResolved()) {
            throw new PropertyNotFoundException(MessageFactory.get(
                    "error.resolver.unhandled", t.base, t.property));
        }
        return result;
    }

    private final Target getTarget(EvaluationContext ctx) throws ELException {
        // evaluate expr-a to value-a
        Object base = this.children[0].getValue(ctx);

        // if our base is null (we know there are more properties to evaluate)
        if (base == null) {
            throw new PropertyNotFoundException(MessageFactory.get(
                    "error.unreachable.base", this.children[0].getImage()));
        }

        // set up our start/end
        Object property = null;
        int propCount = this.jjtGetNumChildren();

        int i = 1;
        // Evaluate any properties or methods before our target
        ELResolver resolver = ctx.getELResolver();
        while (i < propCount) {
            if (i + 2 < propCount &&
                    this.children[i + 1] instanceof AstMethodParameters) {
                // Method call not at end of expression
                base = resolver.invoke(ctx, base,
                        this.children[i].getValue(ctx), null,
                        ((AstMethodParameters)
                                this.children[i + 1]).getParameters(ctx));
                i += 2;
            } else if (i + 2 == propCount &&
                    this.children[i + 1] instanceof AstMethodParameters) {
                // Method call at end of expression
                ctx.setPropertyResolved(false);
                property = this.children[i].getValue(ctx);
                i += 2;

                if (property == null) {
                    throw new PropertyNotFoundException(MessageFactory.get(
                            "error.unreachable.property", property));
                }
            } else if (i + 1 < propCount) {
                // Object with property not at end of expression
                property = this.children[i].getValue(ctx);
                ctx.setPropertyResolved(false);
                base = resolver.getValue(ctx, base, property);
                i++;

            } else {
                // Object with property at end of expression
                ctx.setPropertyResolved(false);
                property = this.children[i].getValue(ctx);
                i++;

                if (property == null) {
                    throw new PropertyNotFoundException(MessageFactory.get(
                            "error.unreachable.property", property));
                }
            }
            if (base == null) {
                throw new PropertyNotFoundException(MessageFactory.get(
                        "error.unreachable.property", property));
            }
        }

        Target t = new Target();
        t.base = base;
        t.property = property;
        return t;
    }

    @Override
    public Object getValue(EvaluationContext ctx) throws ELException {
        Object base = this.children[0].getValue(ctx);
        int propCount = this.jjtGetNumChildren();
        int i = 1;
        Object suffix = null;
        ELResolver resolver = ctx.getELResolver();
        while (base != null && i < propCount) {
            suffix = this.children[i].getValue(ctx);
            if (i + 1 < propCount &&
                    (this.children[i+1] instanceof AstMethodParameters)) {
                AstMethodParameters mps =
                    (AstMethodParameters) this.children[i+1];
                if (base instanceof Optional && "orElseGet".equals(suffix) &&
                        mps.jjtGetNumChildren() == 1) {
                    Node paramFoOptional = mps.jjtGetChild(0);
                    if (!(paramFoOptional instanceof AstLambdaExpression ||
                            paramFoOptional instanceof LambdaExpression)) {
                        throw new ELException(MessageFactory.get(
                                "stream.optional.paramNotLambda", suffix));
                    }
                }
                // This is a method
                Object[] paramValues = mps.getParameters(ctx);
                base = resolver.invoke(ctx, base, suffix,
                        getTypesFromValues(paramValues), paramValues);
                i+=2;
            } else {
                // This is a property
                if (suffix == null) {
                    return null;
                }

                ctx.setPropertyResolved(false);
                base = resolver.getValue(ctx, base, suffix);
                i++;
            }
        }
        if (!ctx.isPropertyResolved()) {
            throw new PropertyNotFoundException(MessageFactory.get(
                    "error.resolver.unhandled", base, suffix));
        }
        return base;
    }

    @Override
    public boolean isReadOnly(EvaluationContext ctx) throws ELException {
        Target t = getTarget(ctx);
        ctx.setPropertyResolved(false);
        boolean result =
            ctx.getELResolver().isReadOnly(ctx, t.base, t.property);
        if (!ctx.isPropertyResolved()) {
            throw new PropertyNotFoundException(MessageFactory.get(
                    "error.resolver.unhandled", t.base, t.property));
        }
        return result;
    }

    @Override
    public void setValue(EvaluationContext ctx, Object value)
            throws ELException {
        Target t = getTarget(ctx);
        ctx.setPropertyResolved(false);
        ELResolver resolver = ctx.getELResolver();

        // coerce to the expected type
        Class<?> targetClass = resolver.getType(ctx, t.base, t.property);
        resolver.setValue(ctx, t.base, t.property,
                ELSupport.coerceToType(ctx, value, targetClass));
        if (!ctx.isPropertyResolved()) {
            throw new PropertyNotFoundException(MessageFactory.get(
                    "error.resolver.unhandled", t.base, t.property));
        }
    }

    @Override
    // Interface el.parser.Node uses raw types (and is auto-generated)
    public MethodInfo getMethodInfo(EvaluationContext ctx,
            @SuppressWarnings("rawtypes") Class[] paramTypes)
            throws ELException {
        Target t = getTarget(ctx);
        Method m = ReflectionUtil.getMethod(
                ctx, t.base, t.property, paramTypes, null);
        return new MethodInfo(m.getName(), m.getReturnType(), m
                .getParameterTypes());
    }

    @Override
    // Interface el.parser.Node uses a raw type (and is auto-generated)
    public Object invoke(EvaluationContext ctx,
            @SuppressWarnings("rawtypes") Class[] paramTypes,
            Object[] paramValues) throws ELException {

        Target t = getTarget(ctx);
        Method m = null;
        Object[] values = null;
        Class<?>[] types = null;
        if (isParametersProvided()) {
            values = ((AstMethodParameters) this.jjtGetChild(
                    this.jjtGetNumChildren() - 1)).getParameters(ctx);
            types = getTypesFromValues(values);
        } else {
            values = paramValues;
            types = paramTypes;
        }
        m = ReflectionUtil.getMethod(ctx, t.base, t.property, types, values);

        // Handle varArgs and any coercion required
        values = convertArgs(ctx, values, m);

        Object result = null;
        try {
            result = m.invoke(t.base, values);
        } catch (IllegalAccessException iae) {
            throw new ELException(iae);
        } catch (IllegalArgumentException iae) {
            throw new ELException(iae);
        } catch (InvocationTargetException ite) {
            Throwable cause = ite.getCause();
            if (cause instanceof ThreadDeath) {
                throw (ThreadDeath) cause;
            }
            if (cause instanceof VirtualMachineError) {
                throw (VirtualMachineError) cause;
            }
            throw new ELException(cause);
        }
        return result;
    }

    private Object[] convertArgs(EvaluationContext ctx, Object[] src, Method m) {
        Class<?>[] types = m.getParameterTypes();
        if (types.length == 0) {
            // Treated as if parameters have been provided so src is ignored
            return EMPTY_ARRAY;
        }

        int paramCount = types.length;

        if (m.isVarArgs() && paramCount > 1 && (src == null || paramCount > src.length) ||
                !m.isVarArgs() && (paramCount > 0 && src == null ||
                        src != null && src.length != paramCount)) {
            String srcCount = null;
            if (src != null) {
                srcCount = Integer.toString(src.length);
            }
            String msg;
            if (m.isVarArgs()) {
                msg = MessageFactory.get("error.invoke.tooFewParams",
                        m.getName(), srcCount, Integer.toString(paramCount));
            } else {
                msg = MessageFactory.get("error.invoke.wrongParams",
                        m.getName(), srcCount, Integer.toString(paramCount));
            }
            throw new IllegalArgumentException(msg);
        }

        if (src == null) {
            // Must be a varargs method with a single parameter.
            // Use a new array every time since the called code could modify the
            // contents of the array
            return new Object[1];
        }

        Object[] dest = new Object[paramCount];

        for (int i = 0; i < paramCount - 1; i++) {
            dest[i] = ELSupport.coerceToType(ctx, src[i], types[i]);
        }

        if (m.isVarArgs()) {
            Object[] varArgs = (Object[]) Array.newInstance(
                    m.getParameterTypes()[paramCount - 1].getComponentType(),
                    src.length - (paramCount - 1));
            for (int i = 0; i < src.length - (paramCount - 1); i ++) {
                varArgs[i] = ELSupport.coerceToType(ctx, src[paramCount - 1 + i],
                        types[paramCount - 1].getComponentType());
            }
            dest[paramCount - 1] = varArgs;
        } else {
            dest[paramCount - 1] = ELSupport.coerceToType(
                    ctx, src[paramCount - 1], types[paramCount - 1]);
        }

        return dest;
    }

    private Class<?>[] getTypesFromValues(Object[] values) {
        if (values == null) {
            return null;
        }

        Class<?> result[] = new Class<?>[values.length];
        for (int i = 0; i < values.length; i++) {
            if (values[i] == null) {
                result[i] = null;
            } else {
                result[i] = values[i].getClass();
            }
        }
        return result;
    }


    /**
     * @since EL 2.2
     */
    @Override
    public ValueReference getValueReference(EvaluationContext ctx) {
        // Check this is a reference to a base and a property
        if (this.children.length > 2 &&
                this.jjtGetChild(2) instanceof AstMethodParameters) {
            // This is a method call
            return null;
        }
        Target t = getTarget(ctx);
        return new ValueReference(t.base, t.property);
    }


    /**
     * @since EL 2.2
     */
    @Override
    public boolean isParametersProvided() {
        // Assumption is that method parameters, if present, will be the last
        // child
        int len = children.length;
        if (len > 2) {
            if (this.jjtGetChild(len - 1) instanceof AstMethodParameters) {
                return true;
            }
        }
        return false;
    }
}
