/*
 * 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
//     09/21/2010-2.2 Frank Schwarz and ailitchev - Bug 325684 - QueryHints.BATCH combined with QueryHints.FETCH_GROUP_LOAD will cause NPE
package org.eclipse.persistence.testing.tests.jpa.fetchgroups;

import java.util.Collection;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

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

import junit.framework.TestSuite;

import org.eclipse.persistence.config.QueryHints;
import org.eclipse.persistence.internal.helper.IdentityHashSet;
import org.eclipse.persistence.internal.jpa.EntityManagerImpl;
import org.eclipse.persistence.internal.queries.EntityFetchGroup;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.jpa.JpaHelper;
import org.eclipse.persistence.queries.AttributeGroup;
import org.eclipse.persistence.queries.FetchGroup;
import org.eclipse.persistence.queries.FetchGroupTracker;
import org.eclipse.persistence.queries.LoadGroup;
import org.eclipse.persistence.testing.models.jpa.advanced.Address;
import org.eclipse.persistence.testing.models.jpa.advanced.Department;
import org.eclipse.persistence.testing.models.jpa.advanced.Employee;
import org.eclipse.persistence.testing.models.jpa.advanced.PhoneNumber;
import org.eclipse.persistence.testing.models.jpa.advanced.Project;
import org.eclipse.persistence.testing.models.jpa.advanced.Employee.Gender;
import org.eclipse.persistence.testing.models.jpa.advanced.compositepk.Competency;

import org.junit.Test;

/**
 * @author dclarke
 * @since EclipseLink 2.1
 */
public class NestedFetchGroupTests extends BaseFetchGroupTests {

    public NestedFetchGroupTests() {
        super();
    }

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

    public static junit.framework.Test suite() {
        TestSuite suite = new TestSuite();
        suite.setName("NestedFetchGroupTests");

        suite.addTest(new NestedFetchGroupTests("testSetup"));
        suite.addTest(new NestedFetchGroupTests("dynamicFetchGroup_EmployeeAddress"));
        suite.addTest(new NestedFetchGroupTests("dynamicFetchGroup_Employee_NullAddress"));
        suite.addTest(new NestedFetchGroupTests("dynamicFetchGroup_EmployeeAddressNullPhone"));
        suite.addTest(new NestedFetchGroupTests("dynamicFetchGroup_EmployeeAddressEmptyPhone"));
        suite.addTest(new NestedFetchGroupTests("dynamicFetchGroup_EmployeeAddressEmptyPhoneLoad"));
        suite.addTest(new NestedFetchGroupTests("dynamicHierarchicalFetchGroup"));
        suite.addTest(new NestedFetchGroupTests("dynamicFetchGroup_ElementCollection"));
//**temp        suite.addTest(new NestedFetchGroupTests("dynamicHierarchicalFetchGroup_JOIN_FETCH"));
        suite.addTest(new NestedFetchGroupTests("dynamicHierarchicalFetchGroup_JOIN_FETCH_Copy"));
//**temp        suite.addTest(new NestedFetchGroupTests("managerDoubleNestedFetchGroupWithJoinFetch"));
        suite.addTest(new NestedFetchGroupTests("managerTripleNestedFetchGroupWithJoinFetch"));
        suite.addTest(new NestedFetchGroupTests("allNestedFetchGroupWithJoinFetch"));
        suite.addTest(new NestedFetchGroupTests("joinFetchDefaultFetchGroup"));
        suite.addTest(new NestedFetchGroupTests("joinFetchOutsideOfFetchGroup"));
        suite.addTest(new NestedFetchGroupTests("simpleNestedFetchGroupWithBatch"));
        suite.addTest(new NestedFetchGroupTests("simpleLoadGroup"));
        suite.addTest(new NestedFetchGroupTests("simpleFetchGroupLoadWithBatch"));

        return suite;
    }

    @Override
    public void setUp() {
        super.setUp();

        defaultPhoneFG = new FetchGroup();
        defaultPhoneFG.addAttribute("number");
        phoneDescriptor.getFetchGroupManager().setDefaultFetchGroup(defaultPhoneFG);

        reprepareReadQueries(phoneDescriptor);
        reprepareReadQueries(employeeDescriptor);

        // We'll put a default FetchGroup on Phone
        assertNotNull(phoneDescriptor.getDefaultFetchGroup());
        assertNotNull(phoneDescriptor.getDescriptorQueryManager().getReadObjectQuery().getExecutionFetchGroup());
        assertTrue(phoneDescriptor.getFetchGroupManager().getFetchGroups().isEmpty());
    }

    @Test
    public void dynamicFetchGroup_EmployeeAddress() throws Exception {
        EntityManager em = createEntityManager();
        try {
            beginTransaction(em);

            Query query = em.createQuery("SELECT e FROM Employee e WHERE e.gender = :GENDER");
            query.setParameter("GENDER", Gender.Male);

            // Define the fields to be fetched on Employee
            FetchGroup fg = new FetchGroup();
            fg.addAttribute("id");
            fg.addAttribute("version");
            fg.addAttribute("firstName");
            fg.addAttribute("lastName");
            fg.addAttribute("address.city");
            fg.addAttribute("address.postalCode");

            // Configure the dynamic FetchGroup
            query.setHint(QueryHints.FETCH_GROUP, fg);

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

            assertNotNull(emps);
            for (Employee emp : emps) {
                FetchGroupTracker tracker = (FetchGroupTracker) emp;

                assertNotNull(tracker._persistence_getFetchGroup());

                // Verify specified fields plus mandatory ones are loaded
                assertTrue(tracker._persistence_isAttributeFetched("firstName"));
                assertTrue(tracker._persistence_isAttributeFetched("lastName"));
                assertTrue(tracker._persistence_isAttributeFetched("address"));
                FetchGroupTracker addrTracker = (FetchGroupTracker) emp.getAddress();
                assertTrue(addrTracker._persistence_isAttributeFetched("city"));
                assertTrue(addrTracker._persistence_isAttributeFetched("postalCode"));
                assertFalse(addrTracker._persistence_isAttributeFetched("street"));

                // Verify the other fields are not loaded
                assertFalse(tracker._persistence_isAttributeFetched("salary"));
                assertFalse(tracker._persistence_isAttributeFetched("startTime"));
                assertFalse(tracker._persistence_isAttributeFetched("endTime"));

                // Force the loading of lazy fields and verify
                emp.getSalary();

                assertTrue(tracker._persistence_isAttributeFetched("firstName"));
                assertTrue(tracker._persistence_isAttributeFetched("lastName"));
                assertTrue(tracker._persistence_isAttributeFetched("address"));
                assertTrue(tracker._persistence_isAttributeFetched("salary"));
                assertTrue(tracker._persistence_isAttributeFetched("startTime"));
                assertTrue(tracker._persistence_isAttributeFetched("endTime"));

                // Now we'll check the address uses the provided dynamic fetch-group
                addrTracker = (FetchGroupTracker) emp.getAddress();
                assertNotNull("Address does not have a FetchGroup", addrTracker._persistence_getFetchGroup());
                assertTrue(addrTracker._persistence_isAttributeFetched("city"));
                assertTrue(addrTracker._persistence_isAttributeFetched("postalCode"));
                assertFalse(addrTracker._persistence_isAttributeFetched("street"));
                assertFalse(addrTracker._persistence_isAttributeFetched("country"));

                // Now we'll check the phoneNumbers use of the default fetch group
                for (PhoneNumber phone : emp.getPhoneNumbers()) {
                    FetchGroupTracker phoneTracker = (FetchGroupTracker) phone;
                    assertNotNull("PhoneNumber does not have a FetchGroup", phoneTracker._persistence_getFetchGroup());
                    assertTrue(phoneTracker._persistence_isAttributeFetched("number"));
                    assertFalse(phoneTracker._persistence_isAttributeFetched("areaCode"));
                }
            }
        } finally {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
        }
    }

    @Test
    public void dynamicFetchGroup_Employee_NullAddress() throws Exception {
        EntityManager em = createEntityManager();
        try {
            beginTransaction(em);

            Query query = em.createQuery("SELECT e FROM Employee e WHERE e.gender = :GENDER");
            query.setParameter("GENDER", Gender.Male);

            // Define the fields to be fetched on Employee
            FetchGroup empGroup = new FetchGroup();
            empGroup.addAttribute("firstName");
            empGroup.addAttribute("lastName");
            empGroup.addAttribute("address");

            // Define the fields to be fetched on Address
            FetchGroup addressGroup = new FetchGroup();
            addressGroup.addAttribute("city");
            addressGroup.addAttribute("postalCode");

            empGroup.addAttribute("address");

            // Configure the dynamic FetchGroup
            query.setHint(QueryHints.FETCH_GROUP, empGroup);

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

            assertNotNull(emps);
            for (Employee emp : emps) {
                FetchGroupTracker tracker = (FetchGroupTracker) emp;

                assertNotNull(tracker._persistence_getFetchGroup());

                // Verify specified fields plus mandatory ones are loaded
                assertTrue(tracker._persistence_isAttributeFetched("id"));
                assertTrue(tracker._persistence_isAttributeFetched("firstName"));
                assertTrue(tracker._persistence_isAttributeFetched("lastName"));
                assertTrue(tracker._persistence_isAttributeFetched("version"));

                // Verify the other fields are not loaded
                assertFalse(tracker._persistence_isAttributeFetched("salary"));
                assertFalse(tracker._persistence_isAttributeFetched("startTime"));
                assertFalse(tracker._persistence_isAttributeFetched("endTime"));

                // Force the loading of lazy fields and verify
                emp.getSalary();

                assertTrue(tracker._persistence_isAttributeFetched("salary"));
                assertTrue(tracker._persistence_isAttributeFetched("startTime"));
                assertTrue(tracker._persistence_isAttributeFetched("endTime"));

                // Now we'll check the address uses the provided dynamic fetch-group
                FetchGroupTracker addrTracker = (FetchGroupTracker) emp.getAddress();
                assertNull("Address has an unexpected FetchGroup", addrTracker._persistence_getFetchGroup());

                // Now we'll check the phoneNumbers use of the default fetch group
                for (PhoneNumber phone : emp.getPhoneNumbers()) {
                    FetchGroupTracker phoneTracker = (FetchGroupTracker) phone;
                    assertNotNull("PhoneNumber does not have a FetchGroup", phoneTracker._persistence_getFetchGroup());
                    assertTrue(phoneTracker._persistence_isAttributeFetched("number"));
                    assertFalse(phoneTracker._persistence_isAttributeFetched("areaCode"));
                }
            }
        } finally {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
        }
    }

    @Test
    public void dynamicFetchGroup_EmployeeAddressNullPhone() throws Exception {
        EntityManager em = createEntityManager();
        try {
            beginTransaction(em);

            Query query = em.createQuery("SELECT e FROM Employee e WHERE e.gender = :GENDER");
            query.setParameter("GENDER", Gender.Male);

            // Define the fields to be fetched on Employee
            FetchGroup empGroup = new FetchGroup();
            empGroup.addAttribute("firstName");
            empGroup.addAttribute("lastName");
            empGroup.addAttribute("address");
            empGroup.addAttribute("address.city");
            empGroup.addAttribute("address.postalCode");

            //empGroup.addAttribute("phoneNumbers").setUseDefaultFetchGroup(false);
            FetchGroup fullPhone = this.phoneDescriptor.getFetchGroupManager().createFullFetchGroup();
            // to preclude Employee from being loaded by phoneNumber.owner add it to the fetch group
            fullPhone.addAttribute("owner.id");
            empGroup.addAttribute("phoneNumbers", fullPhone);

            // Configure the dynamic FetchGroup
            query.setHint(QueryHints.FETCH_GROUP, empGroup);

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

            assertNotNull(emps);
            for (Employee emp : emps) {
                FetchGroupTracker tracker = (FetchGroupTracker) emp;

                assertNotNull(tracker._persistence_getFetchGroup());

                // Verify specified fields plus mandatory ones are loaded
                assertTrue(tracker._persistence_isAttributeFetched("id"));
                assertTrue(tracker._persistence_isAttributeFetched("firstName"));
                assertTrue(tracker._persistence_isAttributeFetched("lastName"));
                assertTrue(tracker._persistence_isAttributeFetched("version"));

                // Verify the other fields are not loaded
                assertFalse(tracker._persistence_isAttributeFetched("salary"));
                assertFalse(tracker._persistence_isAttributeFetched("startTime"));
                assertFalse(tracker._persistence_isAttributeFetched("endTime"));

                // Force the loading of lazy fields and verify
                emp.getSalary();

                assertTrue(tracker._persistence_isAttributeFetched("salary"));
                assertTrue(tracker._persistence_isAttributeFetched("startTime"));
                assertTrue(tracker._persistence_isAttributeFetched("endTime"));

                // Now we'll check the address uses the provided dynamic fetch-group
                FetchGroupTracker addrTracker = (FetchGroupTracker) emp.getAddress();
                assertNotNull("Address does not have a FetchGroup", addrTracker._persistence_getFetchGroup());
                assertTrue(addrTracker._persistence_isAttributeFetched("city"));
                assertTrue(addrTracker._persistence_isAttributeFetched("postalCode"));
                assertFalse(addrTracker._persistence_isAttributeFetched("street"));
                assertFalse(addrTracker._persistence_isAttributeFetched("country"));

                // Now we'll check the phoneNumbers use of the default fetch group
                for (PhoneNumber phone : emp.getPhoneNumbers()) {
                    FetchGroupTracker phoneTracker = (FetchGroupTracker) phone;
                    assertNull("PhoneNumber has a FetchGroup", phoneTracker._persistence_getFetchGroup());
                }
            }
        } finally {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
        }
    }

    @Test
    public void dynamicFetchGroup_ElementCollection(){
        EntityManager em = createEntityManager();
        AttributeGroup compt = new AttributeGroup(null, Competency.class, true);
        compt.addAttribute("description");
        AttributeGroup fg = new AttributeGroup(null, org.eclipse.persistence.testing.models.jpa.advanced.compositepk.Department.class, true);
        fg.addAttribute("competencies", compt);
        clearCache();
        Collection<org.eclipse.persistence.testing.models.jpa.advanced.compositepk.Department> results = em.createQuery("select d from Department d").setHint(QueryHints.FETCH_GROUP, fg.toFetchGroup()).getResultList();
        for (org.eclipse.persistence.testing.models.jpa.advanced.compositepk.Department dept : results){
            assertFalse("Collection fetched: scientists, fg ignored", ((FetchGroupTracker)dept)._persistence_isAttributeFetched("scientists"));
            assertFalse("Collection fetched: offices, fg ignored", ((FetchGroupTracker)dept)._persistence_isAttributeFetched("offices"));
            assertTrue("Collection not fetched: competencies, fg ignored", ((FetchGroupTracker)dept)._persistence_isAttributeFetched("competencies"));
            for (Competency embeded: dept.getCompetencies()){
                assertTrue("Element attribute not loaded: description, fg ignored", ((FetchGroupTracker)embeded)._persistence_isAttributeFetched("description"));
            }
            dept.getScientists().size();
            assertTrue("Collection not fetched: scientists, fg ignored", ((FetchGroupTracker)dept)._persistence_isAttributeFetched("scientists"));
            assertTrue("Collection not fetched: offices, fg ignored", ((FetchGroupTracker)dept)._persistence_isAttributeFetched("offices"));
            assertTrue("Collection not fetched: competencies, fg ignored", ((FetchGroupTracker)dept)._persistence_isAttributeFetched("competencies"));
            for (Competency embeded: dept.getCompetencies()){
                embeded.getRating();
                assertTrue("Element attribute not loaded: description, fg ignored", ((FetchGroupTracker)embeded)._persistence_isAttributeFetched("description"));
            }
        }
    }

    @Test
    public void dynamicFetchGroup_EmployeeAddressEmptyPhone() {

    }
    public void dynamicFetchGroup_EmployeeAddressEmptyPhoneLoad() {

    }
    void internal_dynamicFetchGroup_EmployeeAddressEmptyPhone(boolean shouldLoad) {
        EntityManager em = createEntityManager();
        try {
            beginTransaction(em);

            Query query = em.createQuery("SELECT e FROM Employee e WHERE e.gender = :GENDER");
            query.setParameter("GENDER", Gender.Male);

            // Define the fields to be fetched on Employee
            FetchGroup fg = new FetchGroup();
            fg.addAttribute("firstName");
            fg.addAttribute("lastName");
            fg.addAttribute("address.city");
            fg.addAttribute("address.postalCode");
            // to preclude Employee from being loaded by phoneNumber.owner add it to the fetch group
            FetchGroup ownerId = new FetchGroup();
            ownerId.addAttribute("owner.id");
            fg.addAttribute("phoneNumbers", ownerId);

            if(shouldLoad) {
                fg.setShouldLoad(true);
            }

            // Configure the dynamic FetchGroup
            query.setHint(QueryHints.FETCH_GROUP, fg);

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

            assertNotNull(emps);
            assertEquals(1 + (shouldLoad ? 0 : (emps.size() * 2)), getQuerySQLTracker(em).getTotalSQLSELECTCalls());

            for (Employee emp : emps) {
                FetchGroupTracker tracker = (FetchGroupTracker) emp;

                assertNotNull(tracker._persistence_getFetchGroup());

                // Verify specified fields plus mandatory ones are loaded
                assertTrue(tracker._persistence_isAttributeFetched("id"));
                assertTrue(tracker._persistence_isAttributeFetched("firstName"));
                assertTrue(tracker._persistence_isAttributeFetched("lastName"));
                assertTrue(tracker._persistence_isAttributeFetched("version"));

                // Verify the other fields are not loaded
                assertFalse(tracker._persistence_isAttributeFetched("salary"));
                assertFalse(tracker._persistence_isAttributeFetched("startTime"));
                assertFalse(tracker._persistence_isAttributeFetched("endTime"));

                // Force the loading of lazy fields and verify
                emp.getSalary();

                assertTrue(tracker._persistence_isAttributeFetched("salary"));
                assertTrue(tracker._persistence_isAttributeFetched("startTime"));
                assertTrue(tracker._persistence_isAttributeFetched("endTime"));

                // Now we'll check the address uses the provided dynamic fetch-group
                FetchGroupTracker addrTracker = (FetchGroupTracker) emp.getAddress();
                assertNotNull("Address does not have a FetchGroup", addrTracker._persistence_getFetchGroup());
                assertTrue(addrTracker._persistence_isAttributeFetched("city"));
                assertTrue(addrTracker._persistence_isAttributeFetched("postalCode"));
                assertFalse(addrTracker._persistence_isAttributeFetched("street"));
                assertFalse(addrTracker._persistence_isAttributeFetched("country"));

                // Now we'll check the phoneNumbers use of the default fetch group
                for (PhoneNumber phone : emp.getPhoneNumbers()) {
                    FetchGroupTracker phoneTracker = (FetchGroupTracker) phone;
                    assertNotNull("PhoneNumber does not have a FetchGroup", phoneTracker._persistence_getFetchGroup());
                    assertFalse(phoneTracker._persistence_isAttributeFetched("number"));
                    assertFalse(phoneTracker._persistence_isAttributeFetched("areaCode"));

                    phone.getNumber();

                    assertTrue(phoneTracker._persistence_isAttributeFetched("number"));
                    assertTrue(phoneTracker._persistence_isAttributeFetched("areaCode"));
                }
            }
        } finally {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
        }
    }

    @Test
    public void dynamicHierarchicalFetchGroup() throws Exception {

        EntityManager em = createEntityManager();

        Query query = em.createQuery("SELECT e FROM Employee e WHERE e.lastName LIKE :LNAME AND e.manager.lastName <> e.lastName");
        query.setParameter("LNAME", "%");

        // Define the fields to be fetched on Employee
        FetchGroup fg = new FetchGroup();
        fg.addAttribute("firstName");
        fg.addAttribute("lastName");
        fg.addAttribute("salary");
        fg.addAttribute("gender");
        fg.addAttribute("manager.firstName");
        fg.addAttribute("manager.lastName");
        fg.addAttribute("manager.salary");
        fg.addAttribute("manager.gender");
        fg.addAttribute("manager.manager.firstName");
        fg.addAttribute("manager.manager.lastName");
        fg.addAttribute("manager.manager.salary");
        fg.addAttribute("manager.manager.gender");
        query.setHint(QueryHints.FETCH_GROUP, fg);

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

        int numSelect = getQuerySQLTracker(em).getTotalSQLSELECTCalls();

        for (Employee emp : emps) {
            assertFetched(emp, fg);
        }
        assertEquals(numSelect, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
    }

    @Test
    public void dynamicHierarchicalFetchGroup_JOIN_FETCH() throws Exception {
        internalDynamicHierarchicalFetchGroup_JOIN_FETCH(false);
    }

    @Test
    public void dynamicHierarchicalFetchGroup_JOIN_FETCH_Copy() throws Exception {
        internalDynamicHierarchicalFetchGroup_JOIN_FETCH(true);
    }

    void internalDynamicHierarchicalFetchGroup_JOIN_FETCH(boolean useCopy) throws Exception {

        EntityManager em = createEntityManager();
        try {
            beginTransaction(em);

            Query query = em.createQuery("SELECT e FROM Employee e JOIN FETCH e.manager WHERE e.lastName LIKE :LNAME AND e.manager.lastName <> e.lastName");
            query.setParameter("LNAME", "%");

            // Define the fields to be fetched on Employee
            FetchGroup fg = new FetchGroup();
            fg.addAttribute("firstName");
            fg.addAttribute("lastName");
            fg.addAttribute("manager.firstName");
            fg.addAttribute("manager.salary");
            fg.addAttribute("manager.manager");
            query.setHint(QueryHints.FETCH_GROUP, fg);

            // applied to the selected Employee who is not a manager of some other selected Employee
            FetchGroup employeeFG = new EntityFetchGroup(new String[]{"id", "version", "firstName", "lastName", "manager"});
            // applied to the manager of a selected Employee who is not selected as an Employee
            FetchGroup managerFG = new EntityFetchGroup(new String[]{"id", "version", "firstName", "salary", "manager"});
            // applied to the object which is both selected as an Employee and the manager of another selected Employee
            FetchGroup employeeManagerFG = employeeDescriptor.getFetchGroupManager().flatUnionFetchGroups(employeeFG, managerFG, false);

            // used in useCopy case only
            FetchGroup employeeManagerManagerFG = null;
            if(useCopy) {
                employeeManagerManagerFG = employeeDescriptor.getFetchGroupManager().flatUnionFetchGroups(new EntityFetchGroup("manager"), employeeDescriptor.getFetchGroupManager().getNonReferenceEntityFetchGroup(), false);
            }

            /*
             * These are the first names of Employees involved; --> means "managed by".
             * All the employees here are returned by the query except Jill and Sarah-loo (they got no manager).
             *
             * Sarah ------>Bob -------> John ----> Jim-bob ---> Jill ---> null
             * Charles -----^   Marius ----^
             *
             * Nancy ------> Sarah-loo ---> null
             *
             * Sarah, Charles, Nancy should have employeeFG;
             * Sarah-loo - managerFG;
             * Bob, Marius - employeeManagerFG;
             * John, Jim-bob should have a union of three fetch groups: {firstName,lastName,manager}, {firstName,salary,manager}, {manager}
             * Jill should have a union of two groups:  {firstName,salary,manager}, {manager}
             * The result for all three of them is the same:
             *   in read case (useCopy == false) it should be null (no fetch group), because defaultFetchGroup is null;
             *   in copy case (useCopy == true) it should be a union of "manager" and all non relational attributes (NonReferenceEntityFetchGroup).
             * That's how leaf reference attribute is treated:
             *   default fetch group for read;
             *   NonReferenceEntityFetchGroup (see FetchGroupManager) for copy.
             * In this test defaultFetchGroup (null) / NonReferenceEntityFetchGroup comes from {manager},
             *   in useCopy == true case additional manager comes from another fetch group (they all contain manager).
             */

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

            if(useCopy) {
                /*for(Employee emp : emps) {
                    int idHashCode =  System.identityHashCode(emp);
                    System.out.println(emp.getFirstName() + '\t' + idHashCode);
                }*/
                emps = (List)JpaHelper.getEntityManager(em).copy(emps, fg);
            }

            // Sets of managed Employees keyed by their manager
            Map<Employee, Set<Employee>> managedEmployeesByManager = new IdentityHashMap();
            for (Employee emp : emps) {
                Employee manager = emp.getManager();
                Set<Employee> managedEmployees = managedEmployeesByManager.get(manager);
                if(managedEmployees == null) {
                    managedEmployees = new IdentityHashSet();
                    managedEmployeesByManager.put(manager, managedEmployees);
                }
                managedEmployees.add(emp);
            }

            for (Employee emp : emps) {
                Set<Employee> managedEmployees = managedEmployeesByManager.get(emp);
                Employee manager = emp.getManager();
                if(managedEmployees == null) {
                    // employee is NOT a manager of any of the selected employees:
                    assertFetched(emp, employeeFG);

                    Set<Employee> managedByManagerEmployees = managedEmployeesByManager.get(manager);
                    // indicates whether one of manager's managed employees is a manager itself
                    boolean isManagersManager = false;
                    for(Employee managedEmp : managedByManagerEmployees) {
                        if(managedEmployeesByManager.containsKey(managedEmp)) {
                            isManagersManager = true;
                            break;
                        }
                    }
                    if(isManagersManager) {
                        if(useCopy) {
                            // for at least one of the selected employees manager is manager's manager:
                            //   someSelectedEmp.getManager().getManager() == manager
                            // That means for someSelectedEmp emp is defined by {manager.manager} FetchGroup's item,
                            // which means NonReferenceEntityFetchGroup (only non-reference attributes + pk)
                            // for another employee it's just a manager - which means it should include "manager":
                            // employeeManagerManagerFG is the union of these two EntityFetchGroups.
                            assertFetched(manager, employeeManagerManagerFG);
                        } else {
                            // for at least one of the selected employees manager is manager's manager:
                            //   someSelectedEmp.getManager().getManager() == manager
                            // That means for someSelectedEmp emp is defined by {manager.manager} FetchGroup's item,
                            // which means no fetch group should be used.
                            assertNoFetchGroup(manager);
                        }
                    } else {
                        // it's not manager's manager
                        if(emps.contains(manager)) {
                            // it's a manager of one of the selected Employees, and selected itself.
                            assertFetched(manager, employeeManagerFG);
                        } else {
                            // it's a manager of one of the selected Employees, but not selected itself.
                            assertFetched(manager, managerFG);
                        }
                    }
                } else {
                    // employee is a manager of at least one of the selected employees
                    // indicates whether one of emp's managed employees is a manager itself
                    boolean isManagersManager = false;
                    for(Employee managedEmp : managedEmployees) {
                        if(managedEmployeesByManager.containsKey(managedEmp)) {
                            isManagersManager = true;
                            break;
                        }
                    }

                    if(isManagersManager) {
                        if(useCopy) {
                            // for at least one of the selected employees manager is manager's manager:
                            //   someSelectedEmp.getManager().getManager() == manager
                            // That means for someSelectedEmp emp is defined by {manager.manager} FetchGroup's item,
                            // which means NonReferenceEntityFetchGroup (only non-reference attributes + pk)
                            // for another employee it's just a manager - which means it should include "manager":
                            // employeeManagerManagerFG is the union of these two EntityFetchGroups.
                            assertFetched(emp, employeeManagerManagerFG);
                        } else {
                            // for at least one of the selected employees emp is manager's manager:
                            //   someSelectedEmp.getManager().getManager() == emp
                            // That means for someSelectedEmp emp is defined by {manager.manager} FetchGroup's item,
                            // which means no fetch group should be used.
                            assertNoFetchGroup(emp);
                        }
                    } else {
                        // it's selected employee, manager of some selected employee, but not manager's manager
                        assertFetched(emp, employeeManagerFG);
                    }

                    if(useCopy) {
                        // for at least one of the selected employees manager is manager's manager:
                        //   someSelectedEmp.getManager().getManager() == manager
                        // That means for someSelectedEmp emp is defined by {manager.manager} FetchGroup's item,
                        // which means NonReferenceEntityFetchGroup (only non-reference attributes + pk)
                        // for another employee it's just a manager - which means it should include "manager":
                        // employeeManagerManagerFG is the union of these two EntityFetchGroups.
                        assertFetched(manager, employeeManagerManagerFG);
                    } else {
                        // for at least one of the selected employees manager is manager's manager:
                        //   someSelectedEmp.getManager().getManager() == manager
                        // That means for someSelectedEmp emp.getManager() is defined by {manager.manager} FetchGroup's item,
                        // which means no fetch group should be used.
                        assertNoFetchGroup(manager);
                    }
                }
            }
        } finally {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
        }
    }

   @Test
   public void managerDoubleNestedFetchGroupWithJoinFetch() {
       managerNestedFetchGroupWithJoinFetch(true);
   }

   @Test
   public void managerTripleNestedFetchGroupWithJoinFetch() {
       managerNestedFetchGroupWithJoinFetch(false);
   }

   void managerNestedFetchGroupWithJoinFetch(boolean isDouble) {
        EntityManager em = createEntityManager();
        try {
            beginTransaction(em);

            Query query = em.createQuery("SELECT e FROM Employee e WHERE e.manager.manager IS NOT NULL");
            FetchGroup managerFG = new FetchGroup();
            if(isDouble) {
                // Double
                managerFG.addAttribute("manager.manager");
            } else {
                // Triple
                managerFG.addAttribute("manager.manager.manager");
            }

            query.setHint(QueryHints.FETCH_GROUP, managerFG);
            query.setHint(QueryHints.LEFT_FETCH, "e.manager");

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

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

            int nSql;
            if(isDouble) {
                // In this case the number of generated sqls is unpredictable.
                // Additional sql generated for every object that
                // has been first fetched as manager.manager
                // and then is selected as an employee - getting its manger
                // performed without fetch group therefore triggering reading of the whole object
                nSql = getQuerySQLTracker(em).getTotalSQLSELECTCalls();
            } else {
                assertEquals(1, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
                nSql = 1;
            }

            Employee emp = employees.get(0);
            assertFetched(emp, managerFG);

            // manager (if not null) is instantiated by the fetch group, before emp.getManager call.
            Employee manager = emp.getManager();
            assertEquals(nSql, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
            assertFetched(manager, managerFG);

            // instantiates the whole object
            emp.getLastName();
            nSql++;
            assertNoFetchGroup(emp);
            assertEquals(nSql, getQuerySQLTracker(em).getTotalSQLSELECTCalls());

            assertFetched(manager, managerFG);
            // instantiates the whole object
            manager.getLastName();
            nSql++;
            assertNoFetchGroup(manager);
            assertEquals(nSql, getQuerySQLTracker(em).getTotalSQLSELECTCalls());

            nSql++;
            for (PhoneNumber phone : emp.getPhoneNumbers()) {
                assertFetched(phone, defaultPhoneFG);
                phone.getAreaCode();
                nSql++;
                assertNoFetchGroup(phone);
            }
            assertEquals(nSql, getQuerySQLTracker(em).getTotalSQLSELECTCalls());

            nSql++;
            for (PhoneNumber phone : manager.getPhoneNumbers()) {
                assertFetched(phone, defaultPhoneFG);
                phone.getAreaCode();
                nSql++;
                assertNoFetchGroup(phone);
            }
            assertEquals(nSql, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
        } finally {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
        }
    }

   @Test
   public void allNestedFetchGroupWithJoinFetch() {
        EntityManager em = createEntityManager();
        try {
            beginTransaction(em);

            // select employees who are neither managers nor team leaders
            Query query = em.createQuery("SELECT e FROM Employee e WHERE NOT EXISTS(SELECT p.id FROM Project p WHERE p.teamLeader = e) AND NOT EXISTS(SELECT e2.id FROM Employee e2 WHERE e2.manager = e)");
            FetchGroup employeeFG = new FetchGroup("employee");
            employeeFG.addAttribute("lastName");

            employeeFG.addAttribute("address.country");
            employeeFG.addAttribute("address.city");
            query.setHint(QueryHints.LEFT_FETCH, "e.address");

            employeeFG.addAttribute("phoneNumbers");
            query.setHint(QueryHints.LEFT_FETCH, "e.phoneNumbers");

            employeeFG.addAttribute("projects.name");

            employeeFG.addAttribute("projects.teamLeader.firstName");
            //employeeFG.addAttribute("projects.teamLeader.address.street");
            //employeeFG.addAttribute("projects.teamLeader.address.postalCode");
            employeeFG.addAttribute("projects.teamLeader.phoneNumbers.owner");
            employeeFG.addAttribute("projects.teamLeader.phoneNumbers.type");
            employeeFG.addAttribute("projects.teamLeader.phoneNumbers.areaCode");
            query.setHint(QueryHints.LEFT_FETCH, "e.projects.teamLeader.phoneNumbers");

            employeeFG.addAttribute("manager.firstName");
            //employeeFG.addAttribute("manager.address.street");
            //employeeFG.addAttribute("manager.address.postalCode");
            employeeFG.addAttribute("manager.phoneNumbers.owner");
            employeeFG.addAttribute("manager.phoneNumbers.type");
            employeeFG.addAttribute("manager.phoneNumbers.areaCode");
            query.setHint(QueryHints.LEFT_FETCH, "e.manager.phoneNumbers");

            // department attribute defined with JoinFetchType.OUTER
            employeeFG.addAttribute("department.name");

            query.setHint(QueryHints.FETCH_GROUP, employeeFG);

            List<Employee> employees = query.getResultList();
            assertEquals(1, getQuerySQLTracker(em).getTotalSQLSELECTCalls());

            for(Employee emp :employees) {
                assertFetched(emp, employeeFG);

                Address address = emp.getAddress();
                if(address != null) {
                    assertFetched(address, employeeFG.getGroup("address"));
                }

                for (PhoneNumber phone : emp.getPhoneNumbers()) {
                    assertFetched(phone, defaultPhoneFG);
                }

                for (Project project : emp.getProjects()) {
                    assertFetched(project, employeeFG.getGroup("projects"));
                    Employee teamLeader = project.getTeamLeader();
                    if(teamLeader != null) {
                        assertFetched(teamLeader, employeeFG.getGroup("projects.teamLeader"));
                        for (PhoneNumber phone : teamLeader.getPhoneNumbers()) {
                            assertFetched(phone, employeeFG.getGroup("projects.teamLeader.phoneNumbers"));
                        }
                    }
                }

                Employee manager = emp.getManager();
                if(manager != null) {
                    assertFetched(manager, employeeFG.getGroup("manager"));
                    for (PhoneNumber phone : manager.getPhoneNumbers()) {
                        assertFetched(phone, employeeFG.getGroup("manager.phoneNumbers"));
                    }
                }

                Department department = emp.getDepartment();
                if(department != null) {
                    assertFetched(department, employeeFG.getGroup("department"));
                }
            }
            assertEquals(1, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
        } finally {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
        }
    }

   @Test
   public void joinFetchDefaultFetchGroup() throws Exception {
        EntityManager em = createEntityManager();

        Query query = em.createQuery("SELECT e FROM Employee e");
        query.setHint(QueryHints.LEFT_FETCH, "e.phoneNumbers");

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

        for(Employee emp : employees) {
            assertNoFetchGroup(emp);
            for (PhoneNumber phone : emp.getPhoneNumbers()) {
                assertFetched(phone, defaultPhoneFG);
            }
        }
    }

   @Test
   public void joinFetchOutsideOfFetchGroup() throws Exception {
        EntityManager em = createEntityManager();

        Query query = em.createQuery("SELECT e FROM Employee e");
        // Define the fields to be fetched on Employee
        FetchGroup fg = new FetchGroup();
        fg.addAttribute("firstName");
        fg.addAttribute("lastName");
        query.setHint(QueryHints.FETCH_GROUP, fg);
        query.setHint(QueryHints.LEFT_FETCH, "e.address");

        List<Employee> employees = query.getResultList();
    }

   @Test
   public void simpleNestedFetchGroupWithBatch() {
       EntityManager em = createEntityManager();
        try {
            beginTransaction(em);

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

            // Define the fields to be fetched on Employee
            FetchGroup employeeFG = new FetchGroup();
            employeeFG.setShouldLoad(true);
            employeeFG.addAttribute("firstName");
            employeeFG.addAttribute("lastName");
            employeeFG.addAttribute("address.country");
            employeeFG.addAttribute("address.city");

            FetchGroup phonesFG = defaultPhoneFG.clone();
            // to preclude PhoneNumber from triggering owner's full read
            phonesFG.addAttribute("owner.id");
            employeeFG.addAttribute("phoneNumbers", phonesFG);

            FetchGroup projectsFG = new FetchGroup("projects");
            projectsFG.addAttribute("name");
            projectsFG.addAttribute("name");
            // to preclude Project from triggering full read of the referenced Employee(s)
            projectsFG.addAttribute("teamMembers.id");
            projectsFG.addAttribute("teamLeader.id");
            employeeFG.addAttribute("projects", projectsFG);

            query.setHint(QueryHints.FETCH_GROUP, employeeFG);

            query.setHint(QueryHints.BATCH, "e.address");
            query.setHint(QueryHints.BATCH, "e.phoneNumbers");
            query.setHint(QueryHints.BATCH, "e.projects");

            // A single sql will be used to read all Project subclasses.
            query.setHint(QueryHints.INHERITANCE_OUTER_JOIN, "true");

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

            // Employee, Address, PhoneNumbers, Projects - an sql per class.
            // Address, PhoneNumbers and Projects are already loaded because
            // employeeFG.shouldLoad is set to true.
            assertEquals(4, getQuerySQLTracker(em).getTotalSQLSELECTCalls());

            // verify fetch groups
            for(Employee emp : employees) {
                assertFetched(emp, employeeFG);

                Address address = emp.getAddress();
                if(address != null) {
                         assertFetched(address, employeeFG.getGroup("address"));
                }

                for (PhoneNumber phone : emp.getPhoneNumbers()) {
                         assertFetched(phone, phonesFG);
                }

                for (Project project : emp.getProjects()) {
                         assertFetched(project, projectsFG);
                }
            }

            // Now let's access an attribute outside of the fetch group.
            // That triggers loading of the whole object.
            for(Employee emp : employees) {
                emp.getSalary();
                assertNoFetchGroup(emp);

                Address address = emp.getAddress();
                if(address != null) {
                   address.getStreet();
                   assertNoFetchGroup(address);
                }

                for (PhoneNumber phone : emp.getPhoneNumbers()) {
                    phone.getAreaCode();
                    assertNoFetchGroup(phone);
                }

                for (Project project : emp.getProjects()) {
                    project.getDescription();
                    assertNoFetchGroup(project);
                }
            }
        } finally {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
        }
   }

   @Test
    public void simpleLoadGroup() {
        EntityManager em = createEntityManager();
        try {
            beginTransaction(em);

             Query query = em.createQuery("SELECT e FROM Employee e WHERE e.gender = :GENDER");
             query.setParameter("GENDER", Gender.Female);
             List<Employee> employees = query.getResultList();

             LoadGroup group = new LoadGroup();
             group.addAttribute("address");
             group.addAttribute("phoneNumbers");
             group.addAttribute("manager.projects");
             AbstractSession session = (AbstractSession)((EntityManagerImpl)em.getDelegate()).getActiveSession();
             session.load(employees, group, session.getClassDescriptor(Employee.class), false);

             int numSelectBefore = getQuerySQLTracker(em).getTotalSQLSELECTCalls();

             // All indirections specified in the plan should have been already triggered.
             for(Employee emp : employees) {
                 emp.getAddress();
                 emp.getPhoneNumbers().size();
                 if(emp.getManager() != null) {
                     emp.getManager().getProjects().size();
                 }
             }

             int numSelectAfter = getQuerySQLTracker(em).getTotalSQLSELECTCalls();
             assertEquals(numSelectBefore, numSelectAfter);
        } finally {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
        }
    }

   @Test
   // Bug 325684 - QueryHints.BATCH combined with QueryHints.FETCH_GROUP_LOAD will cause NPE
    public void simpleFetchGroupLoadWithBatch() {
        EntityManager em = createEntityManager();
        try {
            beginTransaction(em);

             FetchGroup projectGroup = new FetchGroup();
             projectGroup.addAttribute("name");

             FetchGroup employeeGroup = new FetchGroup();
             employeeGroup.addAttribute("firstName");
             employeeGroup.addAttribute("lastName");
             employeeGroup.addAttribute("projects", projectGroup);

             Query query = em.createQuery("SELECT e FROM Employee e WHERE e.gender = :GENDER");
             query.setParameter("GENDER", Gender.Female);
             query.setHint(QueryHints.FETCH_GROUP, employeeGroup);
             query.setHint(QueryHints.FETCH_GROUP_LOAD, "true");
             query.setHint(QueryHints.BATCH, "e.projects");
             List<Employee> employees = query.getResultList();

             int numSelectBefore = getQuerySQLTracker(em).getTotalSQLSELECTCalls();

             // All indirections specified in the plan should have been already triggered.
             for (Employee e : employees) {
                 e.getProjects().size();
             }

             int numSelectAfter = getQuerySQLTracker(em).getTotalSQLSELECTCalls();
             assertEquals(numSelectBefore, numSelectAfter);
        } finally {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
        }
    }
}
