/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. 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,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     05/16/2008-1.0M8 Guy Pelletier
//       - 218084: Implement metadata merging functionality between mapping files
//     01/05/2010-2.1 Guy Pelletier
//       - 211324: Add additional event(s) support to the EclipseLink-ORM.XML Schema
//     07/15/2010-2.2 Guy Pelletier
//       -311395 : Multiple lifecycle callback methods for the same lifecycle event
//     12/14/2017-3.0 Tomas Kraus
//       - 291546: Performance degradation due to usage of Vector in DescriptorEventManager
package org.eclipse.persistence.internal.jpa.metadata.listeners;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.eclipse.persistence.descriptors.DescriptorEvent;
import org.eclipse.persistence.descriptors.DescriptorEventAdapter;
import org.eclipse.persistence.descriptors.DescriptorEventManager;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedMethodInvoker;
import org.eclipse.persistence.internal.security.PrivilegedNewInstanceFromClass;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.logging.SessionLog;

/**
 * An EntityListener is placed on the owning entity's descriptor.
 * Callback methods from an EntityListener require a signature on the method.
 * Namely, they must have an Object parameter.
 *
 * @author Guy Pelletier
 * @since Eclipselink 1.0
 */
public class EntityListener<T> extends DescriptorEventAdapter {
    public final static String POST_BUILD = "postBuild";
    public final static String POST_CLONE = "postClone";
    public final static String POST_DELETE = "postDelete";
    public final static String POST_INSERT = "postInsert";
    public final static String POST_REFRESH = "postRefresh";
    public final static String POST_UPDATE = "postUpdate";
    public final static String PRE_PERSIST = "prePersist";
    public final static String PRE_REMOVE = "preRemove";
    public final static String PRE_UPDATE_WITH_CHANGES = "preUpdateWithChanges";

    private T m_listener;
    private Class<T> m_listenerClass;
    private Class m_entityClass;
    private Map<String, List<Method>> m_methods;
    private final Map<String, Map<Integer, Boolean>> m_overriddenEvents;
    private static final Map<Integer, String> m_eventStrings;
    private AbstractSession owningSession;

    static {
        // For quick look up of equivalent event strings from event codes.
        Map<Integer, String> mappings = new HashMap<>(9);
        mappings.put(DescriptorEventManager.PostBuildEvent, POST_BUILD);
        mappings.put(DescriptorEventManager.PostCloneEvent, POST_CLONE);
        mappings.put(DescriptorEventManager.PostDeleteEvent, POST_DELETE);
        mappings.put(DescriptorEventManager.PostInsertEvent, POST_INSERT);
        mappings.put(DescriptorEventManager.PostRefreshEvent, POST_REFRESH);
        mappings.put(DescriptorEventManager.PostUpdateEvent, POST_UPDATE);
        mappings.put(DescriptorEventManager.PrePersistEvent, PRE_PERSIST);
        mappings.put(DescriptorEventManager.PreRemoveEvent, PRE_REMOVE);
        mappings.put(DescriptorEventManager.PreUpdateWithChangesEvent, PRE_UPDATE_WITH_CHANGES);
        m_eventStrings = Collections.unmodifiableMap(mappings);
    }
    /**
     * INTERNAL:
     */
    protected EntityListener(Class entityClass) {
        m_entityClass = entityClass;
        m_methods = new ConcurrentHashMap<>();

        // Remember which events are overridden in subclasses. Overridden events
        // must be built for each subclass chain.
        m_overriddenEvents = new ConcurrentHashMap<>();
    }

    public EntityListener(Class<T> listenerClass, Class entityClass){
        this(entityClass);
        this.m_listenerClass = listenerClass;
    }

    /**
     * INTERNAL:
     * You can have multiple event methods for the same event, however, only
     * one event method per class is permitted.
     */
    public void addEventMethod(String event, Method method) {
        if (m_methods.containsKey(event)) {
            Method lastEventMethod = getLastEventMethod(event);

            if (lastEventMethod.getDeclaringClass().equals(method.getDeclaringClass())) {
                throw ValidationException.multipleLifecycleCallbackMethodsForSameLifecycleEvent(getListenerClass(), method, lastEventMethod);
            } else {
                // We must be adding a callback method from a mapped superclass
                // at this point, so validate the method and add it.
                validateMethod(method);
                m_methods.get(event).add(method);
            }
        } else {
            // Validate the method is valid.
            validateMethod(method);

            // Create the methods list and add this method to it.
            List<Method> methods = new ArrayList<>();
            methods.add(method);
            m_methods.put(event, methods);
        }
    }

    /**
     * Create the wrapped listener and trigger CDI injection.
     * @param entityListenerClass the {@link EntityListener} class
     * @return the class instance that has had injection run on it. If injection fails, null.
     */
    protected T createEntityListenerAndInjectDependencies(Class<T> entityListenerClass){
        try{
            return owningSession.<T>getInjectionManager().createManagedBeanAndInjectDependencies(entityListenerClass);
        } catch (Exception e){
            owningSession.logThrowable(SessionLog.FINEST, SessionLog.JPA, e);
        }
        return null;
    }

    /**
     * Construct an instance of the wrapped entity listener
     * This method will attempt to create the listener in a CDI injection
     * friendly manner and if that fails, reflectively instantiate the class
     * @return the entity listener instance
     */
    protected T constructListenerInstance(){
        T entityListenerClassInstance =  createEntityListenerAndInjectDependencies(m_listenerClass);
        try {
            if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                try {
                    if (entityListenerClassInstance == null){
                        entityListenerClassInstance = AccessController.doPrivileged(new PrivilegedNewInstanceFromClass<>(m_listenerClass));
                    }
                } catch (PrivilegedActionException exception) {
                    throw ValidationException.errorInstantiatingClass(m_listenerClass, exception.getException());
                }
            } else {
                if (entityListenerClassInstance == null){
                    entityListenerClassInstance = PrivilegedAccessHelper.newInstanceFromClass(m_listenerClass);
                }
            }
        } catch (IllegalAccessException | InstantiationException exception) {
            throw ValidationException.errorInstantiatingClass(m_listenerClass, exception);
        }
        return entityListenerClassInstance;
    }

    /**
     * INTERNAL:
     */
    public Class getEntityClass() {
        return m_entityClass;
    }

    /**
     * INTERNAL:
     */
    public Map<String, List<Method>> getAllEventMethods() {
        return m_methods;
    }

    /**
     * INTERNAL:
     */
    public void setAllEventMethods(Map<String, List<Method>> methods) {
        m_methods = methods;
    }

    /**
     * INTERNAL:
     */
    public void setOwningSession(AbstractSession owningSession) {
        this.owningSession = owningSession;
    }

    /**
     * INTERNAL:
     */
    protected List<Method> getEventMethods(int eventCode) {
        String eventString = m_eventStrings.get(eventCode);
        return eventString != null ? getEventMethods(eventString) : null;
    }

    /**
     * INTERNAL:
     */
    protected List<Method> getEventMethods(String event) {
        return m_methods.get(event);
    }

    /**
     * INTERNAL:
     * Assumes a check for event methods for the given event has been called
     * beforehand.
     */
    protected Method getLastEventMethod(String event) {
        List<Method> methods = m_methods.get(event);
        return methods.get(methods.size()-1);
    }

    public T getListener() {
        if (m_listener == null){
            m_listener = constructListenerInstance();
        }
        return m_listener;
    }
    
    /**
     * INTERNAL:
     */
    public Class getListenerClass() {
        return m_listenerClass;
    }

    /**
     * INTERNAL:
     */
    public AbstractSession getOwningSession() {
        return owningSession;
    }

    /**
     * INTERNAL:
     */
    public boolean hasCallbackMethods() {
        return m_methods.size() > 0;
    }

    /**
     * INTERNAL:
     */
    protected boolean hasEventMethods(int eventCode) {
        return getEventMethods(eventCode) != null;
    }

    /**
     * INTERNAL:
     */
    protected boolean hasEventMethods(String event) {
        return getEventMethods(event) != null;
    }

    /**
     * INTERNAL:
     */
    protected boolean hasOverriddenEventMethod(List<Method> eventMethods, Method eventMethod) {
        if (eventMethods != null) {
            for (Method method : eventMethods) {
                if (method.getName().equals(eventMethod.getName())) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * INTERNAL:
     */
    protected boolean hasOverriddenEventMethod(Method eventMethod, int eventCode) {
        return hasOverriddenEventMethod(getEventMethods(eventCode), eventMethod);
    }

    /**
     * INTERNAL:
     */
    protected boolean hasOverriddenEventMethod(Method eventMethod, String eventCode) {
        return hasOverriddenEventMethod(getEventMethods(eventCode), eventMethod);
    }

    /**
     * INTERNAL:
     */
    void invokeMethod(Method method, Object onObject, Object[] objectList) {
        if (method != null) {
            try {
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                    try {
                        AccessController.doPrivileged(new PrivilegedMethodInvoker<Void>(method, onObject, objectList));
                    } catch (PrivilegedActionException exception) {
                        Exception throwableException = exception.getException();
                        if (throwableException instanceof IllegalAccessException) {
                            throw ValidationException.invalidCallbackMethod(onObject.getClass(), method.toString());
                        } else {
                            Throwable cause = throwableException.getCause();

                            if (cause instanceof RuntimeException) {
                                throw (RuntimeException) cause;
                            } else {
                                throw (Error) cause;
                            }
                        }
                    }
                } else {
                    PrivilegedAccessHelper.invokeMethod(method, onObject, objectList);
                }
            } catch (IllegalAccessException exception) {
                throw ValidationException.invalidCallbackMethod(onObject.getClass(), method.toString());
            } catch (InvocationTargetException e) {
                Throwable cause = e.getCause();

                if (cause instanceof RuntimeException) {
                    throw (RuntimeException) cause;
                } else {
                    throw (Error) cause;
                }
            }
        }
    }

    /**
     * INTERNAL:
     */
    void invokeMethod(String event, DescriptorEvent descriptorEvent) {
        List<Method> eventMethods = getEventMethods(event);
        if (eventMethods != null) {
            for (Method method : eventMethods) {
                Object[] objectList = { descriptorEvent.getSource() };
                invokeMethod(method, getListener(), objectList);
            }
        }
    }

    /**
     * INTERNAL:
     * Return true if listener has a lifecycle callback method that is
     * overridden in a subclass.
     */
    @Override
    public boolean isOverriddenEvent(DescriptorEvent event, List<DescriptorEventManager> eventManagers) {
        int eventCode = event.getEventCode();
        String forSubclass = event.getDescriptor().getJavaClassName();
        Map<Integer, Boolean> subClassMap = m_overriddenEvents.get(forSubclass);

        // If we haven't built an overridden events map for this subclass, do so now.
        if (subClassMap == null) {
            subClassMap = new ConcurrentHashMap<>();
        }

        // Now check the individual events for this subclass.
        if (! subClassMap.containsKey(eventCode)) {
            boolean hasOverrides = false;
            if (hasEventMethods(eventCode)) {
                List<Method> eventMethods = getEventMethods(eventCode);
                for (Method eventMethod : eventMethods) {
                    for (DescriptorEventManager eventManager : eventManagers) {
                        EntityListener childListener = (EntityListener) eventManager.getEntityEventListener();

                        // We can't override ourselves ...
                        if (childListener == this) {
                            break;
                        } else {
                            if (childListener.hasOverriddenEventMethod(eventMethod, eventCode)) {
                                hasOverrides = true;
                                break;
                            }
                        }
                    }
                    if (hasOverrides){
                        break;
                    }
                }
            }
            subClassMap.put(eventCode, hasOverrides);
            //putting this here prevents a vm reorder from putting an unbuilt Map in the
            //m_overriddenEvents collection
            m_overriddenEvents.put(forSubclass, subClassMap);
        }

        return subClassMap.get(eventCode);
    }

    /**
     * INTERNAL:
     */
    @Override
    public void postBuild(DescriptorEvent event) {
        invokeMethod(POST_BUILD, event);
    }

    /**
     * INTERNAL:
     */
    @Override
    public void postClone(DescriptorEvent event) {
        invokeMethod(POST_CLONE, event);
    }

    /**
     * INTERNAL:
     */
    @Override
    public void postDelete(DescriptorEvent event) {
        invokeMethod(POST_DELETE, event);
    }

    /**
     * INTERNAL:
     */
    @Override
    public void postInsert(DescriptorEvent event) {
        invokeMethod(POST_INSERT, event);
    }

    /**
     * INTERNAL:
     */
    @Override
    public void postRefresh(DescriptorEvent event) {
        invokeMethod(POST_REFRESH, event);
    }

    /**
     * INTERNAL:
     */
    @Override
    public void postUpdate(DescriptorEvent event) {
        invokeMethod(POST_UPDATE, event);
    }

    /**
     * INTERNAL:
     */
    @Override
    public void prePersist(DescriptorEvent event) {
        invokeMethod(PRE_PERSIST, event);
    }

    /**
     * INTERNAL:
     */
    @Override
    public void preRemove(DescriptorEvent event) {
        invokeMethod(PRE_REMOVE, event);
    }

    /**
     * INTERNAL:
     */
    @Override
    public void preUpdateWithChanges(DescriptorEvent event) {
        invokeMethod(PRE_UPDATE_WITH_CHANGES, event);
    }

    /**
     * INTERNAL:
     */
    public void setPostBuildMethod(Method method) {
        addEventMethod(POST_BUILD, method);
    }

    /**
     * INTERNAL:
     */
    public void setPostCloneMethod(Method method) {
        addEventMethod(POST_CLONE, method);
    }

    /**
     * INTERNAL:
     */
    public void setPostDeleteMethod(Method method) {
        addEventMethod(POST_DELETE, method);
    }

    /**
     * INTERNAL:
     */
    public void setPostInsertMethod(Method method) {
        addEventMethod(POST_INSERT, method);
    }

    /**
     * INTERNAL:
     */
    public void setPostRefreshMethod(Method method) {
        addEventMethod(POST_REFRESH, method);
    }

    /**
     * INTERNAL:
     */
    public void setPostUpdateMethod(Method method) {
        addEventMethod(POST_UPDATE, method);
    }

    /**
     * INTERNAL:
     */
    public void setPrePersistMethod(Method method) {
        addEventMethod(PRE_PERSIST, method);
    }

    /**
     * INTERNAL:
     */
    public void setPreRemoveMethod(Method method) {
        addEventMethod(PRE_REMOVE, method);
    }

    /**
     * INTERNAL:
     */
    public void setPreUpdateWithChangesMethod(Method method) {
        addEventMethod(PRE_UPDATE_WITH_CHANGES, method);
    }

    /**
     * INTERNAL:
     * Used in the debugger.
     */
    @Override
    public String toString() {
        return getEntityClass().getName();
    }

    /**
     * INTERNAL:
     */
    protected void validateMethod(Method method) {
        int numberOfParameters = method.getParameterTypes().length;

        if (numberOfParameters == 1 && method.getParameterTypes()[0].isAssignableFrom(m_entityClass)) {
            // So far so good, now check the method modifiers.
            validateMethodModifiers(method);
        } else {
            Class parameterClass = (numberOfParameters == 0) ? null : method.getParameterTypes()[0];
            throw ValidationException.invalidEntityListenerCallbackMethodArguments(m_entityClass, parameterClass, getListenerClass(), method.getName());
        }
    }

    /**
     * INTERNAL:
     */
    protected void validateMethodModifiers(Method method) {
        int modifiers = method.getModifiers();

        if (Modifier.isStatic(modifiers) || Modifier.isFinal(modifiers)) {
            throw ValidationException.invalidCallbackMethodModifier(getListenerClass(), method.getName());
        }
    }
}
