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

import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;

import jakarta.el.ELContext;
import jakarta.el.ELException;
import jakarta.el.FunctionMapper;
import jakarta.el.MethodExpression;
import jakarta.el.MethodInfo;
import jakarta.el.MethodNotFoundException;
import jakarta.el.MethodReference;
import jakarta.el.PropertyNotFoundException;
import jakarta.el.VariableMapper;

import org.apache.el.lang.EvaluationContext;
import org.apache.el.lang.ExpressionBuilder;
import org.apache.el.parser.Node;
import org.apache.el.util.ReflectionUtil;


/**
 * An <code>Expression</code> that refers to a method on an object.
 * <p>
 * The {@link jakarta.el.ExpressionFactory#createMethodExpression} method can be used to parse an expression string and
 * return a concrete instance of <code>MethodExpression</code> that encapsulates the parsed expression. The
 * {@link FunctionMapper} is used at parse time, not evaluation time, so one is not needed to evaluate an expression
 * using this class. However, the {@link ELContext} is needed at evaluation time.
 * </p>
 * <p>
 * The {@link #getMethodInfo} and {@link #invoke} methods will evaluate the expression each time they are called. The
 * {@link jakarta.el.ELResolver} in the <code>ELContext</code> is used to resolve the top-level variables and to
 * determine the behavior of the <code>.</code> and <code>[]</code> operators. For any of the two methods, the
 * {@link jakarta.el.ELResolver#getValue} method is used to resolve all properties up to but excluding the last one.
 * This provides the <code>base</code> object on which the method appears. If the <code>base</code> object is null, a
 * <code>NullPointerException</code> must be thrown. At the last resolution, the final <code>property</code> is then
 * coerced to a <code>String</code>, which provides the name of the method to be found. A method matching the name and
 * expected parameters provided at parse time is found, and it is either queried or invoked (depending on the method
 * called on this <code>MethodExpression</code>).
 * </p>
 * <p>
 * See the notes about comparison, serialization and immutability in the {@link jakarta.el.Expression} javadocs.
 *
 * @see jakarta.el.ELResolver
 * @see jakarta.el.Expression
 * @see jakarta.el.ExpressionFactory
 * @see jakarta.el.MethodExpression
 */
public final class MethodExpressionImpl extends MethodExpression implements Externalizable {

    private Class<?> expectedType;

    private String expr;

    private FunctionMapper fnMapper;

    private VariableMapper varMapper;

    private transient Node node;

    private Class<?>[] paramTypes;

    /**
     * Default constructor.
     */
    public MethodExpressionImpl() {
        super();
    }

    /**
     * Constructor.
     * @param expr the expression
     * @param node the node
     * @param fnMapper the function mapper
     * @param varMapper the variable mapper
     * @param expectedType the expected type
     * @param paramTypes the parameter types
     */
    public MethodExpressionImpl(String expr, Node node, FunctionMapper fnMapper, VariableMapper varMapper,
            Class<?> expectedType, Class<?>[] paramTypes) {
        super();
        this.expr = expr;
        this.node = node;
        this.fnMapper = fnMapper;
        this.varMapper = varMapper;
        this.expectedType = expectedType;
        this.paramTypes = paramTypes;
    }

    /**
     * Determines whether the specified object is equal to this <code>Expression</code>.
     * <p>
     * The result is <code>true</code> if and only if the argument is not <code>null</code>, is an
     * <code>Expression</code> object that is the of the same type (<code>ValueExpression</code> or
     * <code>MethodExpression</code>), and has an identical parsed representation.
     * </p>
     * <p>
     * Note that two expressions can be equal if their expression Strings are different. For example,
     * <code>${fn1:foo()}</code> and <code>${fn2:foo()}</code> are equal if their corresponding
     * <code>FunctionMapper</code>s mapped <code>fn1:foo</code> and <code>fn2:foo</code> to the same method.
     * </p>
     *
     * @param obj the <code>Object</code> to test for equality.
     *
     * @return <code>true</code> if <code>obj</code> equals this <code>Expression</code>; <code>false</code> otherwise.
     *
     * @see java.util.Hashtable
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @Override
    public boolean equals(Object obj) {
        return (obj instanceof MethodExpressionImpl && obj.hashCode() == this.hashCode());
    }

    /**
     * Returns the original String used to create this <code>Expression</code>, unmodified.
     * <p>
     * This is used for debugging purposes but also for the purposes of comparison (e.g. to ensure the expression in a
     * configuration file has not changed).
     * </p>
     * <p>
     * This method does not provide sufficient information to re-create an expression. Two different expressions can
     * have exactly the same expression string but different function mappings. Serialization should be used to save and
     * restore the state of an <code>Expression</code>.
     * </p>
     *
     * @return The original expression String.
     *
     * @see jakarta.el.Expression#getExpressionString()
     */
    @Override
    public String getExpressionString() {
        return this.expr;
    }

    /**
     * Evaluates the expression relative to the provided context, and returns information about the actual referenced
     * method.
     *
     * @param context The context of this evaluation
     *
     * @return an instance of <code>MethodInfo</code> containing information about the method the expression evaluated
     *             to.
     *
     * @throws NullPointerException      if context is <code>null</code> or the base object is <code>null</code> on the
     *                                       last resolution.
     * @throws PropertyNotFoundException if one of the property resolutions failed because a specified variable or
     *                                       property does not exist or is not readable.
     * @throws MethodNotFoundException   if no suitable method can be found.
     * @throws ELException               if an exception was thrown while performing property or variable resolution.
     *                                       The thrown exception must be included as the cause property of this
     *                                       exception, if available.
     *
     * @see jakarta.el.MethodExpression#getMethodInfo(jakarta.el.ELContext)
     */
    @Override
    public MethodInfo getMethodInfo(ELContext context)
            throws PropertyNotFoundException, MethodNotFoundException, ELException {
        Node n = this.getNode();
        EvaluationContext ctx = new EvaluationContext(context, this.fnMapper, this.varMapper);
        ctx.notifyBeforeEvaluation(getExpressionString());
        MethodInfo result = n.getMethodInfo(ctx, this.paramTypes);
        ctx.notifyAfterEvaluation(getExpressionString());
        return result;
    }

    private Node getNode() throws ELException {
        if (this.node == null) {
            this.node = ExpressionBuilder.createNode(this.expr);
        }
        return this.node;
    }

    /**
     * Returns the hash code for this <code>Expression</code>.
     * <p>
     * See the note in the {@link #equals} method on how two expressions can be equal if their expression Strings are
     * different. Recall that if two objects are equal according to the <code>equals(Object)</code> method, then calling
     * the <code>hashCode</code> method on each of the two objects must produce the same integer result. Implementations
     * must take special note and implement <code>hashCode</code> correctly.
     * </p>
     *
     * @return The hash code for this <code>Expression</code>.
     *
     * @see #equals
     * @see java.util.Hashtable
     * @see java.lang.Object#hashCode()
     */
    @Override
    public int hashCode() {
        return this.expr.hashCode();
    }

    /**
     * Evaluates the expression relative to the provided context, invokes the method that was found using the supplied
     * parameters, and returns the result of the method invocation.
     *
     * @param context The context of this evaluation.
     * @param params  The parameters to pass to the method, or <code>null</code> if no parameters.
     *
     * @return the result of the method invocation (<code>null</code> if the method has a <code>void</code> return
     *             type).
     *
     * @throws NullPointerException      if context is <code>null</code> or the base object is <code>null</code> on the
     *                                       last resolution.
     * @throws PropertyNotFoundException if one of the property resolutions failed because a specified variable or
     *                                       property does not exist or is not readable.
     * @throws MethodNotFoundException   if no suitable method can be found.
     * @throws ELException               if an exception was thrown while performing property or variable resolution.
     *                                       The thrown exception must be included as the cause property of this
     *                                       exception, if available. If the exception thrown is an
     *                                       <code>InvocationTargetException</code>, extract its <code>cause</code> and
     *                                       pass it to the <code>ELException</code> constructor.
     *
     * @see jakarta.el.MethodExpression#invoke(jakarta.el.ELContext, java.lang.Object[])
     */
    @Override
    public Object invoke(ELContext context, Object[] params)
            throws PropertyNotFoundException, MethodNotFoundException, ELException {
        EvaluationContext ctx = new EvaluationContext(context, this.fnMapper, this.varMapper);
        ctx.notifyBeforeEvaluation(getExpressionString());
        Object result = this.getNode().invoke(ctx, this.paramTypes, params);
        ctx.notifyAfterEvaluation(getExpressionString());
        return result;
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        this.expr = in.readUTF();
        String type = in.readUTF();
        if (!type.isEmpty()) {
            this.expectedType = ReflectionUtil.forName(type);
        }
        this.paramTypes = ReflectionUtil.toTypeArray(((String[]) in.readObject()));
        this.fnMapper = (FunctionMapper) in.readObject();
        this.varMapper = (VariableMapper) in.readObject();
    }

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeUTF(this.expr);
        out.writeUTF((this.expectedType != null) ? this.expectedType.getName() : "");
        out.writeObject(ReflectionUtil.toTypeNameArray(this.paramTypes));
        out.writeObject(this.fnMapper);
        out.writeObject(this.varMapper);
    }

    @Override
    public boolean isLiteralText() {
        return false;
    }


    @Override
    public boolean isParametersProvided() {
        return this.getNode().isParametersProvided();
    }


    @Override
    public MethodReference getMethodReference(ELContext context) {
        EvaluationContext ctx = new EvaluationContext(context, this.fnMapper, this.varMapper);
        ctx.notifyBeforeEvaluation(getExpressionString());
        MethodReference methodReference = this.getNode().getMethodReference(ctx);
        ctx.notifyAfterEvaluation(getExpressionString());
        return methodReference;
    }
}
