/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     ailitchev - Uni-directional OneToMany
package org.eclipse.persistence.testing.tests.unidirectional;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.expressions.ExpressionBuilder;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.queries.Call;
import org.eclipse.persistence.queries.ReadAllQuery;
import org.eclipse.persistence.queries.ReadObjectQuery;
import org.eclipse.persistence.queries.SQLCall;
import org.eclipse.persistence.sessions.UnitOfWork;
import org.eclipse.persistence.tools.schemaframework.PopulationManager;
import org.eclipse.persistence.testing.framework.*;
import org.eclipse.persistence.testing.models.unidirectional.*;
import org.eclipse.persistence.testing.tests.writing.ComplexUpdateTest;

/**
 * This model tests reading/writing/deleting through using the employee demo.
 */
public class UnidirectionalEmployeeBasicTestModel extends TestModel {

    /**
     * Return the JUnit suite to allow JUnit runner to find it.
     * Unfortunately JUnit only allows suite methods to be static,
     * so it is not possible to generically do this.
     */
    public static junit.framework.TestSuite suite() {
        return new UnidirectionalEmployeeBasicTestModel();
    }

    public UnidirectionalEmployeeBasicTestModel() {
        setDescription("This model tests reading/writing/deleting using the unidirectionl employee demo.");
    }

    @Override
    public void addRequiredSystems() {
        addRequiredSystem(new EmployeeSystem());
    }

    @Override
    public void addTests() {
        addTest(getReadObjectTestSuite());
        addTest(getComplexUpdateObjectTestSuite());
        addTest(getInsertObjectTestSuite());
        addTest(getDeleteObjectTestSuite());
        addTest(getReadAllTestSuite());
    }

    public static TestSuite getDeleteObjectTestSuite() {
        TestSuite suite = new TestSuite();
        suite.setName("EmployeeDeleteObjectTestSuite");
        suite.setDescription("This suite tests the deletion of each object in the employee demo.");

        Class employeeClass = org.eclipse.persistence.testing.models.unidirectional.Employee.class;
        PopulationManager manager = PopulationManager.getDefaultManager();

        suite.addTest(new DeleteObjectTest(manager.getObject(employeeClass, "0001")));
        suite.addTest(new DeleteObjectTest(manager.getObject(employeeClass, "0002")));
        suite.addTest(new DeleteObjectTest(manager.getObject(employeeClass, "0003")));
        suite.addTest(new DeleteObjectTest(manager.getObject(employeeClass, "0004")));
        suite.addTest(new DeleteObjectTest(manager.getObject(employeeClass, "0005")));

        suite.addTest(new TargetLockingTest_DeleteSource(true));
        suite.addTest(new TargetLockingTest_DeleteSource(false));

        return suite;
    }

    public static TestSuite getInsertObjectTestSuite() {
        TestSuite suite = new TestSuite();
        suite.setName("EmployeeUOWBasicInsertObjectTestSuite");
        suite.setDescription("This suite tests the insertion of each object in the employee demo using uow.");
        EmployeePopulator system = new EmployeePopulator();

        suite.addTest(new UnitOfWorkBasicInsertObjectTest(system.basicEmployeeExample1()));
        suite.addTest(new UnitOfWorkBasicInsertObjectTest(system.basicEmployeeExample2()));
        suite.addTest(new UnitOfWorkBasicInsertObjectTest(system.basicEmployeeExample3()));
        suite.addTest(new UnitOfWorkBasicInsertObjectTest(system.basicEmployeeExample4()));
        suite.addTest(new UnitOfWorkBasicInsertObjectTest(system.basicEmployeeExample5()));

        return suite;
    }

    public static TestSuite getReadAllTestSuite() {
        TestSuite suite = new TestSuite();
        suite.setName("EmployeeReadAllTestSuite");
        suite.setDescription("This suite tests the reading of all the objects of each class in the employee demo.");

        suite.addTest(new ReadAllTest(Employee.class, 12));

        suite.addTest(new ReadAllCallTest(Employee.class, 12, new SQLCall("SELECT VERSION, EMP_ID, L_NAME, F_NAME FROM UNIDIR_EMPLOYEE")));

        //Add new tests here ...
        Expression orderBy = new ExpressionBuilder().get("firstName").ascending();
        Call call = new SQLCall("SELECT VERSION, EMP_ID, L_NAME, F_NAME FROM UNIDIR_EMPLOYEE");
        suite.addTest(new ReadAllCallWithOrderingTest(Employee.class, 12, call, orderBy));

        suite.addTest(new JoinTest());
        suite.addTest(new JoinTest_SelectByFirstName());
        suite.addTest(new BatchReadingTest());
        suite.addTest(new BatchReadingTest_SelectByFirstName());

        return suite;
    }

    public static TestSuite getReadObjectTestSuite() {
        TestSuite suite = new TestSuite();
        suite.setName("EmployeeReadObjectTestSuite");
        suite.setDescription("This suite test the reading of each object in the employee demo.");

        Class employeeClass = Employee.class;
        PopulationManager manager = PopulationManager.getDefaultManager();

        suite.addTest(new ReadObjectTest(manager.getObject(employeeClass, "0001")));
        suite.addTest(new ReadObjectTest(manager.getObject(employeeClass, "0002")));
        suite.addTest(new ReadObjectTest(manager.getObject(employeeClass, "0003")));
        suite.addTest(new ReadObjectTest(manager.getObject(employeeClass, "0004")));
        suite.addTest(new ReadObjectTest(manager.getObject(employeeClass, "0005")));

        Employee employee = (Employee)manager.getObject(employeeClass, "0001");
        suite.addTest(new ReadObjectCallTest(employeeClass, new SQLCall("SELECT VERSION, EMP_ID, L_NAME, F_NAME FROM UNIDIR_EMPLOYEE WHERE F_NAME = '"+employee.getFirstName()+"' AND L_NAME = '"+employee.getLastName()+"'")));
        employee = (Employee)manager.getObject(employeeClass, "0002");
        suite.addTest(new ReadObjectCallTest(employeeClass, new SQLCall("SELECT VERSION, EMP_ID, L_NAME, F_NAME FROM UNIDIR_EMPLOYEE WHERE F_NAME = '"+employee.getFirstName()+"' AND L_NAME = '"+employee.getLastName()+"'")));
        employee = (Employee)manager.getObject(employeeClass, "0003");
        suite.addTest(new ReadObjectCallTest(employeeClass, new SQLCall("SELECT VERSION, EMP_ID, L_NAME, F_NAME FROM UNIDIR_EMPLOYEE WHERE F_NAME = '"+employee.getFirstName()+"' AND L_NAME = '"+employee.getLastName()+"'")));

        return suite;
    }

    public static TestSuite getComplexUpdateObjectTestSuite() {
        TestSuite suite = new TestSuite();
        suite.setName("EmployeeComplexUpdateTestSuite");
        suite.setDescription("This suite tests the updating of each an employee by adding and/or removing managed employees and/or phones.");

        Class employeeClass = Employee.class;
        PopulationManager manager = PopulationManager.getDefaultManager();
        Employee originalEmployee = (Employee)manager.getObject(employeeClass, "0001");
        Employee otherEmployee = (Employee)manager.getObject(employeeClass, "0002");

        // add a managed Employee from other Employee managed List; remove the first managed Employee.
        suite.addTest(new EmployeeComplexUpdateTest(originalEmployee, otherEmployee.getManagedEmployees().get(0), originalEmployee.getManagedEmployees().get(0)));
        // remove the first Phone.
        suite.addTest(new EmployeeComplexUpdateTest(originalEmployee, (Object)null, originalEmployee.getPhoneNumbers().get(0)));
        // add a managed Employee from other Employee managed List and new phone;
        // remove the first two managed Employees and the first Phone.
        Employee newEmployee = new Employee();
        newEmployee.setFirstName("New");
        PhoneNumber newPhoneNumber = new PhoneNumber("home", "001", "0000001");
        suite.addTest(new EmployeeComplexUpdateTest(originalEmployee,
                new Object[]{otherEmployee.getManagedEmployees().get(0), newEmployee, newPhoneNumber},
                new Object[]{originalEmployee.getManagedEmployees().get(0), originalEmployee.getManagedEmployees().get(1), originalEmployee.getPhoneNumbers().get(0)}));
        suite.addTest(new CascadeLockingTest());
        suite.addTest(new TargetLockingTest_AddRemoveTarget());

        return suite;
    }

    /**
     * Tests adding/removing of target object to/from the source for UnidirectionalOneToManyMapping.
     * Derived from ComplexUpdateTest, this test expects an instance of Employee as original object,
     * as well as object (or array, or list) of objects to be added to the original objects as the second parameter,
     * as well as object (or array, or list) of objects to be removed from the original objects as the third parameter.
     * These objects should be of type either Employee or PhoneNumber.
     */
    static class EmployeeComplexUpdateTest extends ComplexUpdateTest {
        List<Employee> managedEmployeesToAdd = new ArrayList<Employee>();
        List<Employee> managedEmployeesToRemove = new ArrayList<Employee>();
        List<PhoneNumber> phonesToAdd = new ArrayList<PhoneNumber>();
        List<PhoneNumber> phonesToRemove = new ArrayList<PhoneNumber>();
        public EmployeeComplexUpdateTest(Employee originalEmployee, List objectsToAdd, Object objectToRemove) {
            this(originalEmployee, (objectsToAdd != null ? objectsToAdd.toArray() : null), (objectToRemove != null ? new Object[]{objectToRemove} : null));
        }
        public EmployeeComplexUpdateTest(Employee originalEmployee, Object objectToAdd, List objectsToRemove) {
            this(originalEmployee, (objectToAdd != null ? new Object[]{objectToAdd} : null), (objectsToRemove != null ? objectsToRemove.toArray() : null));
        }
        public EmployeeComplexUpdateTest(Employee originalEmployee, List objectsToAdd, List objectsToRemove) {
            this(originalEmployee, (objectsToAdd != null ? objectsToAdd.toArray() : null), (objectsToRemove != null ? objectsToRemove.toArray() : null));
        }
        public EmployeeComplexUpdateTest(Employee originalEmployee, Object objectToAdd, Object objectToRemove) {
            this(originalEmployee, (objectToAdd != null ? new Object[]{objectToAdd} : null), (objectToRemove != null ? new Object[]{objectToRemove} : null));
        }
        public EmployeeComplexUpdateTest(Employee originalEmployee, Object[] objectsToAdd, Object objectToRemove) {
            this(originalEmployee, objectsToAdd, (objectToRemove != null ? new Object[]{objectToRemove} : null));
        }
        public EmployeeComplexUpdateTest(Employee originalEmployee, Object objectToAdd, Object[] objectsToRemove) {
            this(originalEmployee, (objectToAdd != null ? new Object[]{objectToAdd} : null), objectsToRemove);
        }
        public EmployeeComplexUpdateTest(Employee originalEmployee, Object[] objectsToAdd, Object[] objectsToRemove) {
            super(originalEmployee);
            this.usesUnitOfWork = true;
            if(objectsToAdd != null) {
                for(int i=0; i < objectsToAdd.length; i++) {
                    Object objectToAdd = objectsToAdd[i];
                    if(objectToAdd instanceof Employee) {
                        if(!originalEmployee.getManagedEmployees().contains(objectToAdd)) {
                            managedEmployeesToAdd.add((Employee)objectToAdd);
                        } else {
                            throw new TestWarningException("OriginalEmployee: " + originalEmployee + " already manages employee to be added: " + objectToAdd);
                        }
                    } else {
                        // must be Phone
                        if(!originalEmployee.getPhoneNumbers().contains(objectToAdd)) {
                            phonesToAdd.add((PhoneNumber)objectToAdd);
                        } else {
                            throw new TestWarningException("OriginalEmployee: " + originalEmployee + " already has the phonee to be added: " + objectToAdd);
                        }
                    }
                }
            }
            if(objectsToRemove != null) {
                for(int i=0; i < objectsToRemove.length; i++) {
                    Object objectToRemove = objectsToRemove[i];
                    if(objectToRemove instanceof Employee) {
                        if(originalEmployee.getManagedEmployees().contains(objectToRemove)) {
                            managedEmployeesToRemove.add((Employee)objectToRemove);
                        } else {
                            throw new TestWarningException("OriginalEmployee: " + originalEmployee + " doesn't manage employee to be removed: " + objectToRemove);
                        }
                    } else {
                        // must be Phone
                        if(originalEmployee.getPhoneNumbers().contains(objectToRemove)) {
                            phonesToRemove.add((PhoneNumber)objectToRemove);
                        } else {
                            throw new TestWarningException("OriginalEmployee: " + originalEmployee + " doesn't have the phonee to be removed: " + objectToRemove);
                        }
                    }
                }
            }
            // generate a meaningful test name
            String employeeString = "";
            if(managedEmployeesToAdd.size() > 0 || managedEmployeesToRemove.size() > 0 ) {
                String addString = "";
                if(managedEmployeesToAdd.size() > 0) {
                    addString = "add "+ managedEmployeesToAdd.size();
                }
                String removeString = "";
                if(managedEmployeesToRemove.size() > 0) {
                    removeString = "remove "+ managedEmployeesToRemove.size();
                }
                employeeString = addString +(addString.length()>0 && removeString.length()>0 ? " and " : " ") + removeString + " Employees";
            }
            String phoneString = "";
            if(phonesToAdd.size() > 0 || phonesToRemove.size() > 0 ) {
                String addString = "";
                if(phonesToAdd.size() > 0) {
                    addString = "add "+ phonesToAdd.size();
                }
                String removeString = "";
                if(phonesToRemove.size() > 0) {
                    removeString = "remove "+ phonesToRemove.size();
                }
                phoneString = addString +(addString.length()>0 && removeString.length()>0 ? " and " : "") + removeString + " Phones";
            }
            setName("EmployeeComplexUpdateTest: " + employeeString +(employeeString.length()>0 && phoneString.length()>0 ? "; " : "")+ phoneString+";");
            setDescription("The test updates original Employee object: " +originalObject.toString()+ " from the database by adding and/or removing managedEmployees and/or PhoneNumbers and verifies that the object updated correctly.");
        }
        @Override
        public String getName() {
            String testName = super.getName();
            int lastIndex = testName.lastIndexOf(";");
            if(lastIndex > 0) {
                testName = testName.substring(0, lastIndex);
            }
            return testName;
        }
        @Override
        protected void changeObject() {
            UnitOfWork uow = (UnitOfWork)getSession();
            Employee cloneEmployee = (Employee)workingCopy;
            for(int i=0; i < managedEmployeesToAdd.size(); i++) {
                Employee cloneEmployeeToAdd = (Employee)uow.registerObject(managedEmployeesToAdd.get(i));
                cloneEmployee.addManagedEmployee(cloneEmployeeToAdd);
            }
            for(int i=0; i < managedEmployeesToRemove.size(); i++) {
                Employee cloneEmployeeToRemove = (Employee)uow.registerObject(managedEmployeesToRemove.get(i));
                cloneEmployee.removeManagedEmployee(cloneEmployeeToRemove);
            }
            for(int i=0; i < phonesToRemove.size(); i++) {
                PhoneNumber clonePhoneToRemove = (PhoneNumber)uow.registerObject(phonesToRemove.get(i));
                cloneEmployee.removePhoneNumber(clonePhoneToRemove);
            }
            for(int i=0; i < phonesToAdd.size(); i++) {
                PhoneNumber clonePhoneToAdd = (PhoneNumber)uow.registerObject(phonesToAdd.get(i));
                cloneEmployee.addPhoneNumber(clonePhoneToAdd);
            }
        }
        @Override
        protected void setup() {
            super.setup();

            for(int i=0; i < managedEmployeesToAdd.size(); i++) {
                Employee readEmployeeToAdd = (Employee)readObject(managedEmployeesToAdd.get(i));
                if(readEmployeeToAdd != null) {
                    managedEmployeesToAdd.set(i, readEmployeeToAdd);
                } else {
                    // it's a new object
                }
            }
            for(int i=0; i < managedEmployeesToRemove.size(); i++) {
                Employee readEmployeeToRemove = (Employee)readObject(managedEmployeesToRemove.get(i));
                if(readEmployeeToRemove != null) {
                    managedEmployeesToRemove.set(i, readEmployeeToRemove);
                } else {
                    throw new TestWarningException("Employee to be removed: " + managedEmployeesToRemove.get(i) + " is not in the db");
                }
            }
            for(int i=0; i < phonesToRemove.size(); i++) {
                PhoneNumber readPhoneToRemove = (PhoneNumber)readObject(phonesToRemove.get(i));
                if(readPhoneToRemove != null) {
                    phonesToRemove.set(i, readPhoneToRemove);
                } else {
                    throw new TestWarningException("Phone to be removed: " + phonesToRemove.get(i) + " is not in the db");
                }
            }
            for(int i=0; i < phonesToAdd.size(); i++) {
                PhoneNumber readPhoneToAdd = (PhoneNumber)readObject(phonesToAdd.get(i));
                if(readPhoneToAdd != null) {
                    phonesToAdd.set(i, readPhoneToAdd);
                } else {
                    // it's a new object
                }
            }
        }
        protected Object readObject(Object object) {
            ReadObjectQuery query = new ReadObjectQuery();
            query.setSelectionObject(object);
            return getSession().executeQuery(query);
        }
    }

    /**
     * Tests cascade locking of the source Employee object for adding, modifying and removing the target object (Employee and Phone).
     * The version of he source should be always incremented on either adding or removing any target.
     * Also currently source's version incremented on changing of the privately owned target (Phone),
     * but on change of non private target (managed Employee) stays unchanged.
     */
    static class CascadeLockingTest extends TransactionalTestCase {
        long version[] = new long[7];
        long versionExpected[] = new long[] {1, 2, 2, 3, 4, 5, 6};
        public CascadeLockingTest() {
            super();
            setName("CascadeLockingPolicyTest");
            setDescription("Tests optimistic lock cascading for UnidirectionalOneToManyMapping");
        }
        @Override
        public void setup() {
            super.setup();
            for(int i=0; i<version.length; i++) {
                version[i] = 0;
            }
        }
        @Override
        public void test() {
            // setup
            Employee manager = new Employee();
            manager.setFirstName("Manager");
            Employee employee = new Employee();
            employee.setFirstName("Employee");

            UnitOfWork uow = getSession().acquireUnitOfWork();
            uow.registerObject(manager);
            uow.registerObject(employee);
            uow.commit();

            version[0] = (Long) getSession().getDescriptor(Employee.class).getOptimisticLockingPolicy().getWriteLockValue(manager, manager.getId(), getAbstractSession());

            // test1 - add managed employee, manager's version should increment.
            uow = getSession().acquireUnitOfWork();
            Employee managerClone = (Employee)uow.registerObject(manager);
            Employee employeeClone = (Employee)uow.registerObject(employee);
            managerClone.addManagedEmployee(employeeClone);
            uow.commit();
            version[1] = (Long) getSession().getDescriptor(Employee.class).getOptimisticLockingPolicy().getWriteLockValue(manager, manager.getId(), getAbstractSession());

            // test2 - alter managed employee, manager's version should NOT increment.
            uow = getSession().acquireUnitOfWork();
            employeeClone = (Employee)uow.registerObject(employee);
            employeeClone.setFirstName("Altered");
            uow.commit();
            version[2] = (Long) getSession().getDescriptor(Employee.class).getOptimisticLockingPolicy().getWriteLockValue(manager, manager.getId(), getAbstractSession());

            // test3- remove managed employee, manager's version should increment.
            uow = getSession().acquireUnitOfWork();
            managerClone = (Employee)uow.registerObject(manager);
            employeeClone = (Employee)uow.registerObject(employee);
            managerClone.removeManagedEmployee(employeeClone);
            uow.commit();
            version[3] = (Long) getSession().getDescriptor(Employee.class).getOptimisticLockingPolicy().getWriteLockValue(manager, manager.getId(), getAbstractSession());

            PhoneNumber phone = new PhoneNumber("home", "613", "1111111");

            // test4 - add phone, manager's version should increment.
            uow = getSession().acquireUnitOfWork();
            managerClone = (Employee)uow.registerObject(manager);
            PhoneNumber phoneClone = (PhoneNumber)uow.registerObject(phone);
            managerClone.addPhoneNumber(phoneClone);
            uow.commit();
            version[4] = (Long) getSession().getDescriptor(Employee.class).getOptimisticLockingPolicy().getWriteLockValue(manager, manager.getId(), getAbstractSession());

            // test5- alter phone, manager's version should increment.
            uow = getSession().acquireUnitOfWork();
            phoneClone = (PhoneNumber)uow.registerObject(phone);
            phoneClone.setType("work");
            uow.commit();
            version[5] = (Long) getSession().getDescriptor(Employee.class).getOptimisticLockingPolicy().getWriteLockValue(manager, manager.getId(), getAbstractSession());

            // test6- remove phone, manager's version should increment.
            uow = getSession().acquireUnitOfWork();
            managerClone = (Employee)uow.registerObject(manager);
            phoneClone = (PhoneNumber)uow.registerObject(phone);
            managerClone.removePhoneNumber(phoneClone);
            uow.commit();
            version[6] = (Long) getSession().getDescriptor(Employee.class).getOptimisticLockingPolicy().getWriteLockValue(manager, manager.getId(), getAbstractSession());
        }
        @Override
        public void verify() {
            int numTestsFailed = 0;
            String errorMsg = "";
            for(int i=0; i<version.length; i++) {
                if(version[i] + numTestsFailed != versionExpected[i]) {
                    numTestsFailed++;
                    errorMsg += "test" + i +" failed; ";
                }
            }
            if(numTestsFailed > 0) {
                throw new TestErrorException(errorMsg);
            }
        }
    }
    static class BatchReadingTest extends TestCase {
        boolean shouldPrintDebugOutput = false;
        public BatchReadingTest() {
            setName("EmployeeBatchReadingTest - no selection criteria");
            setDescription("Tests batch reading of Employees with batch expression managedEmployees.phoneNumbers");
        }
        void setSelectionCriteria(ReadAllQuery query) {
        }
        @Override
        public void test() {
            // clear cache
            getSession().getIdentityMapAccessor().initializeAllIdentityMaps();
            // create batch read query, set its selectionCriteria
            ReadAllQuery query = new ReadAllQuery(Employee.class);
            setSelectionCriteria(query);
            // before adding batch read attributes clone the query to create control query
            ReadAllQuery controlQuery = (ReadAllQuery)query.clone();
            // add batch read attributes
            Expression managedEmployees = query.getExpressionBuilder().get("managedEmployees");
            Expression managedEmployeesPhoneNumbers = managedEmployees.get("phoneNumbers");
            query.addBatchReadAttribute(managedEmployeesPhoneNumbers);
            // execute the query
            List employees = (List)getSession().executeQuery(query);
            if(employees.isEmpty()) {
                throw new TestProblemException("No Employees were read");
            }
            // need to instantiate only a single Phone on a single managed Employee to trigger sql that reads data from the db for all.
            // still need to trigger all the indirections - but (except the first one) they are not accessing the db
            // (the data is already cached in the value holders).
            printDebug("Trigger batch reading results");
            boolean isConnected = true;
            for(int i=0; i < employees.size(); i++) {
                Employee manager = (Employee)employees.get(i);
                if(!manager.getManagedEmployees().isEmpty()) {
                    printDebug("Manager = " + manager);
                    for(int j=0; j < manager.getManagedEmployees().size(); j++) {
                        Employee emp = (Employee)manager.getManagedEmployees().get(j);
                        printDebug("     " + emp);
                        for(int k = 0; k < emp.getPhoneNumbers().size(); k++) {
                            if(isConnected) {
                                // need to instantiate only a single Phone on a single managed Employee to trigger sql that reads data from the db for all.
                                // to ensure that no other sql is issued close connection.
                                ((AbstractSession)getSession()).getAccessor().closeConnection();
                                isConnected = false;
                            }
                            PhoneNumber phone = (PhoneNumber)emp.getPhoneNumbers().get(k);
                            printDebug("          " + phone);
                        }
                    }
                } else {
                    printDebug(manager.toString());
                }
            }
            if(!isConnected) {
                // reconnect connection
                ((AbstractSession)getSession()).getAccessor().reestablishConnection((AbstractSession)getSession());
            }
            printDebug("");

            // obtain control results
            // clear cache
            getSession().getIdentityMapAccessor().initializeAllIdentityMaps();
            // execute control query
            List controlEmployees = (List)getSession().executeQuery(controlQuery);
            // instantiate all value holders that the batch query expected to instantiate
            printDebug("Trigger control results");
            for(int i=0; i < controlEmployees.size(); i++) {
                Employee manager = (Employee)controlEmployees.get(i);
                if(!manager.getManagedEmployees().isEmpty()) {
                    printDebug("Manager = " + manager);
                    for(int j=0; j < manager.getManagedEmployees().size(); j++) {
                        Employee emp = (Employee)manager.getManagedEmployees().get(j);
                        printDebug("     " + emp);
                        for(int k = 0; k < emp.getPhoneNumbers().size(); k++) {
                            PhoneNumber phone = (PhoneNumber)emp.getPhoneNumbers().get(k);
                            printDebug("          " + phone);
                        }
                    }
                } else {
                    printDebug(manager.toString());
                }
            }

            // compare results
            String errorMsg = JoinedAttributeTestHelper.compareCollections(employees, controlEmployees, getSession().getClassDescriptor(Employee.class), ((AbstractSession)getSession()));
            if(errorMsg.length() > 0) {
                throw new TestErrorException(errorMsg);
            }
        }
        void printDebug(String msg) {
            if(shouldPrintDebugOutput) {
                System.out.println(msg);
            }
        }
    }
    static class BatchReadingTest_SelectByFirstName extends BatchReadingTest {
        public BatchReadingTest_SelectByFirstName() {
            super();
            setName("EmployeeBatchReadingTest - select by first name");
        }
        @Override
        void setSelectionCriteria(ReadAllQuery query) {
            query.setSelectionCriteria(query.getExpressionBuilder().get("firstName").like("J%"));
        }
    }
    static class JoinTest extends TestCase {
        public JoinTest() {
            super();
            setName("JoinTest - no selection criteria");
            setDescription("Tests reading of Employees with join expressions anyOf(managedEmployees) and anyOf(managedEmployees).anyOf(phoneNumbers)");
        }
        void setSelectionCriteria(ReadAllQuery query) {
        }
        @Override
        public void test() {
            ReadAllQuery query = new ReadAllQuery();
            query.setReferenceClass(Employee.class);
            setSelectionCriteria(query);

            ReadAllQuery controlQuery = (ReadAllQuery)query.clone();

            Expression employees = query.getExpressionBuilder().anyOf("managedEmployees");
            query.addJoinedAttribute(employees);
            Expression phones = employees.anyOf("phoneNumbers");
            query.addJoinedAttribute(phones);

            String errorMsg = JoinedAttributeTestHelper.executeQueriesAndCompareResults(controlQuery, query, (AbstractSession)getSession());
            if(errorMsg.length() > 0) {
                throw new TestErrorException(errorMsg);
            }
        }
    }
    static class JoinTest_SelectByFirstName extends JoinTest {
        public JoinTest_SelectByFirstName() {
            super();
            setName("JoinTest - select by first name");
        }
        @Override
        void setSelectionCriteria(ReadAllQuery query) {
            query.setSelectionCriteria(query.getExpressionBuilder().get("firstName").like("J%"));
        }
    }

    /**
     * Base class for TargetLockingTest_AddRemoveTarget and TargetLockingTest_DeleteSource.
     * and mapping's shouldIncrementTargetLockValueOnAddOrRemoveTarget flag is set to true (default setting)
     * adding/removing target to/from source causes target's version to increment.
     */
    static class TargetLockingTest extends TestCase {
        Employee employee[];

        public TargetLockingTest() {
            super();
        }
        long getVersion(Employee emp) {
            return (Long) getSession().getDescriptor(Employee.class).getOptimisticLockingPolicy().getWriteLockValue(emp, emp.getId(), getAbstractSession());
        }
        @Override
        public void reset() {
            UnitOfWork uow = getSession().acquireUnitOfWork();
            for(int i=0; i<employee.length; i++) {
                if(employee[i] != null) {
                    uow.deleteObject(employee[i]);
                }
            }
            uow.commit();
        }
    }
    /**
     * If target descriptor of UnidirectionalOneToMany mapping has optimistic locking policy,
     * and mapping's shouldIncrementTargetLockValueOnAddOrRemoveTarget flag is set to true (default setting)
     * adding/removing target to/from source causes target's version to increment.
     */
    static class TargetLockingTest_AddRemoveTarget extends TargetLockingTest {

        public TargetLockingTest_AddRemoveTarget() {
            super();
            setName("TargetLockingTest_AddRemoveTarget");
            setDescription("Tests target optimistic locking for UnidirectionalOneToManyMapping when targets are added to and removed from the source.");
        }
        @Override
        public void setup() {
            // create 5 Employees.
            employee = new Employee[5];

            employee[0] = new Employee();
            employee[0].setFirstName("Manager");

            // 1 and 2 have manager 0.
            employee[1] = new Employee();
            employee[1].setFirstName("Employee_1");
            employee[0].addManagedEmployee(employee[1]);

            employee[2] = new Employee();
            employee[2].setFirstName("Employee_2");
            employee[0].addManagedEmployee(employee[2]);

            // 3 and 4 don't have a manager.
            employee[3] = new Employee();
            employee[3].setFirstName("Employee_3");

            employee[4] = new Employee();
            employee[4].setFirstName("Employee_4");

            // insert all the Employees into the db.
            UnitOfWork uow = getSession().acquireUnitOfWork();
            for(int i=0; i<employee.length; i++) {
                uow.registerObject(employee[i]);
            }
            uow.commit();
        }
        @Override
        public void test() {
            UnitOfWork uow = getSession().acquireUnitOfWork();
            Employee managerClone = (Employee)uow.registerObject(employee[0]);
            // remove all managed Employees (1 and 2)
            managerClone.getManagedEmployees().clear();
            // add to managed list new Employees (3 and 4)
            Employee employee3Clone = (Employee)uow.registerObject(employee[3]);
            Employee employee4Clone = (Employee)uow.registerObject(employee[4]);
            managerClone.addManagedEmployee(employee3Clone);
            managerClone.addManagedEmployee(employee4Clone);
            // after commit the  versions of all Employees should be changed.
            uow.commit();
        }
        @Override
        public void verify() {
            long version[] = new long[employee.length];
            String errorMsg = "";
            for(int i=0; i<employee.length; i++) {
                version[i] = getVersion(employee[i]);
                if(version[i] != 2) {
                    errorMsg += "in the cache version["+i+"] = "+version[i]+" (2 was expected); ";
                }
            }
            // make sure that versions in the db are correct, too.
            for(int i=0; i<employee.length; i++) {
                employee[i] = (Employee)getSession().refreshObject(employee[i]);
                version[i] = getVersion(employee[i]);
                if(version[i] != 2) {
                    errorMsg += "in the db version["+i+"] = "+version[i]+" (2 was expected); ";
                }
            }
            if(errorMsg.length() > 0) {
                throw new TestErrorException(errorMsg);
            }
        }
    }
    /**
     * If target descriptor of UnidirectionalOneToMany mapping has optimistic locking policy,
     * and mapping's shouldIncrementTargetLockValueOnDeleteSource flag is set to true (default setting)
     * the deleting the source source causes all targets' versions to increment.
     * Note that in this case the indirection is triggered to make sure that the proper targets' versions used.
     */
    static class TargetLockingTest_DeleteSource extends TargetLockingTest {
        boolean isIndirectionTriggered;

        public TargetLockingTest_DeleteSource(boolean isIndirectionTriggered) {
            super();
            this.isIndirectionTriggered = isIndirectionTriggered;
            setName("TargetLockingTest_DeleteSource");
            if(isIndirectionTriggered) {
                setName(getName() + "_IndirectionTriggered");
            } else {
                setName(getName() + "_IndirectionNotTriggered");
            }
            setDescription("Tests target optimistic locking for UnidirectionalOneToManyMapping when the source is deleted.");
        }
        @Override
        public void setup() {
            // create 3 Employees.
            employee = new Employee[3];

            employee[0] = new Employee();
            employee[0].setFirstName("Manager");

            // 1 and 2 have manager 0.
            employee[1] = new Employee();
            employee[1].setFirstName("Employee_1");
            employee[0].addManagedEmployee(employee[1]);

            employee[2] = new Employee();
            employee[2].setFirstName("Employee_2");
            employee[0].addManagedEmployee(employee[2]);

            // insert all the Employees into the db.
            UnitOfWork uow = getSession().acquireUnitOfWork();
            for(int i=0; i<employee.length; i++) {
                uow.registerObject(employee[i]);
            }
            uow.commit();

            getSession().getIdentityMapAccessor().initializeAllIdentityMaps();
        }
        @Override
        public void test() {
            employee[0] = (Employee)getSession().readObject(employee[0]);
            if(isIndirectionTriggered) {
                // that triggers indirection.
                employee[0].getManagedEmployees().size();
            }

            UnitOfWork uow = getSession().acquireUnitOfWork();
            Employee managerClone = (Employee)uow.deleteObject(employee[0]);
            // after commit 0 is deleted and the versions of 1 and 2 should be changed.
            uow.commit();
            // set the deleted Employee to null so that reset method won't attempt to delete it again.
            employee[0] = null;
        }
        @Override
        public void verify() {
            long version[] = new long[employee.length];
            String errorMsg = "";
            for(int i=1; i<employee.length; i++) {
                version[i] = getVersion(employee[i]);
                if(version[i] != 2) {
                    errorMsg += "in the cache version["+i+"] = "+version[i]+" (2 was expected); ";
                }
            }
            // make sure that versions in the db are correct, too.
            for(int i=1; i<employee.length; i++) {
                employee[i] = (Employee)getSession().refreshObject(employee[i]);
                version[i] = getVersion(employee[i]);
                if(version[i] != 2) {
                    errorMsg += "in the db version["+i+"] = "+version[i]+" (2 was expected); ";
                }
            }
            if(errorMsg.length() > 0) {
                throw new TestErrorException(errorMsg);
            }
        }
    }
}
