/*
 * 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.HashMap;
import java.util.List;
import java.util.Map;

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

import junit.framework.TestSuite;

import org.eclipse.persistence.config.QueryHints;
import org.eclipse.persistence.indirection.IndirectList;
import org.eclipse.persistence.queries.FetchGroup;

import org.eclipse.persistence.testing.models.jpa.advanced.Employee;
import org.eclipse.persistence.testing.models.jpa.advanced.PhoneNumber;

import org.junit.Test;

/**
 * Simple tests to verify the functionality of single level FetchGroup usage
 *
 * @author dclarke
 * @since EclipseLink 2.1
 */
public class SimpleFetchGroupTests extends BaseFetchGroupTests {

    public SimpleFetchGroupTests() {
        super();
    }

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

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

        suite.addTest(new SimpleFetchGroupTests("testSetup"));
        suite.addTest(new SimpleFetchGroupTests("findNoFetchGroup"));
        suite.addTest(new SimpleFetchGroupTests("singleResultNoFetchGroup"));
        suite.addTest(new SimpleFetchGroupTests("resultListNoFetchGroup"));
        suite.addTest(new SimpleFetchGroupTests("singleResultEmptyFetchGroup"));
        suite.addTest(new SimpleFetchGroupTests("resultListEmptyFetchGroup"));
        suite.addTest(new SimpleFetchGroupTests("resultListPeriodFetchGroup"));
        suite.addTest(new SimpleFetchGroupTests("managerFetchGroup"));
        suite.addTest(new SimpleFetchGroupTests("managerFetchGroupWithJoinFetch"));
        suite.addTest(new SimpleFetchGroupTests("employeeNamesFetchGroup"));
        suite.addTest(new SimpleFetchGroupTests("joinFetchEmployeeAddressWithDynamicFetchGroup"));
        suite.addTest(new SimpleFetchGroupTests("joinFetchEmployeeAddressPhoneWithDynamicFetchGroup"));
        suite.addTest(new SimpleFetchGroupTests("verifyFetchedRelationshipAttributes"));
        suite.addTest(new SimpleFetchGroupTests("detachedByClosingEntityManagerObjectWithFetchGroup"));
        if (!isJPA10()) {
            suite.addTest(new SimpleFetchGroupTests("findEmptyFetchGroup"));
            suite.addTest(new SimpleFetchGroupTests("findEmptyFetchGroup_setUnfetchedSalary"));
            suite.addTest(new SimpleFetchGroupTests("verifyUnfetchedAttributes"));
            suite.addTest(new SimpleFetchGroupTests("explicitlyDetachedObjectWithFetchGroup"));
        }
        return suite;
    }

    @Test
    public void findNoFetchGroup() throws Exception {
        EntityManager em = createEntityManager();
        int minId = minimumEmployeeId(em);

        Employee emp = em.find(Employee.class, minId);

        assertNotNull(emp);

        // Check Basics
        assertFetchedAttribute(emp, "id");
        assertFetchedAttribute(emp, "version");
        assertFetchedAttribute(emp, "firstName");
        assertFetchedAttribute(emp, "lastName");
        assertFetchedAttribute(emp, "gender");
        assertFetchedAttribute(emp, "salary");
        assertFetchedAttribute(emp, "startTime");
        assertFetchedAttribute(emp, "endTime");
        if (emp.getPeriod() != null) {
            assertFetchedAttribute(emp.getPeriod(), "startDate");
            assertFetchedAttribute(emp.getPeriod(), "endDate");
        }

        // Check Relationships
        assertNotFetchedAttribute(emp, "address");
        assertNotFetchedAttribute(emp, "manager");
        assertNotFetchedAttribute(emp, "phoneNumbers");
        assertNotFetchedAttribute(emp, "projects");

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

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

        Query query = em.createQuery("SELECT e FROM Employee e WHERE e.id = :ID");
        query.setParameter("ID", minimumEmployeeId(em));

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

        assertNotNull(emp);

        // Check Basics
        assertFetchedAttribute(emp, "id");
        assertFetchedAttribute(emp, "version");
        assertFetchedAttribute(emp, "firstName");
        assertFetchedAttribute(emp, "lastName");
        assertFetchedAttribute(emp, "gender");
        assertFetchedAttribute(emp, "salary");
        assertFetchedAttribute(emp, "startTime");
        assertFetchedAttribute(emp, "endTime");
        if (emp.getPeriod() != null) {
            assertFetchedAttribute(emp.getPeriod(), "startDate");
            assertFetchedAttribute(emp.getPeriod(), "endDate");
        }

        // Check Relationships
        assertNotFetchedAttribute(emp, "address");
        assertNotFetchedAttribute(emp, "manager");
        assertNotFetchedAttribute(emp, "phoneNumbers");
        assertNotFetchedAttribute(emp, "projects");

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

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

        Query query = em.createQuery("SELECT e FROM Employee e WHERE e.id = :ID");
        query.setParameter("ID", minimumEmployeeId(em));

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

        assertNotNull(emps);
        assertEquals(1, emps.size());

        Employee emp = emps.get(0);

        // Check Basics
        assertFetchedAttribute(emp, "id");
        assertFetchedAttribute(emp, "version");
        assertFetchedAttribute(emp, "firstName");
        assertFetchedAttribute(emp, "lastName");
        assertFetchedAttribute(emp, "gender");
        assertFetchedAttribute(emp, "salary");
        assertFetchedAttribute(emp, "startTime");
        assertFetchedAttribute(emp, "endTime");
        if (emp.getPeriod() != null) {
            assertFetchedAttribute(emp.getPeriod(), "startDate");
            assertFetchedAttribute(emp.getPeriod(), "endDate");
        }

        // Check Relationships
        assertNotFetchedAttribute(emp, "address");
        assertNotFetchedAttribute(emp, "manager");
        assertNotFetchedAttribute(emp, "phoneNumbers");
        assertNotFetchedAttribute(emp, "projects");
    }

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

            int minId = minimumEmployeeId(em);

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

            Map<String, Object> properties = new HashMap<String, Object>();
            FetchGroup emptyFG = new FetchGroup();
            properties.put(QueryHints.FETCH_GROUP, emptyFG);

            Employee emp = em.find(Employee.class, minId, properties);

            assertNotNull(emp);
            assertFetched(emp, emptyFG);
            assertEquals(2, getQuerySQLTracker(em).getTotalSQLSELECTCalls());

            // Check Basics
            assertFetchedAttribute(emp, "id");
            assertFetchedAttribute(emp, "version");
            assertNotFetchedAttribute(emp, "firstName");
            assertNotFetchedAttribute(emp, "lastName");
            assertNotFetchedAttribute(emp, "gender");
            assertNotFetchedAttribute(emp, "salary");
            assertNotFetchedAttribute(emp, "startTime");
            assertNotFetchedAttribute(emp, "endTime");
            if (emp.getPeriod() != null) {
                assertFetchedAttribute(emp.getPeriod(), "startDate");
                assertFetchedAttribute(emp.getPeriod(), "endDate");
            }

            // Check Relationships
            assertNotFetchedAttribute(emp, "address");
            assertNotFetchedAttribute(emp, "manager");
            assertNotFetchedAttribute(emp, "phoneNumbers");
            assertNotFetchedAttribute(emp, "projects");

            emp.getSalary();

            assertFetchedAttribute(emp, "salary");

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

            emp.getAddress();

            assertEquals(4, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
            assertNoFetchGroup(emp.getAddress());

            emp.getPhoneNumbers().size();

            assertEquals(5, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
            for (PhoneNumber phone : emp.getPhoneNumbers()) {
                assertNoFetchGroup(phone);
            }

            if (emp.getManager() != null) {
                assertEquals(6, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
            } else {
                // If manager_id field is null then getManager() does not trigger an sql.
                assertEquals(5, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
            }
        }finally {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
        }
    }

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

            int minId = minimumEmployeeId(em);

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

            Map<String, Object> properties = new HashMap<String, Object>();
            FetchGroup emptyFG = new FetchGroup();
            properties.put(QueryHints.FETCH_GROUP, emptyFG);

            Employee emp = em.find(Employee.class, minId, properties);

            assertNotNull(emp);
            assertFetched(emp, emptyFG);
            assertEquals(2, getQuerySQLTracker(em).getTotalSQLSELECTCalls());

            // Check Basics
            assertFetchedAttribute(emp, "id");
            assertFetchedAttribute(emp, "version");
            assertNotFetchedAttribute(emp, "firstName");
            assertNotFetchedAttribute(emp, "lastName");
            assertNotFetchedAttribute(emp, "gender");
            assertNotFetchedAttribute(emp, "salary");
            assertNotFetchedAttribute(emp, "startTime");
            assertNotFetchedAttribute(emp, "endTime");
            if (emp.getPeriod() != null) {
                assertFetchedAttribute(emp.getPeriod(), "startDate");
                assertFetchedAttribute(emp.getPeriod(), "endDate");
            }
            assertEquals(3, getQuerySQLTracker(em).getTotalSQLSELECTCalls());

            // Check Relationships
            assertNotFetchedAttribute(emp, "address");
            assertNotFetchedAttribute(emp, "manager");
            assertNotFetchedAttribute(emp, "phoneNumbers");
            assertNotFetchedAttribute(emp, "projects");

            emp.setSalary(1);

            assertFetchedAttribute(emp, "salary");

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

            emp.getAddress();

            assertEquals(4, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
            assertNoFetchGroup(emp.getAddress());

            emp.getPhoneNumbers().size();

            assertEquals(5, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
            for (PhoneNumber phone : emp.getPhoneNumbers()) {
                assertNoFetchGroup(phone);
            }
        } finally {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
        }
    }

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

            Query query = em.createQuery("SELECT e FROM Employee e WHERE e.id = :ID");
            query.setParameter("ID", minimumEmployeeId(em));
            FetchGroup emptyFG = new FetchGroup();
            query.setHint(QueryHints.FETCH_GROUP, emptyFG);

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

            assertNotNull(emp);
            assertFetched(emp, emptyFG);
            assertEquals(2, getQuerySQLTracker(em).getTotalSQLSELECTCalls());

            // Check Basics
            assertFetchedAttribute(emp, "id");
            assertFetchedAttribute(emp, "version");
            assertNotFetchedAttribute(emp, "firstName");
            assertNotFetchedAttribute(emp, "lastName");
            assertNotFetchedAttribute(emp, "gender");
            assertNotFetchedAttribute(emp, "salary");
            assertNotFetchedAttribute(emp, "startTime");
            assertNotFetchedAttribute(emp, "endTime");
            if (emp.getPeriod() != null) {
                assertFetchedAttribute(emp.getPeriod(), "startDate");
                assertFetchedAttribute(emp.getPeriod(), "endDate");
            }

            // Check Relationships
            assertNotFetchedAttribute(emp, "address");
            assertNotFetchedAttribute(emp, "manager");
            assertNotFetchedAttribute(emp, "phoneNumbers");
            assertNotFetchedAttribute(emp, "projects");

            emp.getSalary();

            assertFetchedAttribute(emp, "salary");

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

            emp.getAddress();

            assertEquals(4, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
            assertNoFetchGroup(emp.getAddress());

            emp.getPhoneNumbers().size();

            assertEquals(5, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
            for (PhoneNumber phone : emp.getPhoneNumbers()) {
                assertNoFetchGroup(phone);
            }
        } finally {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
        }
    }

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

            Query query = em.createQuery("SELECT e FROM Employee e WHERE e.id = :ID");
            query.setParameter("ID", minimumEmployeeId(em));
            FetchGroup emptyFG = new FetchGroup();
            query.setHint(QueryHints.FETCH_GROUP, emptyFG);

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

            assertNotNull(emps);
            assertEquals(1, emps.size());

            Employee emp = emps.get(0);

            assertEquals(2, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
            assertFetched(emp, emptyFG);

            // Check Basics
            assertFetchedAttribute(emp, "id");
            assertFetchedAttribute(emp, "version");
            assertNotFetchedAttribute(emp, "firstName");
            assertNotFetchedAttribute(emp, "lastName");
            assertNotFetchedAttribute(emp, "gender");
            assertNotFetchedAttribute(emp, "salary");
            assertNotFetchedAttribute(emp, "startTime");
            assertNotFetchedAttribute(emp, "endTime");
            assertEquals(2, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
            if (emp.getPeriod() != null) {
                assertFetchedAttribute(emp.getPeriod(), "startDate");
                assertFetchedAttribute(emp.getPeriod(), "endDate");
            }

            // Check Relationships
            assertNotFetchedAttribute(emp, "address");
            assertNotFetchedAttribute(emp, "manager");
            assertNotFetchedAttribute(emp, "phoneNumbers");
            assertNotFetchedAttribute(emp, "projects");

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

            emp.getSalary();

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

            assertNoFetchGroup(emp.getAddress());

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

            for (PhoneNumber phone : emp.getPhoneNumbers()) {
                assertNoFetchGroup(phone);
            }
            assertEquals(5, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
        } finally {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
        }
    }

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

            Query query = em.createQuery("SELECT e FROM Employee e WHERE e.id = :ID");
            query.setParameter("ID", minimumEmployeeId(em));
            FetchGroup fg = new FetchGroup();
            fg.addAttribute("period");
            query.setHint(QueryHints.FETCH_GROUP, fg);

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

            assertNotNull(emps);
            assertEquals(1, emps.size());

            Employee emp = emps.get(0);

            assertEquals(2, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
            assertFetched(emp, fg);

            // Check Basics
            assertFetchedAttribute(emp, "id");
            assertFetchedAttribute(emp, "version");
            assertNotFetchedAttribute(emp, "firstName");
            assertNotFetchedAttribute(emp, "lastName");
            assertNotFetchedAttribute(emp, "gender");
            assertNotFetchedAttribute(emp, "salary");
            assertNotFetchedAttribute(emp, "startTime");
            assertNotFetchedAttribute(emp, "endTime");
            if (emp.getPeriod() != null) {
                assertFetchedAttribute(emp.getPeriod(), "startDate");
                assertFetchedAttribute(emp.getPeriod(), "endDate");
            }

            // Check Relationships
            assertNotFetchedAttribute(emp, "address");
            assertNotFetchedAttribute(emp, "manager");
            assertNotFetchedAttribute(emp, "phoneNumbers");
            assertNotFetchedAttribute(emp, "projects");

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

            emp.getSalary();

            assertFetchedAttribute(emp, "salary");
            assertNoFetchGroup(emp);

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

            assertNoFetchGroup(emp.getAddress());

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

            for (PhoneNumber phone : emp.getPhoneNumbers()) {
                assertNoFetchGroup(phone);
            }
            assertEquals(5, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
        } finally {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
        }
    }

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

            // 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));

            // Complex where clause used to avoid triggering employees and their departments:
            //   Don't include employees who are managers themselves - otherwise if first selected as employee, then as e.manager the full read will be triggered;
            //   Don't include managers with departments - because there is no fetch group on e.manager its (non-null) department will trigger an extra sql
            Query query = em.createQuery("SELECT e FROM Employee e WHERE e.manager IS NOT NULL AND NOT EXISTS(SELECT e2 FROM Employee e2 WHERE e2.manager = e) AND e.manager.department IS NULL");

            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();

            assertFetched(emp, managerFG);
            //int nSqlBeforeGetManager = getQuerySQLTracker(em).getTotalSQLSELECTCalls();
            // manager hasn't been instantiated yet
            assertEquals(1, getQuerySQLTracker(em).getTotalSQLSELECTCalls());

            int nSqlToAdd = 0;
            if (emp.getManager() != null) {
                assertFetchedAttribute(emp, "manager");
                // additional sql to select the manager
                nSqlToAdd++;
            }
            assertEquals(1 + nSqlToAdd, getQuerySQLTracker(em).getTotalSQLSELECTCalls());

            // acuses instantioation of the whole object
            emp.getLastName();

            assertEquals(2 + nSqlToAdd, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
            assertNoFetchGroup(emp);

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

            assertEquals(3 + nSqlToAdd, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
        } finally {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
        }
    }

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

            //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);

            // Complex where clause used to avoid triggering employees and their departments:
            //   Don't include employees who are managers themselves - otherwise if first selected as employee, then as e.manager the full read will be triggered;
            //   Don't include managers with departments - because there is no fetch group on e.manager its (non-null) department will trigger an extra sql
            Query query = em.createQuery("SELECT e FROM Employee e WHERE e.manager IS NOT NULL AND NOT EXISTS(SELECT e2 FROM Employee e2 WHERE e2.manager = e) AND e.manager.department IS NULL");
            FetchGroup managerFG = new FetchGroup();
            managerFG.addAttribute("manager");

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

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

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

            assertFetched(emp, managerFG);
            assertEquals(1, getQuerySQLTracker(em).getTotalSQLSELECTCalls());

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

            // instantiates the whole object
            emp.getLastName();

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

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

            assertEquals(3, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
        } finally {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
        }
    }

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

            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());
            assertFetched(emp, namesFG);

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

            assertEquals(2, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
            assertFetched(emp, namesFG);

            emp.getGender();
            emp.getSalary();

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

            for (PhoneNumber phone : emp.getPhoneNumbers()) {
                assertNoFetchGroup(phone);
                phone.getAreaCode();
            }
            assertEquals(4, getQuerySQLTracker(em).getTotalSQLSELECTCalls());

            if (emp.getManager() != null) {
                assertEquals(5, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
                assertNoFetchGroup(emp.getManager());
            } else {
                // If manager_id field is null then getManager() does not trigger an sql.
                assertEquals(4, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
            }
        } finally {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
        }
    }

    @Override
    @Test
    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);
    }

    @Override
    @Test
    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);
    }

    @Test
    public void verifyUnfetchedAttributes() throws Exception {
        EntityManager em = createEntityManager();
        try {
            beginTransaction(em);
            TypedQuery<Employee> q = em.createQuery("SELECT e FROM Employee e WHERE e.id IN (SELECT MIN(p.id) FROM PhoneNumber p)", Employee.class);
            FetchGroup fg = new FetchGroup("Employee.empty");
            q.setHint(QueryHints.FETCH_GROUP, fg);
            Employee emp = q.getSingleResult();

            assertNotNull(emp);
            assertEquals(1, getQuerySQLTracker(em).getTotalSQLSELECTCalls());

            // This check using the mapping returns a default (empty) IndirectList
            /*OneToManyMapping phoneMapping = (OneToManyMapping) employeeDescriptor.getMappingForAttributeName("phoneNumbers");
            IndirectList phones = (IndirectList) phoneMapping.getAttributeValueFromObject(emp);
            assertNotNull(phones);
            assertTrue(phones.isInstantiated());
            assertEquals(0, phones.size());
            assertEquals(1, getQuerySQLTracker(em).getTotalSQLSELECTCalls());*/

            IndirectList phonesIL = (IndirectList) emp.getPhoneNumbers();
            assertFalse(phonesIL.isInstantiated());
            assertEquals(2, getQuerySQLTracker(em).getTotalSQLSELECTCalls());

            assertTrue(emp.getPhoneNumbers().size() > 0);
            assertEquals(3, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
        } finally {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
        }
    }

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

        FetchGroup fg = new FetchGroup("Employee.relationships");
        fg.addAttribute("address");
        fg.addAttribute("phoneNumbers");
        fg.addAttribute("manager");
        fg.addAttribute("projects");

        Map<String, Object> hints = new HashMap<String, Object>();
        hints.put(QueryHints.FETCH_GROUP, fg);

        Employee emp = minimumEmployee(em, hints);

        assertNotNull(emp);

    }

    @Test
    public void detachedByClosingEntityManagerObjectWithFetchGroup() {
        EntityManager em = createEntityManager();

        FetchGroup fg = new FetchGroup();
        fg.addAttribute("firstName");
        fg.addAttribute("lastName");

        Map<String, Object> hints = new HashMap<String, Object>();
        hints.put(QueryHints.FETCH_GROUP, fg);

        Employee emp = minimumEmployee(em, hints);
        assertFetched(emp, fg);
        closeEntityManager(em);

        // trigger the fetch group
        emp.getSalary();
        assertNoFetchGroup(emp);
    }

    @Test
    public void explicitlyDetachedObjectWithFetchGroup() {
        EntityManager em = createEntityManager();
        try {
            beginTransaction(em);
            FetchGroup fg = new FetchGroup();
            fg.addAttribute("firstName");
            fg.addAttribute("lastName");

            Map<String, Object> hints = new HashMap<String, Object>();
            hints.put(QueryHints.FETCH_GROUP, fg);

            Employee emp = minimumEmployee(em, hints);
            em.detach(emp);
            assertFetched(emp, fg);

            // trigger the fetch group
            emp.getSalary();
            assertNoFetchGroup(emp);
        } finally {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
        }
    }
}
