/*
 * 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:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.descriptors;

import java.io.Serializable;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.internal.queries.ContainerPolicy;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedClassForName;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.queries.ComplexQueryResult;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
import org.eclipse.persistence.queries.ReadAllQuery;
import org.eclipse.persistence.queries.ReadObjectQuery;

/**
 * <b>Purpose</b>: Allows for a descriptor's implemented interfaces to be configured.
 * Generally Interface Descriptors are used for 1 of 2 reasons:<p>
 *      a. Interface descriptors can be used to query across a set of classes that do not share a table.<br>
 *      b. As a target of a variable one to one mapping.
 *
 * @since TopLink for Java 2.0
 */
public class InterfacePolicy implements Serializable, Cloneable {
    protected List<Class<?>> parentInterfaces;
    protected List<String> parentInterfaceNames;
    protected List<ClassDescriptor> parentDescriptors;
    protected List<ClassDescriptor> childDescriptors;
    protected ClassDescriptor descriptor;
    protected Class<?> implementorDescriptor;
    protected String implementorDescriptorClassName;

    /**
     * INTERNAL:
     * Create a new policy.
     * Only descriptor involved in interface should have a policy.
     */
    public InterfacePolicy() {
        this.childDescriptors = new ArrayList<>();
        this.parentInterfaces = new ArrayList<>(2);
        this.parentInterfaceNames = new ArrayList<>(2);
        this.parentDescriptors = new ArrayList<>(2);
    }

    /**
     * INTERNAL:
     * Create a new policy.
     * Only descriptor involved in interface should have a policy.
     */
    public InterfacePolicy(ClassDescriptor descriptor) {
        this();
        this.descriptor = descriptor;
    }

    /**
     * INTERNAL:
     * Add child descriptor to the parent descriptor.
     */
    public void addChildDescriptor(ClassDescriptor childDescriptor) {
        getChildDescriptors().add(childDescriptor);
    }

    /**
     * INTERNAL:
     * Add parent descriptor.
     */
    public void addParentDescriptor(ClassDescriptor parentDescriptor) {
        getParentDescriptors().add(parentDescriptor);
    }

    /**
     * PUBLIC:
     * Add the parent Interface class.
     *
     * This method should be called once for each parent Interface of the Descriptor.
     */
    public void addParentInterface(Class<?> parentInterface) {
        getParentInterfaces().add(parentInterface);
    }

    public void addParentInterfaceName(String parentInterfaceName) {
        getParentInterfaceNames().add(parentInterfaceName);
    }

    /**
     * INTERNAL:
     * Return if there are any child descriptors.
     */
    public boolean hasChild() {
        return this.childDescriptors.size() > 0;
    }

    /**
     * INTERNAL:
     * Return all the child descriptors.
     */
    public List<ClassDescriptor> getChildDescriptors() {
        return childDescriptors;
    }

    protected ClassDescriptor getDescriptor() {
        return descriptor;
    }

    /**
     * INTERNAL:
     * Returns the implementor descriptor class.
     */
    @SuppressWarnings({"unchecked"})
    public <T> Class<T> getImplementorDescriptor() {
        return (Class<T>) implementorDescriptor;
    }

    /**
     * INTERNAL:
     * Returns the implementor descriptor class name.
     */
    public String getImplementorDescriptorClassName() {
        if ((implementorDescriptorClassName == null) && (implementorDescriptor != null)) {
            implementorDescriptorClassName = implementorDescriptor.getName();
        }
        return implementorDescriptorClassName;
    }

    /**
     * INTERNAL:
     * Return all the parent descriptors.
     */
    public List<ClassDescriptor> getParentDescriptors() {
        return parentDescriptors;
    }

    /**
     * INTERNAL:
     * Return the list of parent interfaces.
     */
    public List<Class<?>> getParentInterfaces() {
        return parentInterfaces;
    }

    public List<String> getParentInterfaceNames() {
        if (parentInterfaceNames.isEmpty() && !parentInterfaces.isEmpty()) {
            for (int i = 0; i < parentInterfaces.size(); i++) {
                parentInterfaceNames.add(parentInterfaces.get(i).getName());
            }
        }
        return parentInterfaceNames;
    }

    /**
     * INTERNAL:
     * Convert all the class-name-based settings in this InheritancePolicy to actual class-based settings.
     * This method is used when converting a project that has been built with class names to a project with classes.
     * It will also convert referenced classes to the versions of the classes from the classLoader.
     */
    public void convertClassNamesToClasses(ClassLoader classLoader) {
        List<Class<?>> newParentInterfaces = new ArrayList<>(2);
        for (Iterator<String> iterator = getParentInterfaceNames().iterator(); iterator.hasNext(); ) {
            String interfaceName = iterator.next();
            Class<?> interfaceClass = null;
            try {
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                    try {
                        interfaceClass = AccessController.doPrivileged(new PrivilegedClassForName<>(interfaceName, true, classLoader));
                    } catch (PrivilegedActionException exception) {
                        throw ValidationException.classNotFoundWhileConvertingClassNames(interfaceName, exception.getException());
                    }
                } else {
                    interfaceClass = org.eclipse.persistence.internal.security.PrivilegedAccessHelper.getClassForName(interfaceName, true, classLoader);
                }
            } catch (ClassNotFoundException exc){
                throw ValidationException.classNotFoundWhileConvertingClassNames(interfaceName, exc);
            }
            newParentInterfaces.add(interfaceClass);
        }
        this.parentInterfaces = newParentInterfaces;
    }

    /**
     * INTERNAL:
     * Set the vector to store parent interfaces.
     */
    public void initialize(AbstractSession session) {
    }

    /**
     * INTERNAL:
     * Check if it is a child descriptor.
     */
    public boolean isInterfaceChildDescriptor() {
        return ((!(parentInterfaces == null) && !parentInterfaces.isEmpty()) ||
            (!(parentInterfaceNames == null) && !parentInterfaceNames.isEmpty()));
    }

    /**
     * INTERNAL:
     */
    public boolean isTablePerClassPolicy() {
        return false;
    }

    /**
     * INTERNAL:
     * Select all objects for a concrete descriptor.
     */
    protected Object selectAllObjects(ReadAllQuery query) {
        ReadAllQuery concreteQuery = (ReadAllQuery)prepareQuery(query);
        return query.getSession().executeQuery(concreteQuery, query.getTranslationRow());
    }

    /**
     * INTERNAL:
     * Select all objects for a concrete descriptor.
     */
    protected ObjectLevelReadQuery prepareQuery(ObjectLevelReadQuery query) {
        ObjectLevelReadQuery concreteQuery = null;
        Class<?> javaClass = this.descriptor.getJavaClass();
        // PERF: First check the subclass query cache for the prepared query.
        boolean shouldPrepare = query.shouldPrepare();
        if (shouldPrepare) {
            concreteQuery = (ObjectLevelReadQuery)query.getConcreteSubclassQueries().get(javaClass);
        }
        if (concreteQuery == null) {
            concreteQuery = (ObjectLevelReadQuery)query.deepClone();
            concreteQuery.setReferenceClass(javaClass);
            concreteQuery.setDescriptor(this.descriptor);
            // Disable query cache from implementation queries.
            concreteQuery.setQueryResultsCachePolicy(null);
            concreteQuery.getExpressionBuilder().setQueryClassAndDescriptor(javaClass, this.descriptor);

            // Update the selection criteria if needed as well and don't lose
            // the translation row.
            if (concreteQuery.getQueryMechanism().getSelectionCriteria() != null) {
                //make sure query builder is used for the selection criteria as deepClone will create
                //two separate builders.
                concreteQuery.getExpressionBuilder().setSession(query.getSession().getRootSession(concreteQuery));
                concreteQuery.setSelectionCriteria(concreteQuery.getQueryMechanism().getSelectionCriteria().rebuildOn(concreteQuery.getExpressionBuilder()));
            }
            if (concreteQuery.hasAdditionalFields()) {
                List<Object> rebuiltFields = new ArrayList<>(concreteQuery.getAdditionalFields().size());
                for (Object field : concreteQuery.getAdditionalFields()) {
                    if (field instanceof Expression) {
                        rebuiltFields.add(((Expression)field).rebuildOn(concreteQuery.getExpressionBuilder()));
                    } else {
                        rebuiltFields.add(field);
                    }
                }
                concreteQuery.setAdditionalFields(rebuiltFields);
            }
            if (shouldPrepare) {
                concreteQuery.setTranslationRow(null);
                if (concreteQuery.isReadObjectQuery()) {
                    ((ReadObjectQuery)concreteQuery).clearSelectionId();
                }
                concreteQuery.checkPrepare(query.getSession(), query.getTranslationRow());
                query.getConcreteSubclassQueries().put(javaClass, concreteQuery);
                concreteQuery = (ObjectLevelReadQuery)concreteQuery.clone();
                concreteQuery.setTranslationRow(query.getTranslationRow());
            }
            concreteQuery.setIsExecutionClone(true);
        } else {
            concreteQuery = (ObjectLevelReadQuery)concreteQuery.clone();
            concreteQuery.setIsExecutionClone(true);
            concreteQuery.setTranslationRow(query.getTranslationRow());
        }

        return concreteQuery;
    }

    /**
     * INTERNAL:
     * Select all objects for an interface descriptor.
     * This is accomplished by selecting for all of the concrete classes and then merging the objects.
     */
    public Object selectAllObjectsUsingMultipleTableSubclassRead(ReadAllQuery query) throws DatabaseException {
        ContainerPolicy containerPolicy = query.getContainerPolicy();
        Object objects = containerPolicy.containerInstance();
        if (query.shouldIncludeData()) {
            ComplexQueryResult result = new ComplexQueryResult();
            result.setResult(objects);
            result.setData(new ArrayList());
            objects = result;
        }
        int size = this.childDescriptors.size();
        for (int index = 0; index < size; index++) {
            ClassDescriptor descriptor = this.childDescriptors.get(index);
            objects = containerPolicy.concatenateContainers(
                    objects, descriptor.getInterfacePolicy().selectAllObjects(query), query.getSession());
        }

        return objects;
    }

    /**
     * INTERNAL:
     * Select one object of any concrete subclass.
     */
    protected Object selectOneObject(ReadObjectQuery query) throws DescriptorException {
        ReadObjectQuery concreteQuery = (ReadObjectQuery)prepareQuery(query);
        return query.getSession().executeQuery(concreteQuery, concreteQuery.getTranslationRow());
    }

    /**
     * INTERNAL:
     * Select one object of any concrete subclass.
     */
    public Object selectOneObjectUsingMultipleTableSubclassRead(ReadObjectQuery query) throws DatabaseException, QueryException {
        int size = this.childDescriptors.size();
        for (int index = 0; index < size; index++) {
            ClassDescriptor descriptor = this.childDescriptors.get(index);
            Object object = descriptor.getInterfacePolicy().selectOneObject(query);
            if (object != null) {
                return object;
            }
        }

        return null;
    }

    /**
     * INTERNAL:
     * Set the descriptor.
     */
    public void setDescriptor(ClassDescriptor descriptor) {
        this.descriptor = descriptor;
    }

    /**
     * INTERNAL:
     * Sets the implementor descriptor class.
     */
    public void setImplementorDescriptor(Class<?> implementorDescriptor) {
        this.implementorDescriptor = implementorDescriptor;
    }

    /**
     * INTERNAL:
     * Sets the implementor descriptor class name.
     */
    public void setImplementorDescriptorClassName(String implementorDescriptorClassName) {
        this.implementorDescriptorClassName = implementorDescriptorClassName;
    }

    /**
     * Set the Vector to store parent interfaces.
     */
    public void setParentInterfaces(List<Class<?>> parentInterfaces) {
        this.parentInterfaces = parentInterfaces;
    }

    public void setParentInterfaceNames(List<String> parentInterfaceNames) {
        this.parentInterfaceNames = parentInterfaceNames;
    }

    /**
     * INTERNAL:
     * Returns true if this descriptor should be ignored and the implementing
     * descriptor should be used instead.
     */
    public boolean usesImplementorDescriptor() {
        return (implementorDescriptor != null);
    }
}
