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

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import jakarta.persistence.EntityManager;
import jakarta.persistence.spi.PersistenceProvider;


import org.eclipse.persistence.queries.ReadAllQuery;
import org.eclipse.persistence.sessions.Session;
import org.eclipse.persistence.sessions.server.ServerSession;
import org.eclipse.persistence.testing.models.jpa.performance.*;
import org.eclipse.persistence.testing.tests.performance.emulateddb.EmulatedDriver;
import org.eclipse.persistence.config.CacheIsolationType;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.jpa.JpaCache;
import org.eclipse.persistence.jpa.JpaEntityManager;
import org.eclipse.persistence.testing.framework.*;

/**
 * Performance tests that compare JPA performance.
 */
public class JPAPerformanceComparisonModel extends TestModel {

    public JPAPerformanceComparisonModel() {
        setDescription("Performance tests that compare JPA performance.");
    }

    @Override
    public void addTests() {
        TestSuite suite = new TestSuite();
        suite.setName("ReadingSuite");
        suite.addTest(buildReadAllVsReadAllResultSet(Address.class));
        suite.addTest(buildReadAllVsReadAllResultSet(Employee.class));
        // ResultSetSideBySideTest useful for profiling regular vs ResultSet Access optimization.
/*        suite.addTest(new ResultSetSideBySideTest(Address.class, true));
        suite.addTest(new ResultSetSideBySideTest(Address.class, false));
        suite.addTest(new ResultSetSideBySideTest(Employee.class, true));
        suite.addTest(new ResultSetSideBySideTest(Employee.class, false));*/
        suite.addTest(buildBatchFetchTest());
        suite.addTest(buildLoadTest());
        addTest(suite);
        suite = new TestSuite();
        suite.setName("WritingSuite");
        suite.addTest(buildBatchWriteTest());
        suite.addTest(buildBatchUpdateTest());
        addTest(suite);
    }

    /**
     * Create/populate database.
     */
    @Override
    public void setup() {
        /*
        // Setup DataSource for apples to apples comparison (otherwise we crush them).
        try {
            System.setProperty("java.naming.factory.initial", "org.eclipse.persistence.testing.framework.naming.InitialContextFactoryImpl");
            oracle.jdbc.pool.OracleDataSource datasource = new oracle.jdbc.pool.OracleDataSource();
            datasource.setURL(getSession().getLogin().getConnectionString());
            datasource.setUser(getSession().getLogin().getUserName());
            datasource.setPassword(getSession().getLogin().getPassword());
            datasource.setConnectionCachingEnabled(true);
            java.util.Properties properties = new java.util.Properties();
            properties.setProperty("MinLimit", "5");
            properties.setProperty("MaxLimit", "100");
            properties.setProperty("InitialLimit", "1");
            properties.setProperty("MaxStatementsLimit", "50");
            datasource.setConnectionCacheProperties(properties);

            new javax.naming.InitialContext().bind("datasource", datasource);
        } catch (Exception exception) {
            throw new RuntimeException(exception);
        }*/

        setupProvider();
        getSession().logMessage(getExecutor().getEntityManagerFactory().getClass().toString());
        System.out.println(getExecutor().getEntityManagerFactory().getClass().toString());
        // Populate database.
        EmulatedDriver.emulate = false;
        EntityManager manager = getExecutor().createEntityManager();
        // Create schema using session from entity manager to create sequences correctly.
        try {
            // Create schema.
            new EmployeeTableCreator().replaceTables(((JpaEntityManager)manager).getServerSession());
        } catch (ClassCastException cast) {
            // Create using DatabaseSession if not EclipseLink JPA.
            new EmployeeTableCreator().replaceTables(getDatabaseSession());
        }

        manager.getTransaction().begin();

        for (int j = 0; j < 100; j++) {
            Employee empInsert = new Employee();
            empInsert.setFirstName("Brendan");
            empInsert.setMale();
            empInsert.setLastName("" + j + "");
            empInsert.setSalary(100000);
            EmploymentPeriod employmentPeriod = new EmploymentPeriod();
            java.sql.Date startDate = Helper.dateFromString("1901-12-31");
            java.sql.Date endDate = Helper.dateFromString("1895-01-01");
            employmentPeriod.setEndDate(startDate);
            employmentPeriod.setStartDate(endDate);
            empInsert.setPeriod(employmentPeriod);
            empInsert.setAddress(new Address());
            empInsert.getAddress().setCity("Nepean");
            empInsert.getAddress().setPostalCode("N5J2N5");
            empInsert.getAddress().setProvince("ON");
            empInsert.getAddress().setStreet("1111 Mountain Blvd. Floor 13, suite " + j);
            empInsert.getAddress().setCountry("Canada");
            empInsert.addPhoneNumber(new PhoneNumber("Work Fax", "613", "2255943"));
            empInsert.addPhoneNumber(new PhoneNumber("Home", "613", "2224599"));
            manager.persist(empInsert);
        }

        for (int j = 0; j < 50; j++) {
            Project project = new SmallProject();
            project.setName("Tracker");
            manager.persist(project);
            project = new LargeProject();
            project.setName("Tracker");
            manager.persist(project);
        }

        manager.getTransaction().commit();
        manager.close();
        EmulatedDriver.emulate = true;
    }

    /**
     * Setup the JPA provider.
     */
    public void setupProvider() {
        // Configure provider to be EclipseLink.
        String providerClass = "org.eclipse.persistence.jpa.PersistenceProvider";
        PersistenceProvider provider = null;
        try {
            provider = (PersistenceProvider)Class.forName(providerClass).getConstructor().newInstance();
        } catch (Exception error) {
            throw new TestProblemException("Failed to create persistence provider.", error);
        }
        Map properties = getPersistenceProperties();
        getExecutor().setEntityManagerFactory(provider.createEntityManagerFactory("performance", properties));
    }

    /**
     * Build the persistence properties.
     */
    public Map getPersistenceProperties() {
        Map properties = new HashMap();

        // For DataSource testing.
        //properties.put("jakarta.persistence.nonJtaDataSource", "datasource");

        // For JSE testing.
        properties.put("eclipselink.jdbc.driver", getSession().getLogin().getDriverClassName());
        properties.put("eclipselink.jdbc.url", getSession().getLogin().getConnectionString());
        properties.put("eclipselink.jdbc.user", getSession().getLogin().getUserName());
        properties.put("eclipselink.jdbc.password", getSession().getLogin().getPassword());

        /** For emulated connection testing.
        try {
            Class.forName(getSession().getLogin().getDriverClassName());
        } catch (Exception ignore) {}
        properties.put("eclipselink.jdbc.driver", "org.eclipse.persistence.testing.tests.performance.emulateddb.EmulatedDriver");
        properties.put("eclipselink.jdbc.url", "emulate:" + getSession().getLogin().getConnectionString());
        properties.put("eclipselink.jdbc.user", getSession().getLogin().getUserName());
        properties.put("eclipselink.jdbc.password", getSession().getLogin().getPassword());*/

        //properties.put("eclipselink.jdbc.batch-writing", "JDBC");
        //properties.put("eclipselink.persistence-context.close-on-commit", "true");
        properties.put("eclipselink.sequencing.default-sequence-to-table", "true");
        properties.put("eclipselink.logging.level", getSession().getSessionLog().getLevelString());
        // properties.put("eclipselink.jdbc.cache-statements", "true");
        // properties.put("eclipselink.cache.shared.default", "false");
        return properties;
    }

    static class PerformanceComparisonTestCaseWithTargetClass extends PerformanceComparisonTestCase {
        Class<?> targetClass;
        public PerformanceComparisonTestCaseWithTargetClass(Class<?> targetClass) {
            super();
            this.targetClass = targetClass;
        }
    }
    /**
     * Add a test to see if the provider is using change tracking.
     */
    public TestCase buildReadAllVsReadAllResultSet(Class<?> targetClass) {
        PerformanceComparisonTestCase test = new PerformanceComparisonTestCaseWithTargetClass(targetClass) {
            ReadAllQuery query;
            ReadAllQuery resultSetQuery;
            ReadAllQuery resultSetAccessQuery;

            @Override
            public void setup() {
                this.query = new ReadAllQuery(targetClass);
                this.resultSetQuery = new ReadAllQuery(targetClass);
                this.resultSetQuery.setIsResultSetOptimizedQuery(true);
                this.resultSetAccessQuery = new ReadAllQuery(targetClass);
                this.resultSetAccessQuery.setIsResultSetAccessOptimizedQuery(true);

                boolean isSimple = createEntityManager().unwrap(Session.class).getDescriptor(targetClass).getObjectBuilder().isSimple();

                if (!getTests().isEmpty()) {
                    return;
                }

                PerformanceComparisonTestCase test;
                if (isSimple) {
                    // Read from result set.
                    test = new PerformanceComparisonTestCase() {
                        @Override
                        public void test() {
                            EntityManager em = createEntityManager();
                            ((JpaEntityManager)em).createQuery(resultSetQuery).getResultList();
                            em.close();
                        }
                    };
                    test.setName("ReadAllResultSet");
                    addTest(test);
                }

                // Read with result set access optimization.
                test = new PerformanceComparisonTestCase() {
                    @Override
                    public void test() {
                        EntityManager em = createEntityManager();
                        ((JpaEntityManager)em).createQuery(resultSetAccessQuery).getResultList();
                        em.close();
                    }
                };
                test.setName("ReadAllResultSetAccess");
                addTest(test);

                // Read, no cache.
                test = new PerformanceComparisonTestCase() {
                    @Override
                    public void startTest() {
                        EntityManager em = createEntityManager();
                        createEntityManager().unwrap(Session.class).getDescriptor(targetClass).setCacheIsolation(CacheIsolationType.ISOLATED);
                        createEntityManager().unwrap(Session.class).getDescriptor(targetClass).setUnitOfWorkCacheIsolationLevel(ClassDescriptor.ISOLATE_CACHE_ALWAYS);
                        em.close();
                    }
                    @Override
                    public void test() {
                        EntityManager em = createEntityManager();
                        ((JpaEntityManager)em).createQuery(query).getResultList();
                        em.close();
                    }
                    @Override
                    public void endTest() {
                        EntityManager em = createEntityManager();
                        createEntityManager().unwrap(Session.class).getDescriptor(targetClass).setCacheIsolation(CacheIsolationType.SHARED);
                        createEntityManager().unwrap(Session.class).getDescriptor(targetClass).setUnitOfWorkCacheIsolationLevel(ClassDescriptor.ISOLATE_NEW_DATA_AFTER_TRANSACTION);
                        em.close();
                    }
                };
                test.setName("ReadAllNoCache");
                addTest(test);

                if (isSimple) {
                    // Read from result set, no cache.
                    test = new PerformanceComparisonTestCase() {
                        @Override
                        public void startTest() {
                            EntityManager em = createEntityManager();
                            createEntityManager().unwrap(Session.class).getDescriptor(targetClass).setCacheIsolation(CacheIsolationType.ISOLATED);
                            createEntityManager().unwrap(Session.class).getDescriptor(targetClass).setUnitOfWorkCacheIsolationLevel(ClassDescriptor.ISOLATE_CACHE_ALWAYS);
                            em.close();
                        }
                        @Override
                        public void test() {
                            EntityManager em = createEntityManager();
                            ((JpaEntityManager)em).createQuery(resultSetQuery).getResultList();
                            em.close();
                        }
                        @Override
                        public void endTest() {
                            EntityManager em = createEntityManager();
                            createEntityManager().unwrap(Session.class).getDescriptor(targetClass).setCacheIsolation(CacheIsolationType.SHARED);
                            createEntityManager().unwrap(Session.class).getDescriptor(targetClass).setUnitOfWorkCacheIsolationLevel(ClassDescriptor.ISOLATE_NEW_DATA_AFTER_TRANSACTION);
                            em.close();
                        }
                    };
                    test.setName("ReadAllResultSetNoCache");
                    addTest(test);
                }

                // Read with result set access optimization, no cache.
                test = new PerformanceComparisonTestCase() {
                    @Override
                    public void startTest() {
                        EntityManager em = createEntityManager();
                        createEntityManager().unwrap(Session.class).getDescriptor(targetClass).setCacheIsolation(CacheIsolationType.ISOLATED);
                        createEntityManager().unwrap(Session.class).getDescriptor(targetClass).setUnitOfWorkCacheIsolationLevel(ClassDescriptor.ISOLATE_CACHE_ALWAYS);
                        em.close();
                    }
                    @Override
                    public void test() {
                        EntityManager em = createEntityManager();
                        ((JpaEntityManager)em).createQuery(resultSetAccessQuery).getResultList();
                        em.close();
                    }
                    @Override
                    public void endTest() {
                        EntityManager em = createEntityManager();
                        createEntityManager().unwrap(Session.class).getDescriptor(targetClass).setCacheIsolation(CacheIsolationType.SHARED);
                        createEntityManager().unwrap(Session.class).getDescriptor(targetClass).setUnitOfWorkCacheIsolationLevel(ClassDescriptor.ISOLATE_NEW_DATA_AFTER_TRANSACTION);
                        em.close();
                    }
                };
                test.setName("ReadAllResultSetAccessNoCache");
                addTest(test);

                /**
                // Raw JDBC only.
                test = new PerformanceComparisonTestCase() {
                    public void test() throws Exception {
                        ServerSession session = ((EntityManagerFactoryImpl)getExecutor().getEntityManagerFactory()).getServerSession();
                        Accessor accessor = session.getReadConnectionPool().acquireConnection();
                        java.sql.Connection connection = accessor.getConnection();
                        java.sql.PreparedStatement statement = connection.prepareStatement("SELECT ADDRESS_ID, P_CODE, STREET, PROVINCE, COUNTRY, CITY FROM P_ADDRESS");
                        java.sql.ResultSet result = statement.executeQuery();
                        while (result.next()) {
                            result.getLong(1);
                            result.getString(2);
                            result.getString(3);
                            result.getString(4);
                            result.getString(5);
                            result.getString(6);
                        }
                        result.close();
                        statement.close();
                        session.getReadConnectionPool().releaseConnection(accessor);
                    }
                };
                test.setName("ReadAllRawJDBC");
                addTest(test);

                // Direct JDBC build objects.
                test = new PerformanceComparisonTestCase() {
                    public void test() throws Exception {
                        ServerSession session = ((EntityManagerFactoryImpl)getExecutor().getEntityManagerFactory()).getServerSession();
                        Accessor accessor = session.getReadConnectionPool().acquireConnection();
                        java.sql.Connection connection = accessor.getConnection();
                        java.sql.PreparedStatement statement = connection.prepareStatement("SELECT ADDRESS_ID, P_CODE, STREET, PROVINCE, COUNTRY, CITY FROM P_ADDRESS");
                        java.sql.ResultSet result = statement.executeQuery();
                        List addresses = new ArrayList();
                        while (result.next()) {
                            Address address = new Address();
                            address.setId(result.getLong(1));
                            address.setPostalCode(result.getString(2));
                            address.setStreet(result.getString(3));
                            address.setProvince(result.getString(4));
                            address.setCountry(result.getString(5));
                            address.setCity(result.getString(6));
                            addresses.add(address);
                        }
                        result.close();
                        statement.close();
                        session.getReadConnectionPool().releaseConnection(accessor);
                    }
                };
                test.setName("ReadAllORMJDBC");
                addTest(test);

                // Direct JDBC, unwrap EM, build objects.
                test = new PerformanceComparisonTestCase() {
                    public void test() throws Exception {
                        EntityManager em = createEntityManager();
                        java.sql.Connection connection = em.unwrap(java.sql.Connection.class);
                        java.sql.PreparedStatement statement = connection.prepareStatement("SELECT ADDRESS_ID, P_CODE, STREET, PROVINCE, COUNTRY, CITY FROM P_ADDRESS");
                        java.sql.ResultSet result = statement.executeQuery();
                        List addresses = new ArrayList();
                        while (result.next()) {
                            Address address = new Address();
                            address.setId(result.getLong(1));
                            address.setPostalCode(result.getString(2));
                            address.setStreet(result.getString(3));
                            address.setProvince(result.getString(4));
                            address.setCountry(result.getString(5));
                            address.setCity(result.getString(6));
                            addresses.add(address);
                        }
                        result.close();
                        statement.close();
                        em.close();
                    }
                };
                test.setName("ReadAllUnwrapJDBC");
                addTest(test);*/
            }

            @Override
            public void test() throws Exception {
                EntityManager em = createEntityManager();
                ((JpaEntityManager)em).createQuery(this.query).getResultList();
                em.close();
            }
        };
        test.setName("ReadAllVsReadAllResultSet(" + Helper.getShortClassName(targetClass) + ')');
        return test;
    }

    /**
     * Add a test to compare various batch fetching options.
     */
    public TestCase buildBatchFetchTest() {
        PerformanceComparisonTestCase test = new PerformanceComparisonTestCase() {
            @Override
            public void setup() {
                createEntityManager().unwrap(Session.class).getDescriptor(Employee.class).setCacheIsolation(CacheIsolationType.ISOLATED);
                createEntityManager().unwrap(Session.class).getDescriptor(Employee.class).setUnitOfWorkCacheIsolationLevel(ClassDescriptor.ISOLATE_CACHE_ALWAYS);
                createEntityManager().unwrap(Session.class).getDescriptor(Address.class).setCacheIsolation(CacheIsolationType.ISOLATED);
                createEntityManager().unwrap(Session.class).getDescriptor(Address.class).setUnitOfWorkCacheIsolationLevel(ClassDescriptor.ISOLATE_CACHE_ALWAYS);
                createEntityManager().unwrap(Session.class).getProject().setHasIsolatedClasses(true);

                if (!getTests().isEmpty()) {
                    return;
                }

                PerformanceComparisonTestCase test = new PerformanceComparisonTestCase() {
                    @Override
                    public void test() {
                        testFetchQuery("findAllEmployeesBatch");
                    }
                };
                test.setName("BatchFetchTest");
                addTest(test);

                test = new PerformanceComparisonTestCase() {
                    @Override
                    public void test() {
                        testFetchQuery("findAllEmployeesBatchEXISTS");
                    }
                };
                test.setName("EXISTSBatchFetchTest");
                addTest(test);

                test = new PerformanceComparisonTestCase() {
                    @Override
                    public void test() {
                        testFetchQuery("findAllEmployeesBatchIN");
                    }
                };
                test.setName("INBatchFetchTest");
                addTest(test);

                test = new PerformanceComparisonTestCase() {
                    @Override
                    public void test() {
                        testFetchQuery("findAllEmployeesJoin");
                    }
                };
                test.setName("JoinFetchTest");
                addTest(test);
            }

            @Override
            public void test() throws Exception {
                testFetchQuery("findAllEmployees");
            }

            @Override
            public void reset() {
                createEntityManager().unwrap(Session.class).getDescriptor(Employee.class).setCacheIsolation(CacheIsolationType.SHARED);
                createEntityManager().unwrap(Session.class).getDescriptor(Employee.class).setUnitOfWorkCacheIsolationLevel(ClassDescriptor.ISOLATE_NEW_DATA_AFTER_TRANSACTION);
                createEntityManager().unwrap(Session.class).getDescriptor(Address.class).setCacheIsolation(CacheIsolationType.SHARED);
                createEntityManager().unwrap(Session.class).getDescriptor(Address.class).setUnitOfWorkCacheIsolationLevel(ClassDescriptor.ISOLATE_NEW_DATA_AFTER_TRANSACTION);
                createEntityManager().unwrap(Session.class).getProject().setHasIsolatedClasses(false);
            }

        };
        test.setName("BatchFetchTest");
        return test;
    }

    /**
     * Add a test to compare various batch fetching options.
     */
    public TestCase buildLoadTest() {
        PerformanceComparisonTestCase test = new PerformanceComparisonTestCase() {
            @Override
            public void setup() {

                if (!getTests().isEmpty()) {
                    return;
                }

                PerformanceComparisonTestCase test = new PerformanceComparisonTestCase() {
                    @Override
                    public void test() {
                        testQuery("findAllEmployeesLoad");
                        ((JpaCache)getExecutor().getEntityManagerFactory().getCache()).clear();
                    }
                };
                test.setName("LoadTest");
                addTest(test);

                test = new PerformanceComparisonTestCase() {
                    @Override
                    public void startTest() {
                        AbstractSession session = getExecutor().getEntityManagerFactory().createEntityManager().unwrap(AbstractSession.class);
                        ((ReadAllQuery)session.getQuery("findAllEmployeesLoad")).getLoadGroup().setIsConcurrent(true);
                        session.setIsConcurrent(true);
                    }

                    @Override
                    public void endTest() {
                        AbstractSession session = getExecutor().getEntityManagerFactory().createEntityManager().unwrap(AbstractSession.class);
                        ((ReadAllQuery)session.getQuery("findAllEmployeesLoad")).getLoadGroup().setIsConcurrent(false);
                        session.setIsConcurrent(false);
                    }

                    @Override
                    public void test() {
                        testQuery("findAllEmployeesLoad");
                        ((JpaCache)getExecutor().getEntityManagerFactory().getCache()).clear();
                    }
                };
                test.setName("ConcurrentLoadTest");
                addTest(test);

                test = new PerformanceComparisonTestCase() {
                    @Override
                    public void startTest() {
                        AbstractSession session = getExecutor().getEntityManagerFactory().createEntityManager().unwrap(AbstractSession.class);
                        session.setIsConcurrent(true);
                    }

                    @Override
                    public void endTest() {
                        AbstractSession session = getExecutor().getEntityManagerFactory().createEntityManager().unwrap(AbstractSession.class);
                        session.setIsConcurrent(false);
                    }

                    @Override
                    public void test() {
                        testQuery("findAllEmployees");
                        ((JpaCache)getExecutor().getEntityManagerFactory().getCache()).clear();
                    }
                };
                test.setName("ConcurrentReadTest");
                addTest(test);
            }

            @Override
            public void test() throws Exception {
                testQuery("findAllEmployees");
                ((JpaCache)getExecutor().getEntityManagerFactory().getCache()).clear();
            }

            @Override
            public void reset() {
            }

        };
        test.setName("LoadTest");
        return test;
    }

    /**
     * Execute the named query and traverse the results.
     */
    protected void testQuery(String query) {
        EntityManager em = getExecutor().createEntityManager();
        List<Employee> employees = em.createNamedQuery(query).getResultList();
        for (Employee employee : employees) {
            employee.toString();
        }
        em.close();
    }

    /**
     * Execute the named query and traverse the results.
     */
    protected void testFetchQuery(String query) {
        EntityManager em = getExecutor().createEntityManager();
        List<Employee> employees = em.createNamedQuery(query).getResultList();
        for (Employee employee : employees) {
            employee.getAddress().toString();
        }
        em.close();
    }

    /**
     * Execute the named query and traverse the results.
     */
    protected void testJPQL(String query) {
        EntityManager em = getExecutor().createEntityManager();
        em.createNamedQuery(query).getResultList().size();
        em.close();
    }

    /**
     * Add a test to compare various batch writing options.
     */
    public TestCase buildBatchWriteTest() {
        PerformanceComparisonTestCase test = new PerformanceComparisonTestCase() {
            int objects = 50;
            boolean originalCacheStatements;

            @Override
            public void setup() {
                originalCacheStatements = getExecutor().createEntityManager().unwrap(ServerSession.class).getLogin().shouldCacheAllStatements();
                getExecutor().createEntityManager().unwrap(ServerSession.class).getLogin().cacheAllStatements();

                if (!getTests().isEmpty()) {
                    getTests().clear();
                }

                PerformanceComparisonTestCase test = new PerformanceComparisonTestCase() {
                    @Override
                    public void test() {
                        EntityManager em = getExecutor().createEntityManager();
                        em.unwrap(ServerSession.class).getLogin().useBatchWriting();
                        try {
                            em.getTransaction().begin();
                            persistBatch(em);
                            em.getTransaction().commit();
                        } finally {
                            em.unwrap(ServerSession.class).getLogin().dontUseBatchWriting();
                            em.close();
                        }
                    }
                };
                test.setName("JDBCBatchTest");
                addTest(test);

                test = new PerformanceComparisonTestCase() {
                    @Override
                    public void test() {
                        EntityManager em = getExecutor().createEntityManager();
                        em.unwrap(ServerSession.class).getLogin().dontBindAllParameters();
                        try {
                            em.getTransaction().begin();
                            persistBatch(em);
                            em.getTransaction().commit();
                        } finally {
                            em.unwrap(ServerSession.class).getLogin().bindAllParameters();
                            em.close();
                        }
                    }
                };
                test.setName("DynamicSQLTest");
                addTest(test);

                test = new PerformanceComparisonTestCase() {
                    @Override
                    public void test() {
                        EntityManager em = getExecutor().createEntityManager();
                        em.unwrap(ServerSession.class).getLogin().dontCacheAllStatements();
                        try {
                            em.getTransaction().begin();
                            persistBatch(em);
                            em.getTransaction().commit();
                        } finally {
                            em.unwrap(ServerSession.class).getLogin().cacheAllStatements();
                            em.close();
                        }
                    }
                };
                test.setName("NoStatementCachingTest");
                addTest(test);

                test = new PerformanceComparisonTestCase() {
                    @Override
                    public void test() {
                        EntityManager em = getExecutor().createEntityManager();
                        em.unwrap(ServerSession.class).getLogin().useBatchWriting();
                        em.unwrap(ServerSession.class).getLogin().dontBindAllParameters();
                        try {
                            em.getTransaction().begin();
                            persistBatch(em);
                            em.getTransaction().commit();
                        } finally {
                            em.unwrap(ServerSession.class).getLogin().dontUseBatchWriting();
                            em.unwrap(ServerSession.class).getLogin().bindAllParameters();
                            em.close();
                        }
                    }
                };
                test.setName("DynamicBatchTest");
                addTest(test);

                test = new PerformanceComparisonTestCase() {
                    @Override
                    public void test() {
                        EntityManager em = getExecutor().createEntityManager();
                        em.unwrap(ServerSession.class).getLogin().useBatchWriting();
                        em.unwrap(ServerSession.class).getLogin().dontUseJDBCBatchWriting();
                        em.unwrap(ServerSession.class).getLogin().dontBindAllParameters();
                        try {
                            em.getTransaction().begin();
                            persistBatch(em);
                            em.getTransaction().commit();
                        } finally {
                            em.unwrap(ServerSession.class).getLogin().dontUseBatchWriting();
                            em.unwrap(ServerSession.class).getLogin().useJDBCBatchWriting();
                            em.unwrap(ServerSession.class).getLogin().bindAllParameters();
                            em.close();
                        }
                    }
                };
                test.setName("BufferedBatchTest");
                addTest(test);

                /*test = new PerformanceComparisonTestCase() {
                    public void test() {
                        EntityManager em = getExecutor().createEntityManager();
                        em.unwrap(ServerSession.class).getLogin().useBatchWriting();
                        DatabaseAccessor accessor =  null;
                        try {
                            em.getTransaction().begin();
                            persistBatch(em);
                            UnitOfWorkImpl uow = (UnitOfWorkImpl)em.unwrap(UnitOfWork.class);
                            uow.beginEarlyTransaction();
                            accessor = (DatabaseAccessor)uow.getAccessor();
                            accessor.setActiveBatchWritingMechanism(new DynamicParameterizedBatchWritingMechanism());
                            accessor.getActiveBatchWritingMechanism(uow.getParent()).setAccessor(accessor, uow.getParent());
                            em.getTransaction().commit();
                        } finally {
                            em.unwrap(ServerSession.class).getLogin().dontUseBatchWriting();
                            em.close();
                            if (accessor != null) {
                                accessor.setActiveBatchWritingMechanism(null);
                            }
                        }
                    }
                };
                test.setName("DynamicParameterizedBatchTest");
                addTest(test);

                test = new PerformanceComparisonTestCase() {
                    public void test() {
                        EntityManager em = getExecutor().createEntityManager();
                        em.unwrap(ServerSession.class).getLogin().useBatchWriting();
                        DatabaseAccessor accessor =  null;
                        try {
                            em.getTransaction().begin();
                            persistBatch(em);
                            UnitOfWorkImpl uow = (UnitOfWorkImpl)em.unwrap(UnitOfWork.class);
                            uow.beginEarlyTransaction();
                            accessor = (DatabaseAccessor)uow.getAccessor();
                            accessor.setActiveBatchWritingMechanism(new DynamicParameterizedHybridBatchWritingMechanism());
                            accessor.getActiveBatchWritingMechanism(uow.getParent()).setAccessor(accessor, uow.getParent());
                            em.getTransaction().commit();
                        } finally {
                            em.unwrap(ServerSession.class).getLogin().dontUseBatchWriting();
                            em.close();
                            if (accessor != null) {
                                accessor.setActiveBatchWritingMechanism(null);
                            }
                        }
                    }
                };
                test.setName("DynamicParameterizedHybridBatchTest");
                addTest(test);*/
            }

            @Override
            public void test() throws Exception {
                EntityManager em = getExecutor().createEntityManager();
                em.getTransaction().begin();
                persistBatch(em);
                em.getTransaction().commit();
                em.close();
            }

            public void persistBatch(EntityManager em) {
                for (int index = 0; index < this.objects; index++) {
                    Address address = new Address();
                    address.setStreet("100 Bank Street");
                    address.setProvince("ON");
                    address.setPostalCode("K2H8C5");
                    address.setCity("Ottawa");
                    address.setCountry("Canada");
                    em.persist(address);
                }
            }

            @Override
            public void reset() {
                EntityManager em = getExecutor().createEntityManager();
                em.getTransaction().begin();
                em.createQuery("Delete from Address a where a.street = '100 Bank Street'").executeUpdate();
                em.getTransaction().commit();
                em.close();
                if (!originalCacheStatements) {
                    getExecutor().createEntityManager().unwrap(ServerSession.class).getLogin().dontCacheAllStatements();
                }
            }

        };
        test.setName("BatchWriteTest");
        return test;
    }


    /**
     * Add a test to compare various batch writing options.
     */
    public TestCase buildBatchUpdateTest() {
        PerformanceComparisonTestCase test = new PerformanceComparisonTestCase() {
            boolean originalCacheStatements;

            @Override
            public void setup() {
                originalCacheStatements = getExecutor().createEntityManager().unwrap(ServerSession.class).getLogin().shouldCacheAllStatements();
                getExecutor().createEntityManager().unwrap(ServerSession.class).getLogin().cacheAllStatements();

                if (!getTests().isEmpty()) {
                    getTests().clear();
                }

                PerformanceComparisonTestCase test = new PerformanceComparisonTestCase() {
                    @Override
                    public void test() {
                        EntityManager em = getExecutor().createEntityManager();
                        em.unwrap(ServerSession.class).getLogin().useBatchWriting();
                        em.getTransaction().begin();
                        persistBatch(em);
                        em.getTransaction().commit();
                        em.unwrap(ServerSession.class).getLogin().dontUseBatchWriting();
                        em.close();
                    }
                };
                test.setName("JDBCBatchUpdateTest");
                addTest(test);

                test = new PerformanceComparisonTestCase() {
                    @Override
                    public void test() {
                        EntityManager em = getExecutor().createEntityManager();
                        em.unwrap(ServerSession.class).getLogin().useBatchWriting();
                        em.unwrap(ServerSession.class).getLogin().dontBindAllParameters();
                        em.getTransaction().begin();
                        persistBatch(em);
                        em.getTransaction().commit();
                        em.unwrap(ServerSession.class).getLogin().dontUseBatchWriting();
                        em.unwrap(ServerSession.class).getLogin().useJDBCBatchWriting();
                        em.unwrap(ServerSession.class).getLogin().bindAllParameters();
                        em.close();
                    }
                };
                test.setName("DynamicBatchUpdateTest");
                addTest(test);

                /*test = new PerformanceComparisonTestCase() {
                    public void test() {
                        EntityManager em = getExecutor().createEntityManager();
                        em.unwrap(ServerSession.class).getLogin().useBatchWriting();
                        em.getTransaction().begin();
                        persistBatch(em);
                        UnitOfWorkImpl uow = (UnitOfWorkImpl)em.unwrap(UnitOfWork.class);
                        uow.beginEarlyTransaction();
                        DatabaseAccessor accessor = (DatabaseAccessor)uow.getAccessor();
                        accessor.setActiveBatchWritingMechanism(new DynamicParameterizedBatchWritingMechanism());
                        accessor.getActiveBatchWritingMechanism(uow.getParent()).setAccessor(accessor, uow.getParent());
                        em.getTransaction().commit();
                        em.unwrap(ServerSession.class).getLogin().dontUseBatchWriting();
                        em.close();
                        accessor.setActiveBatchWritingMechanism(null);
                    }
                };
                test.setName("DynamicParameterizedBatchUpdateTest");
                addTest(test);

                test = new PerformanceComparisonTestCase() {
                    public void test() {
                        EntityManager em = getExecutor().createEntityManager();
                        em.unwrap(ServerSession.class).getLogin().useBatchWriting();
                        em.getTransaction().begin();
                        persistBatch(em);
                        UnitOfWorkImpl uow = (UnitOfWorkImpl)em.unwrap(UnitOfWork.class);
                        uow.beginEarlyTransaction();
                        DatabaseAccessor accessor = (DatabaseAccessor)uow.getAccessor();
                        accessor.setActiveBatchWritingMechanism(new DynamicParameterizedHybridBatchWritingMechanism());
                        accessor.getActiveBatchWritingMechanism(uow.getParent()).setAccessor(accessor, uow.getParent());
                        em.getTransaction().commit();
                        em.unwrap(ServerSession.class).getLogin().dontUseBatchWriting();
                        em.close();
                        accessor.setActiveBatchWritingMechanism(null);
                    }
                };
                test.setName("DynamicParameterizedHybridBatchUpdateTest");
                addTest(test);*/
            }

            @Override
            public void test() throws Exception {
                EntityManager em = getExecutor().createEntityManager();
                em.getTransaction().begin();
                persistBatch(em);
                em.getTransaction().commit();
                em.close();
            }

            public void persistBatch(EntityManager em) {
                List<Employee> employees = em.createQuery("Select e from Employee e").getResultList();
                for (Employee employee : employees) {
                    if (employee.getGender().equals("Male")) {
                        employee.setFemale();
                    } else {
                        employee.setMale();
                    }
                }
            }

            @Override
            public void reset() {
                if (!originalCacheStatements) {
                    getExecutor().createEntityManager().unwrap(ServerSession.class).getLogin().dontCacheAllStatements();
                }
            }

        };
        test.setName("BatchUpdateTest");
        return test;
    }

    /**
     * Useful for side-by-side profiling regular vs ResultSet Access optimization.
     */
    static class ResultSetSideBySideTest extends TestCase {
        Class<?> targetClass;
        boolean withCache;
        ReadAllQuery query;
        ReadAllQuery resultSetQuery;
        int n = 1000;
        long time0;
        long time1;
        long time0square;
        long time1square;
        public ResultSetSideBySideTest(Class<?> targetClass, boolean withCache) {
            super();
            this.targetClass = targetClass;
            this.withCache = withCache;
            setName("ResultSetOptimizationSideBySideTest(" + Helper.getShortClassName(targetClass) + ')' + (withCache ? " CACHE" : " NO CACHE"));
        }

        @Override
        protected void setup() {
            this.query = new ReadAllQuery(targetClass);
            this.query.setIsResultSetAccessOptimizedQuery(false);
            this.resultSetQuery = new ReadAllQuery(targetClass);
            this.resultSetQuery.setIsResultSetAccessOptimizedQuery(true);
            if (!withCache) {
                createEntityManager().unwrap(Session.class).getDescriptor(targetClass).setCacheIsolation(CacheIsolationType.ISOLATED);
                createEntityManager().unwrap(Session.class).getDescriptor(targetClass).setUnitOfWorkCacheIsolationLevel(ClassDescriptor.ISOLATE_CACHE_ALWAYS);
            }
            time0 = 0;
            time1 = 0;
            time0square = 0;
            time1square = 0;
        }

        @Override
        protected void test() {
            for (int i=0; i < n; i++) {
                long testTime0 = test0();
                long testTime1 = test1();
                if (testTime0 != 0l) {
                    time0 += testTime0;
                    time0square += testTime0 * testTime0;
                }
                if (testTime1 != 0l) {
                    time1 += testTime1;
                    time1square += testTime1 * testTime1;
                }
            }
            System.out.println(getName());
            System.out.println("No optimization time:");
            System.out.println(time0 / 1000000);
            System.out.println("Mean per test:");
            System.out.println((double) time0 / (n * 1000000));
            System.out.println("std dev:");
            System.out.println(Math.sqrt((double) time0square / n - (double) (time0 / n) * (time0 / n)) / 1000000);
            System.out.println("zero time tests:");
            System.out.println("ResultSet optimization time:");
            System.out.println(time1 / 1000000);
            System.out.println("Mean per test:");
            System.out.println((double) time1 / (n * 1000000));
            System.out.println("std dev:");
            System.out.println(Math.sqrt((double) time1square / n - (double) (time1 / n) * (time1 / n)) / 1000000);
            System.out.println("zero time tests:");
            System.out.println("No Optimization - Optimization:");
            System.out.println((time0 - time1) / 1000000);
        }

        long test0() {
            EntityManager em = createEntityManager();
            long timeStart = System.nanoTime();
            List result = ((JpaEntityManager)em).createQuery(query).getResultList();
            long testTime = System.nanoTime() - timeStart;
            assertTrue(result.size() == 100);
            em.close();
            return testTime;
        }

        long test1() {
            EntityManager em = createEntityManager();
            long timeStart = System.nanoTime();
            List result = ((JpaEntityManager)em).createQuery(resultSetQuery).getResultList();
            long testTime = System.nanoTime() - timeStart;
            assertTrue(result.size() == 100);
            em.close();
            return testTime;
        }

        @Override
        public void reset() {
            if (!withCache) {
                createEntityManager().unwrap(Session.class).getDescriptor(targetClass).setCacheIsolation(CacheIsolationType.SHARED);
                createEntityManager().unwrap(Session.class).getDescriptor(targetClass).setUnitOfWorkCacheIsolationLevel(ClassDescriptor.ISOLATE_NEW_DATA_AFTER_TRANSACTION);
            }
        }
    }
}
