/*
 * Copyright (c) 2012, 2018 Oracle and/or its affiliates and others.
 * All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package javax.el;

import static java.lang.reflect.Modifier.isPublic;
import static java.lang.reflect.Modifier.isStatic;
import static javax.el.ELUtil.getExceptionMessageString;

import java.beans.FeatureDescriptor;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Iterator;

/**
 * An {@link ELResolver} for resolving static fields, enum constants and static methods. Also handles constructor calls
 * as a special case.
 * 
 * <p>
 * The resolver handles base objects of the type {@link ELClass}, which is usually generated by a Jakarta Expression
 * Language implementation.
 *
 * @see ELClass
 * @since Jakarta Expression Language 3.0
 */
public class StaticFieldELResolver extends ELResolver {

    /**
     * <p>
     * Returns the value of a static field.
     * </p>
     * <p>
     * If the base object is an instance of <code>ELClass</code> and the property is String, the
     * <code>propertyResolved</code> property of the <code>ELContext</code> object must be set to <code>true</code> by this
     * resolver, before returning. If this property is not <code>true</code> after this method is called, the caller should
     * ignore the return value.
     * </p>
     *
     * If the property is a public static field of class specified in <code>ELClass</code>, return the value of the static
     * field. An Enum constant is a public static field of an Enum object, and is a special case of this.
     *
     * @param context The context of this evaluation.
     * @param base An <code>ELClass</code>.
     * @param property A static field name.
     * 
     * @return If the <code>propertyResolved</code> property of <code>ELContext</code> was set to <code>true</code>, then
     * the static field value.
     * 
     * @throws NullPointerException if context is <code>null</code>.
     * @throws PropertyNotFoundException if the specified class does not exist, or if the field is not a public static filed
     * of the class, or if the field is inaccessible.
     */
    @Override
    public Object getValue(ELContext context, Object base, Object property) {
        if (context == null) {
            throw new NullPointerException();
        }

        if (base instanceof ELClass && property instanceof String) {
            Class<?> klass = ((ELClass) base).getKlass();
            String fieldName = (String) property;
            try {
                context.setPropertyResolved(base, property);
                Field field = klass.getField(fieldName);

                int mod = field.getModifiers();
                if (Modifier.isPublic(mod) && Modifier.isStatic(mod)) {
                    return field.get(null);
                }
            } catch (NoSuchFieldException ex) {
            } catch (IllegalAccessException ex) {
            }

            throw new PropertyNotFoundException(ELUtil.getExceptionMessageString(context, "staticFieldReadError", new Object[] { klass.getName(), fieldName }));
        }

        return null;
    }

    /**
     * <p>
     * Attempts to write to a static field.
     * </p>
     * <p>
     * If the base object is an instance of <code>ELClass</code>and the property is String, a
     * <code>PropertyNotWritableException</code> will always be thrown, because writing to a static field is not allowed.
     *
     * @param context The context of this evaluation.
     * @param base An <code>ELClass</code>
     * @param property The name of the field
     * @param value The value to set the field of the class to.
     * @throws NullPointerException if context is <code>null</code>
     * @throws PropertyNotWritableException if base object instance of <code>ELClass</code>and <code>property</code>
     * instance of String
     */
    @Override
    public void setValue(ELContext context, Object base, Object property, Object value) {
        if (context == null) {
            throw new NullPointerException();
        }

        if (base instanceof ELClass && property instanceof String) {
            Class<?> klass = ((ELClass) base).getKlass();
            String fieldName = (String) property;
            throw new PropertyNotWritableException(
                    getExceptionMessageString(context, "staticFieldWriteError", new Object[] { klass.getName(), fieldName }));
        }
    }

    /**
     * Invokes a public static method or the constructor for a class.
     *
     * <p>
     * If the base object is an instance of <code>ELClass</code> and the method is a String, the
     * <code>propertyResolved</code> property of the <code>ELContext</code> object must be set to <code>true</code> by the
     * resolver, before returning. If this property is not <code>true</code> after this method is called, the caller should
     * ignore the return value.
     *
     * <p>
     * Invoke the public static method specified by <code>method</code>.
     *
     * <p>
     * The process involved in the method selection is the same as that used in {@link BeanELResolver}.
     *
     * <p>
     * As a special case, if the name of the method is "&lt;init&gt;", the constructor for the class will be invoked.
     *
     * @param base An <code>ELClass</code>
     * @param methodName When coerced to a <code>String</code>, the simple name of the method.
     * @param paramTypes An array of Class objects identifying the method's formal parameter types, in declared order. Use
     * an empty array if the method has no parameters. Can be <code>null</code>, in which case the method's formal parameter
     * types are assumed to be unknown.
     * @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 MethodNotFoundException if no suitable method can be found.
     * @throws ELException if an exception was thrown while performing (base, method) 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.
     */
    @Override
    public Object invoke(ELContext context, Object base, Object methodName, Class<?>[] paramTypes, Object[] params) {
        if (context == null) {
            throw new NullPointerException();
        }

        if (!(base instanceof ELClass && methodName instanceof String)) {
            return null;
        }

        Class<?> klass = ((ELClass) base).getKlass();
        String name = (String) methodName;

        Object ret;
        if ("<init>".equals(name)) {
            Constructor<?> constructor = ELUtil.findConstructor(klass, paramTypes, params);
            ret = ELUtil.invokeConstructor(context, constructor, params);
        } else {
            Method method = ELUtil.findMethod(klass, name, paramTypes, params, true);
            ret = ELUtil.invokeMethod(context, method, null, params);
        }
        context.setPropertyResolved(base, methodName);

        return ret;
    }

    /**
     * Returns the type of a static field.
     *
     * <p>
     * If the base object is an instance of <code>ELClass</code>and the property is a String, the
     * <code>propertyResolved</code> property of the <code>ELContext</code> object must be set to <code>true</code> by the
     * resolver, before returning. If this property is not <code>true</code> after this method is called, the caller can
     * safely assume no value has been set.
     *
     * <p>
     * If the property string is a public static field of class specified in ELClass, return the type of the static field.
     *
     * @param context The context of this evaluation.
     * @param base An <code>ELClass</code>.
     * @param property The name of the field.
     * @return If the <code>propertyResolved</code> property of <code>ELContext</code> was set to <code>true</code>, then
     * the type of the type of the field.
     * @throws NullPointerException if context is <code>null</code>.
     * @throws PropertyNotFoundException if field is not a public static filed of the class, or if the field is
     * inaccessible.
     */
    @Override
    public Class<?> getType(ELContext context, Object base, Object property) {
        if (context == null) {
            throw new NullPointerException();
        }

        if (base instanceof ELClass && property instanceof String) {
            Class<?> klass = ((ELClass) base).getKlass();
            String fieldName = (String) property;
            try {
                context.setPropertyResolved(true);
                Field field = klass.getField(fieldName);

                int mod = field.getModifiers();
                if (isPublic(mod) && isStatic(mod)) {
                    return field.getType();
                }
            } catch (NoSuchFieldException ex) {
            }
            throw new PropertyNotFoundException(getExceptionMessageString(context, "staticFieldReadError", new Object[] { klass.getName(), fieldName }));
        }

        return null;
    }

    /**
     * <p>
     * Inquires whether the static field is writable.
     * </p>
     * <p>
     * If the base object is an instance of <code>ELClass</code>and the property is a String, the
     * <code>propertyResolved</code> property of the <code>ELContext</code> object must be set to <code>true</code> by the
     * resolver, before returning. If this property is not <code>true</code> after this method is called, the caller can
     * safely assume no value has been set.
     * </p>
     *
     * <p>
     * Always returns a <code>true</code> because writing to a static field is not allowed.
     * </p>
     *
     * @param context The context of this evaluation.
     * @param base An <code>ELClass</code>.
     * @param property The name of the bean.
     * @return <code>true</code>
     * @throws NullPointerException if context is <code>null</code>.
     */
    @Override
    public boolean isReadOnly(ELContext context, Object base, Object property) {
        if (context == null) {
            throw new NullPointerException();
        }

        if (base instanceof ELClass && property instanceof String) {
            ((ELClass) base).getKlass();
            context.setPropertyResolved(true);
        }

        return true;
    }

    /**
     * Returns the properties that can be resolved. Always returns <code>null</code>, since there is no reason to iterate
     * through a list of one element: field name.
     *
     * @param context The context of this evaluation.
     * @param base An <code>ELClass</code>.
     * @return <code>null</code>.
     */
    @Override
    public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context, Object base) {
        return null;
    }

    /**
     * Returns the type of the property. Always returns <code>String.class</code>, since a field name is a String.
     *
     * @param context The context of this evaluation.
     * @param base An <code>ELClass</code>.
     * @return <code>String.class</code>.
     */
    @Override
    public Class<?> getCommonPropertyType(ELContext context, Object base) {
        return String.class;
    }
}
