/*
 * Copyright (c) 2011, 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/19/2010-2.1 ailitchev - Bug 244124 - Add Nested FetchGroup
package org.eclipse.persistence.testing.tests.jpa.fetchgroups;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

import jakarta.persistence.EntityManager;
import jakarta.persistence.Query;

import org.eclipse.persistence.config.CacheIsolationType;
import org.eclipse.persistence.config.DescriptorCustomizer;
import org.eclipse.persistence.config.QueryHints;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.FetchGroupManager;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.jpa.JpaHelper;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.ForeignReferenceMapping;
import org.eclipse.persistence.queries.FetchGroup;
import org.eclipse.persistence.queries.FetchGroupTracker;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
import org.eclipse.persistence.sessions.Session;
import org.eclipse.persistence.sessions.server.ServerSession;

import org.eclipse.persistence.testing.framework.junit.JUnitTestCase;
import org.eclipse.persistence.testing.models.jpa.advanced.AdvancedTableCreator;
import org.eclipse.persistence.testing.models.jpa.advanced.Employee;
import org.eclipse.persistence.testing.models.jpa.advanced.EmployeePopulator;
import org.eclipse.persistence.testing.models.jpa.advanced.EquipmentCode;
import org.eclipse.persistence.testing.models.jpa.advanced.compositepk.CompositePKPopulator;
import org.eclipse.persistence.testing.models.jpa.advanced.compositepk.CompositePKTableCreator;
import org.eclipse.persistence.testing.tests.jpa.dynamic.QuerySQLTracker;

import org.junit.Test;

/**
 * Simple set of tests that verify the {@link FetchGroup} API. Need to verify
 * that the nesting and default behaves as expected.
 *
 * @author dclarke
 * @since EclipseLink 2.1
 */
public abstract class BaseFetchGroupTests extends JUnitTestCase {

    ClassDescriptor employeeDescriptor;
    boolean employeeDescriptorIsIsolatedOriginal;
    ClassDescriptor phoneDescriptor;
    ClassDescriptor addressDescriptor;
    int sessionLogLevelOriginal;

    public static FetchGroup defaultEmployeeFG;
    public static FetchGroup defaultPhoneFG;

    public BaseFetchGroupTests() {
        super();
    }

    public BaseFetchGroupTests(String name) {
        super(name);
    }

    /*
     * Fetch Group tests require weaving.
     */
    @Override
    public void runBare() throws Throwable {
        if (this.shouldRunTestOnServer()) {
            super.runBare();
        } else {
           if (isWeavingEnabled()) {
                super.runBare();
            }
        }
    }

    /**
     * Any FetchGroups setup in test cases are removed.
     * Descriptors should not be isolated.
     * Clear cache, install QuerySQLTracker.
     */
    @Override
    public void setUp() {
        Session session = getServerSession();

        employeeDescriptor = getDescriptor("Employee");
        phoneDescriptor = getDescriptor("PhoneNumber");
        addressDescriptor = getDescriptor("Address");

        // this causes recreation of the cache removing the previously cached queries
        session.getProject().setJPQLParseCacheMaxSize(session.getProject().getJPQLParseCacheMaxSize());

        clearFetchGroups(employeeDescriptor);
        clearFetchGroups(phoneDescriptor);
        clearFetchGroups(addressDescriptor);
        // reprepare read queries after all fetch groups are cleared for all descriptors
        reprepareReadQueries(employeeDescriptor);
        reprepareReadQueries(phoneDescriptor);
        reprepareReadQueries(addressDescriptor);

        assertConfig(employeeDescriptor, null, 0);
        assertConfig(addressDescriptor, null, 0);
        assertConfig(phoneDescriptor, null, 0);

        employeeDescriptorIsIsolatedOriginal = employeeDescriptor.isIsolated();
        if(employeeDescriptorIsIsolatedOriginal) {
            employeeDescriptor.setCacheIsolation(CacheIsolationType.ISOLATED);
        }

        clearCache();
        QuerySQLTracker.install(session);
        sessionLogLevelOriginal = session.getLogLevel();
        if(sessionLogLevelOriginal > SessionLog.FINE) {
            session.setLogLevel(SessionLog.FINE);
        }
    }

    /**
     * Any FetchGroups setup in test cases are removed.
     * Reset isolated flag on Employee descriptor.
     * Clear cache, uninstall QuerySQLTracker.
     */
    @Override
    public void tearDown() {
        Session session = getServerSession();

        // this causes recreation of the cache removing the previously cached queries
        session.getProject().setJPQLParseCacheMaxSize(session.getProject().getJPQLParseCacheMaxSize());

        clearFetchGroups(employeeDescriptor);
        clearFetchGroups(phoneDescriptor);
        clearFetchGroups(addressDescriptor);
        // reprepare read queries after all fetch groups are cleared for all descriptors
        clearReadQueries(employeeDescriptor);
        clearReadQueries(phoneDescriptor);
        clearReadQueries(addressDescriptor);
        if(employeeDescriptorIsIsolatedOriginal) {
            employeeDescriptor.setCacheIsolation(CacheIsolationType.ISOLATED);
        }

        clearCache();
        if(sessionLogLevelOriginal != session.getLogLevel()) {
            session.setLogLevel(sessionLogLevelOriginal);
        }
        QuerySQLTracker.uninstall(session);
    }

    void clearFetchGroups(ClassDescriptor descriptor) {
        FetchGroupManager manager = descriptor.getFetchGroupManager();
        if(manager != null) {
            if(manager.getDefaultFetchGroup() != null) {
                manager.setDefaultFetchGroup(null);
            }
            if(manager.getFetchGroups().size() > 0) {
                manager.getFetchGroups().clear();
            }
        }
    }

    void reprepareReadQueries(ClassDescriptor descriptor) {
        reprepareReadQueriesInternal(descriptor, false);
    }
    void clearReadQueries(ClassDescriptor descriptor) {
        reprepareReadQueriesInternal(descriptor, true);
    }
    private void reprepareReadQueriesInternal(ClassDescriptor descriptor, boolean shouldClear) {
        ObjectLevelReadQuery olrQuery;
        AbstractSession session = getServerSession();
        if(descriptor.getQueryManager().hasReadObjectQuery()) {
            // this un-prePrepares the query, causes executionFetchGroup to be rebuilt
            olrQuery = descriptor.getQueryManager().getReadObjectQuery();
            if(shouldClear) {
                olrQuery.setFetchGroupName(null);
                olrQuery.setShouldUseDefaultFetchGroup(true);
            } else {
                olrQuery.setShouldUseDefaultFetchGroup(olrQuery.shouldUseDefaultFetchGroup());
            }
            descriptor.getQueryManager().getReadObjectQuery().checkPrepare(session, null);
        }
        if(descriptor.getQueryManager().hasReadAllQuery()) {
            // this un-prePrepares the query, causes executionFetchGroup to be rebuilt
            olrQuery = descriptor.getQueryManager().getReadAllQuery();
            if(shouldClear) {
                olrQuery.setFetchGroupName(null);
                olrQuery.setShouldUseDefaultFetchGroup(true);
            } else {
                olrQuery.setShouldUseDefaultFetchGroup(olrQuery.shouldUseDefaultFetchGroup());
            }
            olrQuery.checkPrepare(session, null);
        }
        // this causes recreation of the cache removing the previously cached queries
        descriptor.getQueryManager().setExpressionQueryCacheMaxSize(descriptor.getQueryManager().getExpressionQueryCacheMaxSize());
        for(DatabaseMapping mapping : descriptor.getMappings()) {
            if(mapping.isForeignReferenceMapping()) {
                if(((ForeignReferenceMapping)mapping).getSelectionQuery().isObjectLevelReadQuery()) {
                    olrQuery = (ObjectLevelReadQuery)((ForeignReferenceMapping)mapping).getSelectionQuery();
                    // this un-prePrepares the query, causes executionFetchGroup to be rebuilt
                    if(shouldClear) {
                        olrQuery.setFetchGroupName(null);
                        olrQuery.setShouldUseDefaultFetchGroup(true);
                    } else {
                        olrQuery.setShouldUseDefaultFetchGroup(olrQuery.shouldUseDefaultFetchGroup());
                    }
                    olrQuery.checkPrepare(session, null);
                }
            }
        }
    }

    @Test
    public void testSetup() {
        ServerSession session = getServerSession();
        new AdvancedTableCreator().replaceTables(session);
        //requires another package
        new CompositePKTableCreator().replaceTables(session);

        // Force uppercase for Postgres.
        if (session.getPlatform().isPostgreSQL()) {
            session.getLogin().setShouldForceFieldNamesToUpperCase(true);
        }

        // The EquipmentCode class 'should' be set to read only. We want
        // to be able to create a couple in the Employee populator, so
         // force the read only to false. If EquipmentCode is not
        // actually read only, don't worry, we set the original read
        // only value back on the descriptor and the error will be
        // caught in a later test in this suite.
        ClassDescriptor descriptor = session.getDescriptor(EquipmentCode.class);
        boolean shouldBeReadOnly = descriptor.shouldBeReadOnly();
        descriptor.setShouldBeReadOnly(false);

        // Populate the database with our examples.
        EmployeePopulator employeePopulator = new EmployeePopulator();
        employeePopulator.buildExamples();
        employeePopulator.persistExample(session);

        CompositePKPopulator compositePKPopulator = new CompositePKPopulator();
        compositePKPopulator.buildExamples();
        compositePKPopulator.persistExample(session);

        descriptor.setShouldBeReadOnly(shouldBeReadOnly);

        clearCache();
    }

    public void managerFetchGroup() throws Exception {
        EntityManager em = createEntityManager();

        // Use q query since find will only use default fetch group
        Query query = em.createQuery("SELECT e FROM Employee e WHERE e.id = :ID");
        query.setParameter("ID", minimumEmployeeId(em));

        FetchGroup managerFG = new FetchGroup();
        managerFG.addAttribute("manager");
        query.setHint(QueryHints.FETCH_GROUP, managerFG);

        assertNotNull(getFetchGroup(query));
        assertSame(managerFG, getFetchGroup(query));

        Employee emp = (Employee) query.getSingleResult();

        assertEquals(3, getQuerySQLTracker(em).getTotalSQLSELECTCalls());

        assertFetchedAttribute(emp, "id");
        assertNotFetchedAttribute(emp, "firstName");
        assertFetchedAttribute(emp, "version");
        assertFetchedAttribute(emp, "manager");
        assertFetchedAttribute(emp, "address");
        assertFetchedAttribute(emp, "phoneNumbers");
        assertFetchedAttribute(emp, "projects");

        emp.getManager();
        assertEquals(3, getQuerySQLTracker(em).getTotalSQLSELECTCalls());

        emp.getLastName();

        assertEquals(3, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
    }

    public void employeeNamesFetchGroup() throws Exception {
        EntityManager em = createEntityManager();

        int minId = minimumEmployeeId(em);
        assertEquals(1, getQuerySQLTracker(em).getTotalSQLSELECTCalls());

        // Use q query since find will only use default fetch group
        Query query = em.createQuery("SELECT e FROM Employee e WHERE e.id = :ID");
        query.setParameter("ID", minId);

        FetchGroup namesFG = new FetchGroup();
        namesFG.addAttribute("firstName");
        namesFG.addAttribute("lastName");
        query.setHint(QueryHints.FETCH_GROUP, namesFG);

        assertNotNull(getFetchGroup(query));
        assertSame(namesFG, getFetchGroup(query));

        Employee emp = (Employee) query.getSingleResult();

        assertEquals(2, getQuerySQLTracker(em).getTotalSQLSELECTCalls());

        assertFetchedAttribute(emp, "id");
        assertFetchedAttribute(emp, "firstName");
        assertFetchedAttribute(emp, "lastName");
        assertFetchedAttribute(emp, "gender");
        assertFetchedAttribute(emp, "salary");
        assertFetchedAttribute(emp, "version");
        assertFetchedAttribute(emp, "manager");
        assertFetchedAttribute(emp, "address");
        assertFetchedAttribute(emp, "phoneNumbers");
        assertFetchedAttribute(emp, "projects");

        emp.getId();
        emp.getFirstName();
        emp.getLastName();
        emp.getVersion();

        assertEquals(2, getQuerySQLTracker(em).getTotalSQLSELECTCalls());

        emp.getGender();
        assertEquals(3, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
        assertFetchedAttribute(emp, "gender");
        assertFetchedAttribute(emp, "salary");

        emp.getSalary();

        assertEquals(3, getQuerySQLTracker(em).getTotalSQLSELECTCalls());

        emp.getManager();

        assertEquals(4, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
        assertFetchedAttribute(emp, "manager");
    }

    public void joinFetchEmployeeAddressWithDynamicFetchGroup() {
        EntityManager em = createEntityManager();

        Query query = em.createQuery("SELECT e FROM Employee e JOIN FETCH e.address");

        FetchGroup fetchGroup = new FetchGroup("names");
        fetchGroup.addAttribute("firstName");
        fetchGroup.addAttribute("lastName");
        query.setHint(QueryHints.FETCH_GROUP, fetchGroup);

        List<Employee> emps = query.getResultList();

        assertNotNull(emps);
    }

    public void joinFetchEmployeeAddressPhoneWithDynamicFetchGroup() {
        EntityManager em = createEntityManager();

        Query query = em.createQuery("SELECT e FROM Employee e JOIN FETCH e.address WHERE e.id IN (SELECT p.id FROM PhoneNumber p)");

        FetchGroup fetchGroup = new FetchGroup("names");
        fetchGroup.addAttribute("firstName");
        fetchGroup.addAttribute("lastName");
        query.setHint(QueryHints.FETCH_GROUP, fetchGroup);

        List<Employee> emps = query.getResultList();

        assertNotNull(emps);
    }

    protected Employee findMinimumEmployee(EntityManager em) {
        List<Employee> emps = em.createQuery("SELECT e FROM Employee e WHERE e.id in (SELECT MIN(ee.id) FROM Employee ee)").getResultList();

        assertNotNull("Null returned for min employee query", emps);
        assertEquals("No results returned for Mmin employee query", 1, emps.size());

        return emps.get(0);
    }

    public FetchGroup assertHasFetchGroup(Object entity) {
        assertNotNull("Entity is null", entity);
        assertTrue("Entity does not implement FetchGroupTracker", entity instanceof FetchGroupTracker);
        assertNotNull("Entity does not have FetchGroup", ((FetchGroupTracker) entity)._persistence_getFetchGroup());

        return ((FetchGroupTracker) entity)._persistence_getFetchGroup();
    }

    protected FetchGroup getFetchGroup(Object object) {
        assertNotNull("Cannot get a FetchGroup from null", object);

        if (object instanceof Query) {
            return getFetchGroup((Query) object);
        }
        if (object instanceof ObjectLevelReadQuery) {
            return getExecutionFetchGroup((ObjectLevelReadQuery) object);
        }
        assertTrue("Entity " + object + " does not implement FetchGroupTracker", object instanceof FetchGroupTracker);

        FetchGroupTracker tracker = (FetchGroupTracker) object;
        return tracker._persistence_getFetchGroup();
    }

    protected FetchGroup getFetchGroup(Query query) {
        return getFetchGroup((ObjectLevelReadQuery)JpaHelper.getDatabaseQuery(query));
    }

    protected FetchGroup getFetchGroup(ObjectLevelReadQuery readQuery) {
        return readQuery.getFetchGroup();
    }

    protected FetchGroup getExecutionFetchGroup(Query query) {
        return getExecutionFetchGroup((ObjectLevelReadQuery)JpaHelper.getDatabaseQuery(query));
    }

    protected FetchGroup getExecutionFetchGroup(ObjectLevelReadQuery readQuery) {
        return readQuery.getExecutionFetchGroup();
    }

    public void assertFetchedAttribute(Object entity, String... attribute) {
        FetchGroupAssert.assertFetchedAttribute(getEntityManagerFactory(), entity, attribute);
    }

    public void assertNotFetchedAttribute(Object entity, String... attribute) {
        FetchGroupAssert.assertNotFetchedAttribute(getEntityManagerFactory(), entity, attribute);
    }

    public void assertFetched(Object entity, FetchGroup fetchGroup) {
        FetchGroupAssert.assertFetched(getEntityManagerFactory(), entity, fetchGroup);
    }

    public void assertDefaultFetched(Object entity) {
        FetchGroupAssert.assertDefaultFetched(getEntityManagerFactory(), entity);
    }

    public void assertFetched(Object entity, String fetchGroupName) {
        FetchGroupAssert.assertFetched(getEntityManagerFactory(), entity, fetchGroupName);
    }

    public void assertNoFetchGroup(Object entity) {
        FetchGroupAssert.assertNoFetchGroup(getEntityManagerFactory(), entity);
    }

    public void assertConfig(String entityName, FetchGroup defaultFetchGroup) {
        FetchGroupAssert.assertConfig(getEntityManagerFactory(), entityName, defaultFetchGroup);
    }

    public void assertConfig(String entityName, FetchGroup defaultFetchGroup, int numNamedFetchGroups) {
        FetchGroupAssert.assertConfig(getEntityManagerFactory(), entityName, defaultFetchGroup, numNamedFetchGroups);
    }

    public void assertConfig(ClassDescriptor descriptor, FetchGroup defaultFetchGroup) {
        FetchGroupAssert.assertConfig(descriptor, defaultFetchGroup);
    }

    public void assertConfig(ClassDescriptor descriptor, FetchGroup defaultFetchGroup, int numNamedFetchGroups) {
        FetchGroupAssert.assertConfig(descriptor, defaultFetchGroup, numNamedFetchGroups);
    }

    protected QuerySQLTracker getQuerySQLTracker(EntityManager em) {
        return QuerySQLTracker.getTracker(getServerSession());
    }

    ClassDescriptor getDescriptor(String entityName) {
        return getServerSession().getClassDescriptorForAlias(entityName);
    }

    public static int minimumEmployeeId(EntityManager em) {
        return ((Number) em.createQuery("SELECT MIN(e.id) FROM Employee e").getSingleResult()).intValue();
    }

    public static int minimumEmployeeWithoutDepartmentId(EntityManager em) {
        return ((Number) em.createQuery("SELECT MIN(e.id) FROM Employee e WHERE e.department IS NULL").getSingleResult()).intValue();
    }

    public static Employee minimumEmployee(EntityManager em) {
        Query q = em.createQuery("SELECT e FROM Employee e WHERE e.id in (SELECT MIN(ee.id) FROM Employee ee)");

        return (Employee) q.getSingleResult();
    }

    public static Employee minimumEmployee(EntityManager em, Map<String, Object> hints) {
        Query q = em.createQuery("SELECT e FROM Employee e WHERE e.id in (SELECT MIN(ee.id) FROM Employee ee)");
        Iterator<Map.Entry<String, Object>> it = hints.entrySet().iterator();
        while(it.hasNext()) {
            Map.Entry<String, Object> entry = it.next();
            q.setHint(entry.getKey(), entry.getValue());
        }

        return (Employee) q.getSingleResult();
    }

    public static Employee minEmployeeWithAddressAndPhones(EntityManager em) {
        return (Employee) em.createQuery("SELECT e FROM Employee e JOIN FETCH e.address WHERE e.id IN (SELECT MIN(p.id) FROM PhoneNumber p)").getSingleResult();
    }

    public Employee minEmployeeWithManagerWithAddress(EntityManager em) {
        List<Employee> emps = em.createQuery("SELECT e FROM Employee e JOIN FETCH e.manager WHERE e.manager.address IS NOT NULL ORDER BY e.id").getResultList();
        return emps.get(0);
    }

    public static int minEmployeeIdWithAddressAndPhones(EntityManager em) {
        return ((Number) em.createQuery("SELECT e.id FROM Employee e JOIN FETCH e.address WHERE e.id IN (SELECT MIN(p.id) FROM PhoneNumber p)").getSingleResult()).intValue();
    }

    public static class PhoneCustomizer implements DescriptorCustomizer {

        @Override
        public void customize(ClassDescriptor descriptor) throws Exception {
            defaultPhoneFG = new FetchGroup("PhoneNumber.default");
            defaultPhoneFG.addAttribute("number");
            descriptor.getFetchGroupManager().setDefaultFetchGroup(defaultPhoneFG);
        }
    }
}
