/*
 * 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:
//     July 22, 2009-2.0 Chris Delahunt
//       - TODO Bug#: Bug Description
package org.eclipse.persistence.testing.tests.jpa.criteria;

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import java.util.Iterator;

import org.junit.Assert;
import junit.framework.Test;
import junit.framework.TestSuite;

import jakarta.persistence.Query;
import jakarta.persistence.EntityManager;
import jakarta.persistence.Tuple;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Join;
import jakarta.persistence.criteria.JoinType;
import jakarta.persistence.criteria.ParameterExpression;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.Root;
import jakarta.persistence.criteria.Subquery;
import jakarta.persistence.metamodel.EntityType;

import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.expressions.ExpressionBuilder;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.mappings.DirectToFieldMapping;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.queries.ReportQuery;
import org.eclipse.persistence.queries.ReportQueryResult;
import org.eclipse.persistence.testing.models.jpa.advanced.EmployeePopulator;
import org.eclipse.persistence.testing.framework.junit.JUnitTestCase;
import org.eclipse.persistence.sessions.DatabaseSession;
import org.eclipse.persistence.testing.models.jpa.advanced.Address;
import org.eclipse.persistence.testing.models.jpa.advanced.AdvancedTableCreator;
import org.eclipse.persistence.testing.models.jpa.advanced.Employee;
import org.eclipse.persistence.testing.models.jpa.advanced.Project;
import org.eclipse.persistence.testing.models.jpa.advanced.PhoneNumber;

import org.eclipse.persistence.testing.tests.jpa.advanced.DataHolder;
import org.eclipse.persistence.testing.tests.jpa.jpql.*;

/**
 * <p>
 * <b>Purpose</b>: Test Unit Criteria API functionality.
 * <p>
 * <b>Description</b>: This class creates a test suite, initializes the database
 * and adds tests to the suite.
 * <p>
 * <b>Responsibilities</b>:
 * <ul>
 * <li> Run tests for Criteria API functionality
 * </ul>
 * @see org.eclipse.persistence.testing.models.jpa.advanced.EmployeePopulator
 * @see JUnitDomainObjectComparer
 * @see JUnitJPQLUnitTestSuite
 */

//This test suite demonstrates the bug 4616218, waiting for bug fix
public class JUnitCriteriaUnitTestSuite extends JUnitTestCase
{
  static JUnitDomainObjectComparer comparer;

  public JUnitCriteriaUnitTestSuite()
  {
      super();
  }

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

  //This method is run at the end of EVERY test case method
  @Override
  public void tearDown()
  {
      clearCache();
  }

  //This suite contains all tests contained in this class
  public static Test suite()
  {
    TestSuite suite = new TestSuite();
    suite.setName("JUnitCriteriaUnitTestSuite");
    suite.addTest(new JUnitCriteriaUnitTestSuite("testSetup"));
    suite.addTest(new JUnitCriteriaUnitTestSuite("testExistWithJoin"));
    suite.addTest(new JUnitCriteriaUnitTestSuite("testSelectPhoneNumberAreaCode"));
    suite.addTest(new JUnitCriteriaUnitTestSuite("testSelectPhoneNumberAreaCodeWithEmployee"));
    suite.addTest(new JUnitCriteriaUnitTestSuite("testSelectPhoneNumberNumberWithEmployeeWithExplicitJoin"));
    suite.addTest(new JUnitCriteriaUnitTestSuite("testSelectPhoneNumberNumberWithEmployeeWithFirstNameFirst"));
    suite.addTest(new JUnitCriteriaUnitTestSuite("testSelectEmployeeWithSameParameterUsedMultipleTimes"));
    suite.addTest(new JUnitCriteriaUnitTestSuite("testOuterJoinOnOneToOne"));
    suite.addTest(new JUnitCriteriaUnitTestSuite("testOuterJoinPolymorphic"));
    suite.addTest(new JUnitCriteriaUnitTestSuite("testFirstResult"));
    suite.addTest(new JUnitCriteriaUnitTestSuite("testInvertedSelectionCriteriaNullPK"));
    suite.addTest(new JUnitCriteriaUnitTestSuite("testInvertedSelectionCriteriaInvalidQueryKey"));
    suite.addTest(new JUnitCriteriaUnitTestSuite("testMaxAndFirstResultsOnDataQuery"));
    suite.addTest(new JUnitCriteriaUnitTestSuite("testMaxAndFirstResultsOnDataQueryWithGroupBy"));
    suite.addTest(new JUnitCriteriaUnitTestSuite("testMaxAndFirstResultsOnObjectQueryOnInheritanceRoot"));
    suite.addTest(new JUnitCriteriaUnitTestSuite("testDistinctSelectForEmployeeWithNullAddress"));
    suite.addTest(new JUnitCriteriaUnitTestSuite("testConstructorWithFunctionParameters"));
    suite.addTest(new JUnitCriteriaUnitTestSuite("testNonExistentConstructorCriteriaQuery"));
    suite.addTest(new JUnitCriteriaUnitTestSuite("testIsNullAndIsNotNull"));
    suite.addTest(new JUnitCriteriaUnitTestSuite("testIsNullOrIsNull"));

    return suite;
  }

    /**
     * The setup is done as a test, both to record its failure, and to allow execution in the server.
     */
    public void testSetup() {
        clearCache();
        //get session to start setup
        DatabaseSession session = JUnitTestCase.getServerSession();

        //create a new EmployeePopulator
        EmployeePopulator employeePopulator = new EmployeePopulator();

        new AdvancedTableCreator().replaceTables(session);

        //initialize the global comparer object
        comparer = new JUnitDomainObjectComparer();

        //set the session for the comparer to use
        comparer.setSession((AbstractSession)session.getActiveSession());

        //Populate the tables
        employeePopulator.buildExamples();

        //Persist the examples in the database
        employeePopulator.persistExample(session);
    }

    public Vector getAttributeFromAll(String attributeName, Vector objects, Class<?> referenceClass) {
        ClassDescriptor descriptor = getServerSession().getClassDescriptor(referenceClass);
        DirectToFieldMapping mapping = (DirectToFieldMapping)descriptor.getMappingForAttributeName(attributeName);

        Vector attributes = new Vector();
        Object currentObject;
        for(int i = 0; i < objects.size(); i++) {
            currentObject = objects.elementAt(i);
            if(currentObject.getClass() == ReportQueryResult.class) {
                attributes.addElement(
                    ((ReportQueryResult)currentObject).get(attributeName));
            } else {
                attributes.addElement(
                    mapping.getAttributeValueFromObject(currentObject));
            }
        }
        return attributes;
    }

    public void testFirstResult(){
        EntityManager em = createEntityManager();
        beginTransaction(em);
        try{
            clearCache();

            //SELECT OBJECT(employee) FROM Employee employee WHERE employee.firstName = :firstname
            CriteriaBuilder qb = em.getCriteriaBuilder();
            CriteriaQuery<Employee> cq = qb.createQuery(Employee.class);
            Root<Employee> from = cq.from(Employee.class);
            cq.where(qb.equal(from.get("firstName"), qb.parameter(String.class, "firstname")));
            Query query = em.createQuery(cq);

            List initialList = query.setParameter("firstname", "Nancy").setFirstResult(0).getResultList();

            List secondList = query.setParameter("firstname", "Nancy").setFirstResult(1).getResultList();

            Iterator i = initialList.iterator();
            while (i.hasNext()){
                assertTrue("Employee with incorrect name returned on first query.", ((Employee)i.next()).getFirstName().equals("Nancy"));
            }
            i = secondList.iterator();
            while (i.hasNext()){
                assertTrue("Employee with incorrect name returned on second query.", ((Employee)i.next()).getFirstName().equals("Nancy"));
            }
        } finally {
            rollbackTransaction(em);
            closeEntityManager(em);
        }
    }

    //done upto here
    public void testOuterJoinOnOneToOne(){
        EntityManager em = createEntityManager();
        clearCache();
        beginTransaction(em);
        //"SELECT e from Employee e JOIN e.address a"
        CriteriaBuilder qb = em.getCriteriaBuilder();
        CriteriaQuery<Employee> cq = qb.createQuery(Employee.class);
        cq.from(Employee.class).join("address");
        cq.distinct(true);
        int initialSize = em.createQuery(cq).getResultList().size();

        Employee emp = new Employee();
        emp.setFirstName("Steve");
        emp.setLastName("Harp");
        em.persist(emp);
        em.flush();
        //"SELECT e from Employee e LEFT OUTER JOIN e.address a"
        qb = em.getCriteriaBuilder();
        cq = qb.createQuery(Employee.class);
        cq.from(Employee.class).join("address", JoinType.LEFT);
        cq.distinct(true);

        List<Employee> result = em.createQuery(cq).getResultList();


        assertTrue("Outer join was not properly added to the query", initialSize + 1 == result.size());
        rollbackTransaction(em);
    }

    public void testOuterJoinPolymorphic(){
        EntityManager em = createEntityManager();
        beginTransaction(em);
        try{
            clearCache();
            List resultList = null;
            try{
                resultList = em.createQuery(em.getCriteriaBuilder().createQuery(Project.class)).getResultList();
            } catch (Exception exception){
                fail("Exception caught while executing polymorphic query.  This may mean that outer join is not working correctly on your database platfrom: " + exception.toString());
            }
            assertTrue("Incorrect number of projects returned.", resultList.size() == 15);
        } finally {
            rollbackTransaction(em);
            closeEntityManager(em);
        }
    }

  //This test case demonstrates the bug 4616218
  public void testSelectPhoneNumberAreaCode()
  {

        ExpressionBuilder employeeBuilder = new ExpressionBuilder();
        Expression phones = employeeBuilder.anyOf("phoneNumbers");
        Expression whereClause = phones.get("areaCode").equal("613");

        ReportQuery rq = new ReportQuery();
        rq.setSelectionCriteria(whereClause);
        rq.addAttribute("areaCode", new ExpressionBuilder().anyOf("phoneNumbers").get("areaCode"));
        rq.setReferenceClass(Employee.class);
        rq.dontUseDistinct(); // distinct no longer used on joins in JPQL for gf bug 1395
        EntityManager em = createEntityManager();
        beginTransaction(em);
        try{
            Vector expectedResult = getAttributeFromAll("areaCode", (Vector)getServerSession().executeQuery(rq),Employee.class);
            clearCache();

           //List result = em.createQuery("SELECT phone.areaCode FROM Employee employee, IN (employee.phoneNumbers) phone " +
           //    "WHERE phone.areaCode = \"613\"").getResultList();
           CriteriaBuilder qb = em.getCriteriaBuilder();
           CriteriaQuery<String> cq = qb.createQuery(String.class);
           Root<Employee> root = cq.from(Employee.class);
           Join<Object, Object> phone = root.join("phoneNumbers");
           cq.select(phone.get("areaCode"));
           cq.where(qb.equal(phone.get("areaCode"), "613"));
           List<String> result = em.createQuery(cq).getResultList();

           Assert.assertTrue("SimpleSelectPhoneNumberAreaCode test failed !", comparer.compareObjects(result,expectedResult));
        } finally {
            rollbackTransaction(em);
            closeEntityManager(em);
        }
  }

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

      List expected = em.createQuery("SELECT c FROM Employee c WHERE NOT EXISTS (SELECT o1 FROM c.phoneNumbers o1)").getResultList();
      beginTransaction(em);
      try {
          CriteriaBuilder qbuilder = em.getCriteriaBuilder();
          CriteriaQuery<Employee> cquery =qbuilder.createQuery(Employee.class);
           Root<Employee> customer = cquery.from(Employee.class);
           cquery.select(customer);

           Subquery<PhoneNumber> sq = cquery.subquery(PhoneNumber.class);
           // correlate subquery root to root of main query:
           Root<Employee> sqc = sq.correlate(customer);
           Join<Employee, PhoneNumber> sqo = sqc.join("phoneNumbers");
           sq.select(sqo);
           cquery.where(qbuilder.not(qbuilder.exists(sq)));
           List<Employee> result = em.createQuery(cquery).getResultList();
           Assert.assertTrue("testExistWithJoin test failed !", comparer.compareObjects(result,expected));
      } finally {
          rollbackTransaction(em);
          closeEntityManager(em);
      }



  }


    public void testSelectPhoneNumberAreaCodeWithEmployee()
    {
        EntityManager em = createEntityManager();
        beginTransaction(em);
        try{
            ExpressionBuilder employees = new ExpressionBuilder();
            Expression exp = employees.get("firstName").equal("Bob");
            exp = exp.and(employees.get("lastName").equal("Smith"));
            Employee emp = (Employee) getServerSession().readAllObjects(Employee.class, exp).firstElement();

            PhoneNumber phone = (PhoneNumber) ((Vector)emp.getPhoneNumbers()).firstElement();
            String areaCode = phone.getAreaCode();
            String firstName = emp.getFirstName();

            ExpressionBuilder employeeBuilder = new ExpressionBuilder();
            Expression phones = employeeBuilder.anyOf("phoneNumbers");
            Expression whereClause = phones.get("areaCode").equal(areaCode).and(
            phones.get("owner").get("firstName").equal(firstName));

            ReportQuery rq = new ReportQuery();
            rq.setSelectionCriteria(whereClause);
            rq.addAttribute("areaCode", phones.get("areaCode"));
            rq.setReferenceClass(Employee.class);
            rq.dontMaintainCache();

            Vector expectedResult = getAttributeFromAll("areaCode", (Vector)getServerSession().executeQuery(rq),Employee.class);

            clearCache();

            //"SELECT phone.areaCode FROM Employee employee, IN (employee.phoneNumbers) phone " +
            //    "WHERE phone.areaCode = \"" + areaCode + "\" AND phone.owner.firstName = \"" + firstName + "\"";
            CriteriaBuilder qb = em.getCriteriaBuilder();
            CriteriaQuery<String> cq = qb.createQuery(String.class);
            Root<Employee> root = cq.from(Employee.class);
            Join<Object, Object> joinedPhone = root.join("phoneNumbers");
            cq.select(joinedPhone.get("areaCode"));
            cq.where(qb.and(qb.equal(joinedPhone.get("areaCode"), "613")), qb.equal(joinedPhone.get("owner").get("firstName"), firstName));
            List<String> result = em.createQuery(cq).getResultList();

            Assert.assertTrue("SimpleSelectPhoneNumberAreaCodeWithEmployee test failed !", comparer.compareObjects(result,expectedResult));
        } finally {
            rollbackTransaction(em);
            closeEntityManager(em);
        }
    }

    public void testSelectPhoneNumberNumberWithEmployeeWithExplicitJoin()
    {
        EntityManager em = createEntityManager();
        beginTransaction(em);
        try{
            ExpressionBuilder employees = new ExpressionBuilder();
            Expression exp = employees.get("firstName").equal("Bob");
            exp = exp.and(employees.get("lastName").equal("Smith"));
            Employee emp = (Employee) getServerSession().readAllObjects(Employee.class, exp).firstElement();

            PhoneNumber phone = (PhoneNumber) ((Vector)emp.getPhoneNumbers()).firstElement();
            String areaCode = phone.getAreaCode();
            String firstName = emp.getFirstName();

            ExpressionBuilder employeeBuilder = new ExpressionBuilder(Employee.class);
            Expression phones = employeeBuilder.anyOf("phoneNumbers");
            Expression whereClause = phones.get("areaCode").equal(areaCode).and(
                phones.get("owner").get("id").equal(employeeBuilder.get("id")).and(
                    employeeBuilder.get("firstName").equal(firstName)));


            ReportQuery rq = new ReportQuery();
            rq.addAttribute("number", new ExpressionBuilder().anyOf("phoneNumbers").get("number"));
            rq.setSelectionCriteria(whereClause);
            rq.setReferenceClass(Employee.class);

            Vector expectedResult = getAttributeFromAll("number", (Vector)getServerSession().executeQuery(rq),Employee.class);

            clearCache();

            //"SELECT phone.number FROM Employee employee, IN (employee.phoneNumbers) phone " +
            //    "WHERE phone.areaCode = \"" + areaCode + "\" AND (phone.owner.id = employee.id AND employee.firstName = \"" + firstName + "\")";
            CriteriaBuilder qb = em.getCriteriaBuilder();
            CriteriaQuery<String> cq = qb.createQuery(String.class);
            Root<Employee> root = cq.from(Employee.class);
            Join<Object, Object> joinedPhone = root.join("phoneNumbers");
            cq.select(joinedPhone.get("number"));
            //cq.where(qb.equal(joinedPhone.get("areaCode"), areaCode).add(qb.equal(joinedPhone.get("owner").get("id"), root.get("id"))).add(qb.equal(root.get("firstName"), firstName)));
            Predicate firstAnd = qb.and(qb.equal(joinedPhone.get("areaCode"), areaCode), qb.equal(joinedPhone.get("owner").get("id"), root.get("id")));
            cq.where(qb.and( firstAnd, qb.equal(root.get("firstName"), firstName)));
            List<String> result = em.createQuery(cq).getResultList();

            Assert.assertTrue("SimpleSelectPhoneNumberAreaCodeWithEmployee test failed !", comparer.compareObjects(result,expectedResult));
        } finally {
            rollbackTransaction(em);
            closeEntityManager(em);
        }
    }

    public void testSelectPhoneNumberNumberWithEmployeeWithFirstNameFirst()
    {
        EntityManager em = createEntityManager();
        beginTransaction(em);
        try{
            ExpressionBuilder employees = new ExpressionBuilder();
            Expression exp = employees.get("firstName").equal("Bob");
            exp = exp.and(employees.get("lastName").equal("Smith"));
            Employee emp = (Employee) getServerSession().readAllObjects(Employee.class, exp).firstElement();

            PhoneNumber phone = (PhoneNumber) ((Vector)emp.getPhoneNumbers()).firstElement();
            String areaCode = phone.getAreaCode();
            String firstName = emp.getFirstName();

            ExpressionBuilder employeeBuilder = new ExpressionBuilder();
            Expression phones = employeeBuilder.anyOf("phoneNumbers");
            Expression whereClause = phones.get("owner").get("firstName").equal(firstName).and(
                phones.get("areaCode").equal(areaCode));

            ReportQuery rq = new ReportQuery();
            rq.setSelectionCriteria(whereClause);
            rq.addAttribute("number", phones.get("number"));
            rq.setReferenceClass(Employee.class);

            Vector expectedResult = getAttributeFromAll("number", (Vector)getServerSession().executeQuery(rq),Employee.class);

            clearCache();

            //"SELECT phone.number FROM Employee employee, IN(employee.phoneNumbers) phone " +
            //    "WHERE phone.owner.firstName = \"" + firstName + "\" AND phone.areaCode = \"" + areaCode + "\"";
            CriteriaBuilder qb = em.getCriteriaBuilder();
            CriteriaQuery<String> cq = qb.createQuery(String.class);
            Root<Employee> root = cq.from(Employee.class);
            Join<Object, Object> joinedPhone = root.join("phoneNumbers");
            cq.select(joinedPhone.get("number"));
            Predicate firstNameEquality = qb.equal(joinedPhone.get("owner").get("firstName"), firstName);
            Predicate areaCodeEquality =qb.equal(joinedPhone.get("areaCode"), areaCode);
            cq.where( qb.and(firstNameEquality, areaCodeEquality) );
            List<String> result = em.createQuery(cq).getResultList();

            Assert.assertTrue("SimpleSelectPhoneNumberAreaCodeWithEmployee test failed !", comparer.compareObjects(result,expectedResult));
        } finally {
            rollbackTransaction(em);
            closeEntityManager(em);
        }
    }

    public void testSelectEmployeeWithSameParameterUsedMultipleTimes() {
        Exception exception = null;

        try {
            EntityManager em = createEntityManager();
            beginTransaction(em);
            try{
                //"SELECT emp FROM Employee emp WHERE emp.id > :param1 OR :param1 IS null";
                CriteriaBuilder qb = em.getCriteriaBuilder();
                CriteriaQuery<Employee> cq = qb.createQuery(Employee.class);
                Root<Employee> root = cq.from(Employee.class);
                ParameterExpression<Integer> param1 = qb.parameter(Integer.class);
                //need to cast to erase the type on the get("id") expression so it matches the type on param1
                cq.where(qb.or( qb.greaterThan(root.<Integer>get("id" ), param1), param1.isNull()) );

                em.createQuery(cq).setParameter(param1, 1).getResultList();
            } finally {
                rollbackTransaction(em);
                closeEntityManager(em);
            }
        } catch (Exception e) {
            exception = e;
        }

        Assert.assertNull("Exception was caught.", exception);
    }

    /**
     * Prior to the fix for GF 2333, the query in this test would a Null PK exception
     *
     */
    public void testInvertedSelectionCriteriaNullPK() {
        EntityManager em = createEntityManager();
        beginTransaction(em);
        try{
            //"SELECT e, p FROM Employee e, PhoneNumber p WHERE p.id = e.id AND e.firstName = 'Bob'"
            CriteriaBuilder qb = em.getCriteriaBuilder();
            CriteriaQuery<Tuple> cq = qb.createTupleQuery();
            Root<Employee> rootEmp = cq.from(Employee.class);
            Root<PhoneNumber> rootPhone = cq.from(PhoneNumber.class);
            cq.multiselect(rootEmp, rootPhone);
            cq.where(qb.and( qb.equal(rootPhone.get("id"), rootEmp.get("id")), qb.equal(rootEmp.get("firstName"), "Bob")) );

            em.createQuery(cq).getResultList();
        } finally {
            rollbackTransaction(em);
            closeEntityManager(em);
        }
    }

    /**
     * Tests fix for bug6070214 that using Oracle Rownum pagination with non-unique columns
     * throws an SQl exception.
     */
    public void testMaxAndFirstResultsOnDataQuery(){
        Exception exception = null;
        List resultList = null;
        EntityManager em = createEntityManager();
        beginTransaction(em);
        try{
            clearCache();
            //"SELECT e.id, m.id FROM Employee e LEFT OUTER JOIN e.manager m"
            CriteriaBuilder qb = em.getCriteriaBuilder();
            CriteriaQuery<Tuple> cq = qb.createTupleQuery();
            Root<Employee> rootEmp = cq.from(Employee.class);
            Join<Object, Object> joinedManager = rootEmp.join("manager", JoinType.LEFT);
            cq.multiselect(rootEmp.get("id"), joinedManager.get("id"));

            Query query = em.createQuery(cq);
            try {
                query.setFirstResult(1);
                query.setMaxResults(1);
                resultList = query.getResultList();
            } catch (Exception e) {
                logThrowable(exception);
                exception = e;
            }
            Assert.assertNull("Exception was caught: " + exception, exception);
            Assert.assertTrue("Incorrect number of results returned.  Expected 1, returned "+resultList.size(), resultList.size()==1);
        } finally {
            rollbackTransaction(em);
            closeEntityManager(em);
        }
    }

    /**
     * Tests fix for bug6070214 that using Oracle Rownum pagination with group by
     * throws an SQl exception.
     */
    public void testMaxAndFirstResultsOnDataQueryWithGroupBy() {
        Exception exception = null;
        List resultList = null;
        EntityManager em = createEntityManager();
        beginTransaction(em);
        try{
            clearCache();
            //"SELECT e.id FROM Employee e group by e.id"
            CriteriaBuilder qb = em.getCriteriaBuilder();
            CriteriaQuery<Integer> cq = qb.createQuery(Integer.class);
            Root<Employee> rootEmp = cq.from(Employee.class);
            Join<Object, Object> joinedManager = rootEmp.join("manager", JoinType.LEFT);
            cq.select(rootEmp.get("id"));

            Query query = em.createQuery(cq);
            try {
                query.setFirstResult(1);
                query.setMaxResults(1);
                resultList = query.getResultList();
            } catch (Exception e) {
                logThrowable(exception);
                exception = e;
            }
            Assert.assertNull("Exception was caught: " + exception, exception);
            Assert.assertTrue("Incorrect number of results returned.  Expected 1, returned "+resultList.size(), resultList.size()==1);
        } finally {
            rollbackTransaction(em);
            closeEntityManager(em);
        }
    }

    /**
     * Tests fix for bug 253258 that using filtering using MaxResults/FirstResult returns
     * the correct number of results on an inheritance root class.
     */
    public void testMaxAndFirstResultsOnObjectQueryOnInheritanceRoot() {
        Exception exception = null;
        List resultList = null;
        EntityManager em = createEntityManager();
        beginTransaction(em);
        try{
            clearCache();
            //"SELECT p FROM Project p"
            CriteriaBuilder qb = em.getCriteriaBuilder();
            CriteriaQuery<Project> cq = qb.createQuery(Project.class);

            Query query = em.createQuery(cq);
            try {
                query.setFirstResult(6);
                query.setMaxResults(1);
                resultList = query.getResultList();
            } catch (Exception e) {
                exception = e;
                logThrowable(exception);
            }
            Assert.assertNull("Exception was caught.", exception);
            Assert.assertTrue("Incorrect number of results returned.  Expected 1, returned "+resultList.size(), resultList.size()==1);
        } finally {
            rollbackTransaction(em);
            closeEntityManager(em);
        }
    }

    /**
     * Prior to the fix for GF 2333, the query in this test would generate an invalid query key exception
     *
     */
    public void testInvertedSelectionCriteriaInvalidQueryKey(){
        Exception exception = null;
        try {
            EntityManager em = createEntityManager();
            beginTransaction(em);
            try{
                //"select e, a from Employee e, Address a where a.city = 'Ottawa' and e.address.country = a.country"
                CriteriaBuilder qb = em.getCriteriaBuilder();
                CriteriaQuery<Tuple> cq = qb.createTupleQuery();
                Root<Employee> rootEmp = cq.from(Employee.class);
                Root<Address> rootAddress = cq.from(Address.class);
                cq.multiselect(rootEmp, rootAddress);
                cq.where(qb.and( qb.equal(rootAddress.get("city"), "Ottawa"), qb.equal(rootEmp.get("address").get("country"), rootAddress.get("country"))));

                List<Tuple> resultList =  em.createQuery(cq).getResultList();
            } finally {
                rollbackTransaction(em);
                closeEntityManager(em);
            }
        } catch (Exception e) {
            logThrowable(e);
            exception = e;
        }

        Assert.assertNull("Exception was caught.", exception);
    }

    /*
     * For GF3233, Distinct process fail with NPE when relationship has NULL-valued target.
     */
    public void testDistinctSelectForEmployeeWithNullAddress(){
        EntityManager em = createEntityManager();
        try {
            beginTransaction(em);
            Employee emp = new Employee();
            emp.setFirstName("Dummy");
            emp.setLastName("Person");
            em.persist(emp);
            em.flush();
            //"SELECT DISTINCT e.address FROM Employee e"
            CriteriaBuilder qb = em.getCriteriaBuilder();
            CriteriaQuery<Object> cq = qb.createQuery();
            Root<Employee> rootEmp = cq.from(Employee.class);
            cq.select(rootEmp.get("address"));
            cq.distinct(true);

            List<Object> resultList =  em.createQuery(cq).getResultList();
        }finally{
            rollbackTransaction(em);
        }
    }

    /*
     * For 297385, Constructor expressions are not working with function arguments.
     */
    public void testConstructorWithFunctionParameters(){
        EntityManager em = createEntityManager();
        try {
            beginTransaction(em);
            Employee emp = new Employee();
            emp.setFirstName("Very");
            emp.setLastName("Dumb");
            emp.setSalary(-100);//Employee pays to work?
            em.persist(emp);
            em.flush();
            CriteriaBuilder qb = em.getCriteriaBuilder();
            // Test constructor DataHolder(int)
            CriteriaQuery<?> cq = qb.createQuery(DataHolder.class);
            Root<Employee> from = cq.from(Employee.class);
            EntityType<Employee> Emp_ = em.getMetamodel().entity(Employee.class);
            cq.multiselect( qb.min(from.get(Emp_.getSingularAttribute("salary", int.class))));
            List<?> resultList =  em.createQuery(cq).getResultList();
            Object resultObject = resultList.get(0);
            assertTrue("constructor expression test expected DataHolder object, got " + resultObject,(resultObject instanceof DataHolder));
            assertEquals("Expected DataHolder to contain int value of -100, Got :" + resultObject, -100, ((DataHolder)resultObject).getPrimitiveInt());
        } finally {
            rollbackTransaction(em);
        }
    }

    public void testNonExistentConstructorCriteriaQuery(){
        Exception expectedException = null;
        EntityManager em = createEntityManager();
        CriteriaBuilder qb = em.getCriteriaBuilder();
            // Test constructor object:
        CriteriaQuery<?> cq = qb.createQuery(DataHolder.class);
        Root<Employee> from = cq.from(Employee.class);
        EntityType<Employee> Emp_ = em.getMetamodel().entity(Employee.class);
            //IllegalArgumentException expected from multiselect since DataHolder(String) does not exist
        try{
            cq.multiselect( from.get(Emp_.getSingularAttribute("lastName", String.class)));
            Query query = em.createQuery(cq);
        } catch (IllegalArgumentException exception){
            expectedException = exception;
        }
        assertNotNull("Expected IllegalArgumentException not thrown when using a non-existing constructor", expectedException);
    }

    public void testIsNullAndIsNotNull(){
        EntityManager em = createEntityManager();
        beginTransaction(em);
        try {
        Employee emp = (Employee)em.createQuery("select e from Employee e where e.firstName = 'John' and e.lastName = 'Way'").getSingleResult();
        emp.setFirstName(null);
        emp = (Employee)em.createQuery("select e from Employee e where e.firstName = 'Charles' and e.lastName = 'Chanley'").getSingleResult();
        emp.setFirstName(null);
        emp.setLastName(null);
        em.flush();
        CriteriaBuilder qb = em.getCriteriaBuilder();
        CriteriaQuery<?> cq = qb.createQuery(Employee.class);
        Root<Employee> from = cq.from(Employee.class);
        EntityType<Employee> Emp_ = em.getMetamodel().entity(Employee.class);

        List<Predicate> criteriaList = new ArrayList<Predicate>();
        criteriaList.add(qb.isNotNull(from.get(Emp_.getSingularAttribute("lastName", String.class))));
        criteriaList.add(qb.isNull(from.get(Emp_.getSingularAttribute("firstName", String.class))));
        Predicate criteria = qb.and(criteriaList.toArray(new Predicate[0]));
        cq.where(criteria);
        Query query = em.createQuery(cq);
        List results = query.getResultList();
        assertTrue(results.size() == 1);
        emp = (Employee)results.get(0);
        assertTrue(emp.getFirstName() == null);
        assertTrue(emp.getLastName() != null);
        } finally {
        rollbackTransaction(em);
        }
    }

    public void testIsNullOrIsNull(){
        EntityManager em = createEntityManager();
        beginTransaction(em);
        Employee emp = (Employee)em.createQuery("select e from Employee e where e.firstName = 'John' and e.lastName = 'Way'").getSingleResult();
        emp.setFirstName(null);
        emp = (Employee)em.createQuery("select e from Employee e where e.firstName = 'Charles' and e.lastName = 'Chanley'").getSingleResult();
        emp.setLastName(null);
        em.flush();
        CriteriaBuilder qb = em.getCriteriaBuilder();
        CriteriaQuery<?> cq = qb.createQuery(Employee.class);
        Root<Employee> from = cq.from(Employee.class);
        EntityType<Employee> Emp_ = em.getMetamodel().entity(Employee.class);

        List<Predicate> criteriaList = new ArrayList<Predicate>();
        criteriaList.add(qb.isNull(from.get(Emp_.getSingularAttribute("lastName", String.class))));
        criteriaList.add(qb.isNull(from.get(Emp_.getSingularAttribute("firstName", String.class))));
        Predicate criteria = qb.or(criteriaList.toArray(new Predicate[0]));
        cq.where(criteria);
        Query query = em.createQuery(cq);
        List results = query.getResultList();
        assertTrue(results.size() == 2);
        rollbackTransaction(em);
    }
}
