Bug 579327: ParameterExpression in CriteriaBuilder.isNull() doesn't register

Signed-off-by: Will Dazey <dazeydev.3@gmail.com>
diff --git a/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/query/TestQueryIsNull.java b/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/query/TestQueryIsNull.java
new file mode 100644
index 0000000..f0eea2a
--- /dev/null
+++ b/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/query/TestQueryIsNull.java
@@ -0,0 +1,321 @@
+/*
+ * Copyright (c) 2022 IBM Corporation, Oracle, and/or 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:
+//     IBM - Bug 579327: ParameterExpression in CriteriaBuilder.isNull() doesn't register
+package org.eclipse.persistence.jpa.test.query;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.List;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.EntityManagerFactory;
+import jakarta.persistence.TypedQuery;
+import jakarta.persistence.criteria.CriteriaBuilder;
+import jakarta.persistence.criteria.CriteriaQuery;
+import jakarta.persistence.criteria.ParameterExpression;
+import jakarta.persistence.criteria.Root;
+
+import org.eclipse.persistence.jpa.test.framework.DDLGen;
+import org.eclipse.persistence.jpa.test.framework.Emf;
+import org.eclipse.persistence.jpa.test.framework.EmfRunner;
+import org.eclipse.persistence.jpa.test.framework.Property;
+import org.eclipse.persistence.jpa.test.query.model.EntityTbl01;
+import org.eclipse.persistence.jpa.test.query.model.EntityTbl01_;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(EmfRunner.class)
+public class TestQueryIsNull {
+    @Emf(createTables = DDLGen.DROP_CREATE, classes = { EntityTbl01.class }, 
+            properties = { @Property(name="eclipselink.logging.level", value="FINE")})
+    private EntityManagerFactory emf;
+
+    private static boolean POPULATED = false;
+
+    @Test
+    public void testQueryIsNullLiterals1() {
+        if (emf == null)
+            return;
+
+        if(!POPULATED) 
+            populate();
+
+        EntityManager em = emf.createEntityManager();
+
+        try {
+            TypedQuery<String> query = em.createQuery(""
+                    + "SELECT t.itemString1 FROM EntityTbl01 t "
+                        + "WHERE 'HELLO' IS NULL", String.class);
+
+            List<String> dto01 = query.getResultList();
+            assertNotNull(dto01);
+            assertEquals(0, dto01.size());
+
+            // equivalent CriteriaBuilder
+            CriteriaBuilder cb = em.getCriteriaBuilder();
+            CriteriaQuery<String> cquery = cb.createQuery(String.class);
+            Root<EntityTbl01> root = cquery.from(EntityTbl01.class);
+            cquery.multiselect(root.get(EntityTbl01_.itemString1));
+
+            cquery.where(cb.isNull(cb.literal("HELLO")));
+
+            query = em.createQuery(cquery);
+            dto01 = query.getResultList();
+            assertNotNull(dto01);
+            assertEquals(0, dto01.size());
+
+            // equivalent, alternative CriteriaBuilder
+            CriteriaBuilder cb2 = em.getCriteriaBuilder();
+            CriteriaQuery<String> cquery2 = cb2.createQuery(String.class);
+            Root<EntityTbl01> root2 = cquery2.from(EntityTbl01.class);
+            cquery2.multiselect(root2.get(EntityTbl01_.itemString1));
+
+            cquery2.where(cb2.literal("HELLO").isNull());
+
+            query = em.createQuery(cquery2);
+            dto01 = query.getResultList();
+            assertNotNull(dto01);
+            assertEquals(0, dto01.size());
+        } finally {
+            if (em.getTransaction().isActive()) {
+                em.getTransaction().rollback();
+            }
+            if(em.isOpen()) {
+                em.close();
+            }
+        }
+    }
+
+    @Test
+    public void testQueryIsNotNullLiterals1() {
+        if (emf == null)
+            return;
+
+        if(!POPULATED) 
+            populate();
+
+        EntityManager em = emf.createEntityManager();
+
+        try {
+            TypedQuery<String> query = em.createQuery(""
+                    + "SELECT t.itemString1 FROM EntityTbl01 t "
+                        + "WHERE 'HELLO' IS NOT NULL", String.class);
+
+            List<String> dto01 = query.getResultList();
+            assertNotNull(dto01);
+            assertEquals(4, dto01.size());
+
+            // equivalent CriteriaBuilder
+            CriteriaBuilder cb = em.getCriteriaBuilder();
+            CriteriaQuery<String> cquery = cb.createQuery(String.class);
+            Root<EntityTbl01> root = cquery.from(EntityTbl01.class);
+            cquery.multiselect(root.get(EntityTbl01_.itemString1));
+
+            cquery.where(cb.isNotNull(cb.literal("HELLO")));
+
+            query = em.createQuery(cquery);
+            dto01 = query.getResultList();
+            assertNotNull(dto01);
+            assertEquals(4, dto01.size());
+
+            // equivalent, alternative CriteriaBuilder
+            CriteriaBuilder cb2 = em.getCriteriaBuilder();
+            CriteriaQuery<String> cquery2 = cb2.createQuery(String.class);
+            Root<EntityTbl01> root2 = cquery2.from(EntityTbl01.class);
+            cquery2.multiselect(root2.get(EntityTbl01_.itemString1));
+
+            cquery2.where(cb2.literal("HELLO").isNotNull());
+
+            query = em.createQuery(cquery2);
+            dto01 = query.getResultList();
+            assertNotNull(dto01);
+            assertEquals(4, dto01.size());
+        } finally {
+            if (em.getTransaction().isActive()) {
+                em.getTransaction().rollback();
+            }
+            if(em.isOpen()) {
+                em.close();
+            }
+        }
+    }
+
+    @Test
+    public void testQueryIsNullParameters1() {
+        if (emf == null)
+            return;
+
+        if(!POPULATED) 
+            populate();
+
+        EntityManager em = emf.createEntityManager();
+
+        try {
+            TypedQuery<String> query = em.createQuery(""
+                    + "SELECT t.itemString1 FROM EntityTbl01 t "
+                        + "WHERE ?1 IS NULL", String.class);
+            query.setParameter(1, null);
+
+            List<String> dto01 = query.getResultList();
+            assertNotNull(dto01);
+            assertEquals(4, dto01.size());
+
+            // equivalent CriteriaBuilder
+            CriteriaBuilder cb = em.getCriteriaBuilder();
+            CriteriaQuery<String> cquery = cb.createQuery(String.class);
+            Root<EntityTbl01> root = cquery.from(EntityTbl01.class);
+            cquery.multiselect(root.get(EntityTbl01_.itemString1));
+
+            ParameterExpression<String> strParam1 = cb.parameter(String.class);
+            cquery.where(cb.isNull(strParam1));
+
+            query = em.createQuery(cquery);
+            query.setParameter(strParam1, null);
+            dto01 = query.getResultList();
+            assertNotNull(dto01);
+            assertEquals(4, dto01.size());
+
+            // equivalent, alternative CriteriaBuilder
+            CriteriaBuilder cb2 = em.getCriteriaBuilder();
+            CriteriaQuery<String> cquery2 = cb2.createQuery(String.class);
+            Root<EntityTbl01> root2 = cquery2.from(EntityTbl01.class);
+            cquery2.multiselect(root2.get(EntityTbl01_.itemString1));
+
+            ParameterExpression<String> strParam2 = cb.parameter(String.class);
+            cquery2.where(strParam2.isNull());
+
+            query = em.createQuery(cquery2);
+            query.setParameter(strParam2, null);
+            dto01 = query.getResultList();
+            assertNotNull(dto01);
+            assertEquals(4, dto01.size());
+        } finally {
+            if (em.getTransaction().isActive()) {
+                em.getTransaction().rollback();
+            }
+            if(em.isOpen()) {
+                em.close();
+            }
+        }
+    }
+
+    @Test
+    public void testQueryIsNotNullParameters1() {
+        if (emf == null)
+            return;
+
+        if(!POPULATED) 
+            populate();
+
+        EntityManager em = emf.createEntityManager();
+
+        try {
+            TypedQuery<String> query = em.createQuery(""
+                    + "SELECT t.itemString1 FROM EntityTbl01 t "
+                        + "WHERE ?1 IS NOT NULL", String.class);
+            query.setParameter(1, null);
+
+            List<String> dto01 = query.getResultList();
+            assertNotNull(dto01);
+            assertEquals(0, dto01.size());
+
+            // equivalent CriteriaBuilder
+            CriteriaBuilder cb = em.getCriteriaBuilder();
+            CriteriaQuery<String> cquery = cb.createQuery(String.class);
+            Root<EntityTbl01> root = cquery.from(EntityTbl01.class);
+            cquery.multiselect(root.get(EntityTbl01_.itemString1));
+
+            ParameterExpression<String> strParam1 = cb.parameter(String.class);
+            cquery.where(cb.isNotNull(strParam1));
+
+            query = em.createQuery(cquery);
+            query.setParameter(strParam1, null);
+            dto01 = query.getResultList();
+            assertNotNull(dto01);
+            assertEquals(0, dto01.size());
+
+            // equivalent, alternative CriteriaBuilder
+            CriteriaBuilder cb2 = em.getCriteriaBuilder();
+            CriteriaQuery<String> cquery2 = cb2.createQuery(String.class);
+            Root<EntityTbl01> root2 = cquery2.from(EntityTbl01.class);
+            cquery2.multiselect(root2.get(EntityTbl01_.itemString1));
+
+            ParameterExpression<String> strParam2 = cb.parameter(String.class);
+            cquery2.where(strParam2.isNotNull());
+
+            query = em.createQuery(cquery2);
+            query.setParameter(strParam2, null);
+            dto01 = query.getResultList();
+            assertNotNull(dto01);
+            assertEquals(0, dto01.size());
+        } finally {
+            if (em.getTransaction().isActive()) {
+                em.getTransaction().rollback();
+            }
+            if(em.isOpen()) {
+                em.close();
+            }
+        }
+    }
+
+    private void populate() {
+        EntityManager em = emf.createEntityManager();
+        try {
+            em.getTransaction().begin();
+
+            EntityTbl01 tbl1 = new EntityTbl01();
+            tbl1.setKeyString("Key50");
+            tbl1.setItemString1("A");
+            tbl1.setItemString2(null);
+            tbl1.setItemString3("C");
+            tbl1.setItemString4("D");
+            tbl1.setItemInteger1(3);
+            em.persist(tbl1);
+
+            EntityTbl01 tbl2 = new EntityTbl01();
+            tbl2.setKeyString("Key51");
+            tbl2.setItemString1("A");
+            tbl2.setItemString2("B");
+            tbl2.setItemString3("C");
+            tbl2.setItemString4(null);
+            tbl2.setItemInteger1(4);
+            em.persist(tbl2);
+
+            EntityTbl01 tbl3 = new EntityTbl01();
+            tbl3.setKeyString("Key52");
+            tbl3.setItemString1(null);
+            tbl3.setItemString2("B");
+            tbl3.setItemString3("C");
+            tbl3.setItemString4("D");
+            tbl3.setItemInteger1(3);
+            em.persist(tbl3);
+
+            EntityTbl01 tbl4 = new EntityTbl01();
+            tbl4.setKeyString("Key53");
+            tbl4.setItemString1("A");
+            tbl4.setItemString2("B");
+            tbl4.setItemString3("C");
+            tbl4.setItemString4(null);
+            tbl4.setItemInteger1(4);
+            em.persist(tbl4);
+
+            em.getTransaction().commit();
+
+            POPULATED = true;
+        } finally {
+            if(em.isOpen()) {
+                em.close();
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/querydef/CriteriaBuilderImpl.java b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/querydef/CriteriaBuilderImpl.java
index 9568729..dc8b8a5 100644
--- a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/querydef/CriteriaBuilderImpl.java
+++ b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/querydef/CriteriaBuilderImpl.java
@@ -82,7 +82,7 @@
      */
     @Override
     public CriteriaQuery<Object> createQuery(){
-        return new CriteriaQueryImpl(this.metamodel, ResultType.UNKNOWN, ClassConstants.OBJECT, this);
+        return new CriteriaQueryImpl<Object>(this.metamodel, ResultType.UNKNOWN, ClassConstants.OBJECT, this);
     }
 
     /**
@@ -126,7 +126,7 @@
      */
     @Override
     public CriteriaQuery<Tuple> createTupleQuery(){
-        return new CriteriaQueryImpl(this.metamodel, ResultType.TUPLE, Tuple.class, this);
+        return new CriteriaQueryImpl<Tuple>(this.metamodel, ResultType.TUPLE, Tuple.class, this);
     }
 
     /**
@@ -554,9 +554,7 @@
                 throw new IllegalArgumentException(ExceptionLocalization.buildMessage("PREDICATE_PASSED_TO_EVALUATION"));
             }
         }
-        List<Expression<?>> list = new ArrayList<>();
-        list.add(x);
-        return new CompoundExpressionImpl(this.metamodel, ((InternalSelection)x).getCurrentNode().equal(true), list, "equals");
+        return new CompoundExpressionImpl(this.metamodel, ((InternalSelection)x).getCurrentNode().equal(true), buildList(x), "equals");
     }
 
     /**
@@ -590,7 +588,7 @@
      */
     @Override
     public Predicate isNull(Expression<?> x){
-        return new PredicateImpl(this.metamodel, ((InternalSelection)x).getCurrentNode().isNull(), new ArrayList<>(), BooleanOperator.AND);
+        return new PredicateImpl(this.metamodel, ((InternalSelection)x).getCurrentNode().isNull(), buildList(x), BooleanOperator.AND);
     }
 
     /**
@@ -600,7 +598,7 @@
      */
     @Override
     public Predicate isNotNull(Expression<?> x){
-        return new PredicateImpl(this.metamodel, ((InternalSelection)x).getCurrentNode().notNull(),new ArrayList<>(), BooleanOperator.AND);
+        return new PredicateImpl(this.metamodel, ((InternalSelection)x).getCurrentNode().notNull(), buildList(x), BooleanOperator.AND);
     }
 
     // equality:
@@ -615,11 +613,7 @@
      */
     @Override
     public Predicate equal(Expression<?> x, Expression<?> y){
-
-        List<Expression<?>> list = new ArrayList<>();
-        list.add(x);
-        list.add(y);
-        return new CompoundExpressionImpl(this.metamodel, ((InternalSelection)x).getCurrentNode().equal(((InternalSelection)y).getCurrentNode()), list, "equals");
+        return new CompoundExpressionImpl(this.metamodel, ((InternalSelection)x).getCurrentNode().equal(((InternalSelection)y).getCurrentNode()), buildList(x, y), "equals");
     }
 
     /**
@@ -636,10 +630,7 @@
         if (((InternalSelection)x).getCurrentNode() == null || ((InternalSelection)y).getCurrentNode() == null){
             throw new IllegalArgumentException(ExceptionLocalization.buildMessage("OPERATOR_EXPRESSION_IS_CONJUNCTION"));
         }
-        List<Expression<?>> list = new ArrayList<>();
-        list.add(x);
-        list.add(y);
-        return new CompoundExpressionImpl(this.metamodel, ((InternalSelection)x).getCurrentNode().notEqual(((InternalSelection)y).getCurrentNode()), list, "not equal");
+        return new CompoundExpressionImpl(this.metamodel, ((InternalSelection)x).getCurrentNode().notEqual(((InternalSelection)y).getCurrentNode()), buildList(x, y), "not equal");
     }
 
     /**
@@ -657,12 +648,10 @@
         if (((InternalSelection)x).getCurrentNode() == null){
             throw new IllegalArgumentException(ExceptionLocalization.buildMessage("OPERATOR_EXPRESSION_IS_CONJUNCTION"));
         }
-        if (y instanceof ParameterExpression) return this.equal(x, (ParameterExpression)y);
+        if (y instanceof ParameterExpression) 
+            return this.equal(x, (ParameterExpression)y);
 
-        List<Expression<?>> list = new ArrayList<>();
-        list.add(x);
-        list.add(this.internalLiteral(y));
-        return new CompoundExpressionImpl(this.metamodel, ((InternalSelection)x).getCurrentNode().equal(y), list, "equal");
+        return new CompoundExpressionImpl(this.metamodel, ((InternalSelection)x).getCurrentNode().equal(y), buildList(x, internalLiteral(y)), "equal");
     }
 
     /**
@@ -679,11 +668,10 @@
         if (((InternalSelection)x).getCurrentNode() == null){
             throw new IllegalArgumentException(ExceptionLocalization.buildMessage("OPERATOR_EXPRESSION_IS_CONJUNCTION"));
         }
-        if (y instanceof ParameterExpression) return this.notEqual(x, (ParameterExpression)y);
-        List<Expression<?>> list = new ArrayList<>();
-        list.add(x);
-        list.add(this.internalLiteral(y));
-        return new CompoundExpressionImpl(this.metamodel, ((InternalSelection)x).getCurrentNode().notEqual(y), list, "not equal");
+        if (y instanceof ParameterExpression) 
+            return this.notEqual(x, (ParameterExpression)y);
+
+        return new CompoundExpressionImpl(this.metamodel, ((InternalSelection)x).getCurrentNode().notEqual(y), buildList(x, internalLiteral(y)), "not equal");
     }
 
     // comparisons for generic (non-numeric) operands:
@@ -702,10 +690,7 @@
         if (((InternalSelection)x).getCurrentNode() == null || ((InternalSelection)y).getCurrentNode() == null){
             throw new IllegalArgumentException(ExceptionLocalization.buildMessage("OPERATOR_EXPRESSION_IS_CONJUNCTION"));
         }
-        List<Expression<?>> list = new ArrayList<>();
-        list.add(x);
-        list.add(y);
-        return new CompoundExpressionImpl(this.metamodel, ((InternalSelection)x).getCurrentNode().greaterThan(((InternalSelection)y).getCurrentNode()), list, "greaterThan");
+        return new CompoundExpressionImpl(this.metamodel, ((InternalSelection)x).getCurrentNode().greaterThan(((InternalSelection)y).getCurrentNode()), buildList(x, y), "greaterThan");
     }
 
     /**
@@ -741,10 +726,7 @@
         if (((ExpressionImpl)x).getCurrentNode() == null || ((ExpressionImpl)y).getCurrentNode() == null){
             throw new IllegalArgumentException(ExceptionLocalization.buildMessage("OPERATOR_EXPRESSION_IS_CONJUNCTION"));
         }
-        List<Expression<?>> list = new ArrayList<>();
-        list.add(x);
-        list.add(y);
-        return new CompoundExpressionImpl(this.metamodel, ((ExpressionImpl)x).getCurrentNode().greaterThanEqual(((ExpressionImpl)y).getCurrentNode()), list, "greaterThanEqual");
+        return new CompoundExpressionImpl(this.metamodel, ((ExpressionImpl)x).getCurrentNode().greaterThanEqual(((ExpressionImpl)y).getCurrentNode()), buildList(x, y), "greaterThanEqual");
     }
 
     /**
@@ -762,10 +744,7 @@
         if (((ExpressionImpl)x).getCurrentNode() == null || ((ExpressionImpl)y).getCurrentNode() == null){
             throw new IllegalArgumentException(ExceptionLocalization.buildMessage("OPERATOR_EXPRESSION_IS_CONJUNCTION"));
         }
-        List<Expression<?>> list = new ArrayList<>();
-        list.add(x);
-        list.add(y);
-        return new CompoundExpressionImpl(this.metamodel, ((ExpressionImpl)x).getCurrentNode().lessThanEqual(((ExpressionImpl)y).getCurrentNode()), list, "lessThanEqual");
+        return new CompoundExpressionImpl(this.metamodel, ((ExpressionImpl)x).getCurrentNode().lessThanEqual(((ExpressionImpl)y).getCurrentNode()), buildList(x, y), "lessThanEqual");
     }
 
     /**
@@ -782,12 +761,7 @@
      */
     @Override
     public <Y extends Comparable<? super Y>> Predicate between(Expression<? extends Y> v, Expression<? extends Y> x, Expression<? extends Y> y){
-
-        List<Expression<?>> list = new ArrayList<>();
-        list.add(v);
-        list.add(x);
-        list.add(y);
-        return new CompoundExpressionImpl(this.metamodel, ((ExpressionImpl)v).getCurrentNode().between(((ExpressionImpl)x).getCurrentNode(), ((ExpressionImpl)y).getCurrentNode()), list, "between");
+        return new CompoundExpressionImpl(this.metamodel, ((ExpressionImpl)v).getCurrentNode().between(((ExpressionImpl)x).getCurrentNode(), ((ExpressionImpl)y).getCurrentNode()), buildList(v, x, y), "between");
     }
 
     /**
@@ -802,14 +776,11 @@
      */
     @Override
     public <Y extends Comparable<? super Y>> Predicate greaterThan(Expression<? extends Y> x, Y y){
-        Expression<Y> expressionY = this.internalLiteral(y);
         if (((ExpressionImpl)x).getCurrentNode() == null ){
             throw new IllegalArgumentException(ExceptionLocalization.buildMessage("OPERATOR_EXPRESSION_IS_CONJUNCTION"));
         }
-        List<Expression<?>> list = new ArrayList<>();
-        list.add(x);
-        list.add(expressionY);
-        return new CompoundExpressionImpl(this.metamodel, ((ExpressionImpl)x).getCurrentNode().greaterThan(((ExpressionImpl)expressionY).getCurrentNode()), list, "greaterThan");
+        Expression<Y> expressionY = internalLiteral(y);
+        return new CompoundExpressionImpl(this.metamodel, ((ExpressionImpl)x).getCurrentNode().greaterThan(((ExpressionImpl)expressionY).getCurrentNode()), buildList(x, expressionY), "greaterThan");
     }
 
     /**
@@ -824,14 +795,11 @@
      */
     @Override
     public <Y extends Comparable<? super Y>> Predicate lessThan(Expression<? extends Y> x, Y y){
-        Expression<Y> expressionY = this.internalLiteral(y);
         if (((ExpressionImpl)x).getCurrentNode() == null ){
             throw new IllegalArgumentException(ExceptionLocalization.buildMessage("OPERATOR_EXPRESSION_IS_CONJUNCTION"));
         }
-        List<Expression<?>> list = new ArrayList<>();
-        list.add(x);
-        list.add(expressionY);
-        return new CompoundExpressionImpl(this.metamodel, ((ExpressionImpl)x).getCurrentNode().lessThan(((ExpressionImpl)expressionY).getCurrentNode()), list, "lessThan");
+        Expression<Y> expressionY = internalLiteral(y);
+        return new CompoundExpressionImpl(this.metamodel, ((ExpressionImpl)x).getCurrentNode().lessThan(((ExpressionImpl)expressionY).getCurrentNode()), buildList(x, expressionY), "lessThan");
     }
 
     /**
@@ -846,14 +814,11 @@
      */
     @Override
     public <Y extends Comparable<? super Y>> Predicate greaterThanOrEqualTo(Expression<? extends Y> x, Y y){
-        Expression<Y> expressionY = this.internalLiteral(y);
         if (((ExpressionImpl)x).getCurrentNode() == null ){
             throw new IllegalArgumentException(ExceptionLocalization.buildMessage("OPERATOR_EXPRESSION_IS_CONJUNCTION"));
         }
-        List<Expression<?>> list = new ArrayList<>();
-        list.add(x);
-        list.add(expressionY);
-        return new CompoundExpressionImpl(this.metamodel, ((ExpressionImpl)x).getCurrentNode().greaterThanEqual(((ExpressionImpl)expressionY).getCurrentNode()), list, "greaterThanEqual");
+        Expression<Y> expressionY = internalLiteral(y);
+        return new CompoundExpressionImpl(this.metamodel, ((ExpressionImpl)x).getCurrentNode().greaterThanEqual(((ExpressionImpl)expressionY).getCurrentNode()), buildList(x, expressionY), "greaterThanEqual");
     }
 
     /**
@@ -868,14 +833,11 @@
      */
     @Override
     public <Y extends Comparable<? super Y>> Predicate lessThanOrEqualTo(Expression<? extends Y> x, Y y){
-        Expression<Y> expressionY = this.internalLiteral(y);
         if (((ExpressionImpl)x).getCurrentNode() == null ){
             throw new IllegalArgumentException(ExceptionLocalization.buildMessage("OPERATOR_EXPRESSION_IS_CONJUNCTION"));
         }
-        List<Expression<?>> list = new ArrayList<>();
-        list.add(x);
-        list.add(expressionY);
-        return new CompoundExpressionImpl(this.metamodel, ((ExpressionImpl)x).getCurrentNode().lessThanEqual(((ExpressionImpl)expressionY).getCurrentNode()), list, "lessThanEqual");
+        Expression<Y> expressionY = internalLiteral(y);
+        return new CompoundExpressionImpl(this.metamodel, ((ExpressionImpl)x).getCurrentNode().lessThanEqual(((ExpressionImpl)expressionY).getCurrentNode()), buildList(x, expressionY), "lessThanEqual");
     }
 
     /**
@@ -892,11 +854,7 @@
      */
     @Override
     public <Y extends Comparable<? super Y>> Predicate between(Expression<? extends Y> v, Y x, Y y){
-        List<Expression<?>> list = new ArrayList<>();
-        list.add(v);
-        list.add(this.internalLiteral(x));
-        list.add(this.internalLiteral(y));
-        return new CompoundExpressionImpl(this.metamodel, ((ExpressionImpl)v).getCurrentNode().between(x, y), list, "between");
+        return new CompoundExpressionImpl(this.metamodel, ((ExpressionImpl)v).getCurrentNode().between(x, y), buildList(v, internalLiteral(x), internalLiteral(y)), "between");
     }
 
     protected List<Expression<?>> buildList(Expression<?>... expressions){
@@ -920,10 +878,7 @@
      */
     @Override
     public Predicate gt(Expression<? extends Number> x, Expression<? extends Number> y){
-        List<Expression<?>> list = new ArrayList<>();
-        list.add(x);
-        list.add(y);
-        return new CompoundExpressionImpl(this.metamodel, ((InternalSelection)x).getCurrentNode().greaterThan(((InternalSelection)y).getCurrentNode()), list, "gt");
+        return new CompoundExpressionImpl(this.metamodel, ((InternalSelection)x).getCurrentNode().greaterThan(((InternalSelection)y).getCurrentNode()), buildList(x, y), "gt");
     }
 
     /**
@@ -953,10 +908,7 @@
      */
     @Override
     public Predicate ge(Expression<? extends Number> x, Expression<? extends Number> y){
-        List<Expression<?>> list = new ArrayList<>();
-        list.add(x);
-        list.add(y);
-        return new CompoundExpressionImpl(this.metamodel, ((InternalSelection)x).getCurrentNode().greaterThanEqual(((InternalSelection)y).getCurrentNode()), list, "ge");
+        return new CompoundExpressionImpl(this.metamodel, ((InternalSelection)x).getCurrentNode().greaterThanEqual(((InternalSelection)y).getCurrentNode()), buildList(x, y), "ge");
     }
 
     /**
@@ -971,10 +923,7 @@
      */
     @Override
     public Predicate le(Expression<? extends Number> x, Expression<? extends Number> y){
-        List<Expression<?>> list = new ArrayList<>();
-        list.add(x);
-        list.add(y);
-        return new CompoundExpressionImpl(this.metamodel, ((InternalSelection)x).getCurrentNode().lessThanEqual(((InternalSelection)y).getCurrentNode()), list, "le");
+        return new CompoundExpressionImpl(this.metamodel, ((InternalSelection)x).getCurrentNode().lessThanEqual(((InternalSelection)y).getCurrentNode()), buildList(x, y), "le");
     }
 
     /**
@@ -989,10 +938,7 @@
      */
     @Override
     public Predicate gt(Expression<? extends Number> x, Number y){
-        List<Expression<?>> list = new ArrayList<>();
-        list.add(x);
-        list.add(internalLiteral(y));
-        return new CompoundExpressionImpl(this.metamodel, ((InternalSelection)x).getCurrentNode().greaterThan(y), list, "gt");
+        return new CompoundExpressionImpl(this.metamodel, ((InternalSelection)x).getCurrentNode().greaterThan(y), buildList(x, internalLiteral(y)), "gt");
     }
 
     /**
@@ -1007,7 +953,7 @@
      */
     @Override
     public Predicate lt(Expression<? extends Number> x, Number y){
-        return new CompoundExpressionImpl(this.metamodel, ((InternalSelection)x).getCurrentNode().lessThan(y), buildList(x,internalLiteral(y)), "lt");
+        return new CompoundExpressionImpl(this.metamodel, ((InternalSelection)x).getCurrentNode().lessThan(y), buildList(x, internalLiteral(y)), "lt");
     }
 
     /**
@@ -1022,10 +968,7 @@
      */
     @Override
     public Predicate ge(Expression<? extends Number> x, Number y){
-        List<Expression<?>> list = new ArrayList<>();
-        list.add(x);
-        list.add(internalLiteral(y));
-        return new CompoundExpressionImpl(this.metamodel, ((InternalSelection)x).getCurrentNode().greaterThanEqual(y), list, "ge");
+        return new CompoundExpressionImpl(this.metamodel, ((InternalSelection)x).getCurrentNode().greaterThanEqual(y), buildList(x, internalLiteral(y)), "ge");
     }
 
     /**
@@ -1128,10 +1071,7 @@
      */
     @Override
     public <N extends Number> Expression<N> diff(Expression<? extends N> x, Expression<? extends N> y){
-        List<Expression<?>> list = new ArrayList<>();
-        list.add(x);
-        list.add(y);
-        return new FunctionExpressionImpl(this.metamodel, x.getJavaType(), ExpressionMath.subtract(((InternalSelection)x).getCurrentNode(), ((InternalSelection)y).getCurrentNode()), list, "diff");
+        return new FunctionExpressionImpl(this.metamodel, x.getJavaType(), ExpressionMath.subtract(((InternalSelection)x).getCurrentNode(), ((InternalSelection)y).getCurrentNode()), buildList(x, y), "diff");
     }
 
     /**
@@ -1173,10 +1113,7 @@
      */
     @Override
     public <N extends Number> Expression<N> diff(Expression<? extends N> x, N y){
-        List<Expression<?>> list = new ArrayList<>();
-        list.add(x);
-        list.add(this.internalLiteral(y));
-        return new FunctionExpressionImpl(this.metamodel, y.getClass(), ExpressionMath.subtract(((InternalSelection)x).getCurrentNode(), y), list, "diff");
+        return new FunctionExpressionImpl(this.metamodel, y.getClass(), ExpressionMath.subtract(((InternalSelection)x).getCurrentNode(), y), buildList(x, internalLiteral(y)), "diff");
     }
 
     /**
@@ -1218,11 +1155,8 @@
      */
     @Override
     public <N extends Number> Expression<N> diff(N x, Expression<? extends N> y){
-        List<Expression<?>> list = new ArrayList<>();
-        ExpressionImpl literal = (ExpressionImpl) this.internalLiteral(x);
-        list.add(literal);
-        list.add(y);
-        return new FunctionExpressionImpl(this.metamodel, literal.getJavaType(), ExpressionMath.subtract(((InternalSelection)literal).getCurrentNode(), ((InternalSelection)y).getCurrentNode()), list, "diff");
+        Expression literal = internalLiteral(x);
+        return new FunctionExpressionImpl(this.metamodel, literal.getJavaType(), ExpressionMath.subtract(((InternalSelection)literal).getCurrentNode(), ((InternalSelection)y).getCurrentNode()), buildList(literal, y), "diff");
     }
 
     /**
@@ -1734,9 +1668,8 @@
      */
     @Override
     public Predicate like(Expression<String> x, Expression<String> pattern){
-        List<Expression<?>> list = this.buildList(x, pattern);
         return new CompoundExpressionImpl(this.metamodel,
-            ((InternalSelection)x).getCurrentNode().like(((InternalSelection)pattern).getCurrentNode()), list, "like");
+            ((InternalSelection)x).getCurrentNode().like(((InternalSelection)pattern).getCurrentNode()), buildList(x, pattern), "like");
     }
 
     /**
@@ -1753,9 +1686,8 @@
      */
     @Override
     public Predicate like(Expression<String> x, Expression<String> pattern, Expression<Character> escapeChar){
-        List<Expression<?>> list = this.buildList(x, pattern, escapeChar);
         return new CompoundExpressionImpl(this.metamodel,
-            ((InternalSelection)x).getCurrentNode().like(((InternalSelection)pattern).getCurrentNode(), ((InternalSelection)escapeChar).getCurrentNode()), list, "like");
+            ((InternalSelection)x).getCurrentNode().like(((InternalSelection)pattern).getCurrentNode(), ((InternalSelection)escapeChar).getCurrentNode()), buildList(x, pattern, escapeChar), "like");
     }
 
     /**
@@ -1772,7 +1704,6 @@
      */
     @Override
     public Predicate like(Expression<String> x, Expression<String> pattern, char escapeChar){
-
         return this.like(x, pattern, this.internalLiteral(escapeChar));
     }
 
@@ -1788,8 +1719,7 @@
      */
     @Override
     public Predicate like(Expression<String> x, String pattern){
-        List<Expression<?>> list = this.buildList(x, this.internalLiteral(pattern));
-        return new CompoundExpressionImpl(this.metamodel, ((InternalSelection)x).getCurrentNode().like(pattern), list, "like");
+        return new CompoundExpressionImpl(this.metamodel, ((InternalSelection)x).getCurrentNode().like(pattern), buildList(x, internalLiteral(pattern)), "like");
     }
 
     /**
@@ -1823,11 +1753,10 @@
      */
     @Override
     public Predicate like(Expression<String> x, String pattern, char escapeChar){
-        List<Expression<?>> list = this.buildList(x, this.internalLiteral(pattern), this.internalLiteral(escapeChar));
         String escapeString = String.valueOf(escapeChar);
 
         return new CompoundExpressionImpl(this.metamodel,
-            ((InternalSelection)x).getCurrentNode().like(pattern, escapeString), list, "like");
+            ((InternalSelection)x).getCurrentNode().like(pattern, escapeString), buildList(x, internalLiteral(pattern), internalLiteral(escapeChar)), "like");
     }
 
     /**
@@ -1842,10 +1771,8 @@
      */
     @Override
     public Predicate notLike(Expression<String> x, Expression<String> pattern){
-        List<Expression<?>> list = this.buildList(x, pattern);
-
         return new CompoundExpressionImpl(this.metamodel,
-            ((InternalSelection)x).getCurrentNode().notLike(((InternalSelection)pattern).getCurrentNode()), list, "notLike");
+            ((InternalSelection)x).getCurrentNode().notLike(((InternalSelection)pattern).getCurrentNode()), buildList(x, pattern), "notLike");
     }
 
     /**
@@ -1862,11 +1789,9 @@
      */
     @Override
     public Predicate notLike(Expression<String> x, Expression<String> pattern, Expression<Character> escapeChar){
-        List<Expression<?>> list = this.buildList(x, pattern, escapeChar);
-
         return new CompoundExpressionImpl(this.metamodel,
             ((InternalSelection)x).getCurrentNode().notLike(((InternalSelection)pattern).getCurrentNode(),
-            ((InternalSelection)escapeChar).getCurrentNode()), list, "like");
+            ((InternalSelection)escapeChar).getCurrentNode()), buildList(x, pattern, escapeChar), "like");
     }
 
     /**
@@ -1898,12 +1823,8 @@
      */
     @Override
     public Predicate notLike(Expression<String> x, String pattern){
-        List<Expression<?>> list = new ArrayList<>();
-        list.add(x);
-        list.add(this.internalLiteral(pattern));
-
         return new CompoundExpressionImpl(this.metamodel,
-            ((InternalSelection)x).getCurrentNode().notLike(pattern), list, "notLike");
+            ((InternalSelection)x).getCurrentNode().notLike(pattern), buildList(x, internalLiteral(pattern)), "notLike");
     }
 
     /**
@@ -1951,17 +1872,14 @@
      */
     @Override
     public Expression<String> concat(Expression<String> x, Expression<String> y){
-        List<Expression<?>> list = new ArrayList<>();
-        list.add(x);
-        list.add(y);
         org.eclipse.persistence.expressions.Expression xNode = ((InternalSelection)x).getCurrentNode();
         org.eclipse.persistence.expressions.Expression yNode = ((InternalSelection)y).getCurrentNode();
 
         if (xNode.isParameterExpression() && yNode.isParameterExpression()) {
             //some database require the type when concatting two parameters.
             ((org.eclipse.persistence.internal.expressions.ParameterExpression)xNode).setType(ClassConstants.STRING);
-    }
-        return new FunctionExpressionImpl(this.metamodel, ClassConstants.STRING, xNode.concat(yNode), list, CONCAT);
+        }
+        return new FunctionExpressionImpl(this.metamodel, ClassConstants.STRING, xNode.concat(yNode), buildList(x, y), CONCAT);
     }
 
     /**
@@ -1975,10 +1893,7 @@
      */
     @Override
     public Expression<String> concat(Expression<String> x, String y){
-        List<Expression<?>> list = new ArrayList<>();
-        list.add(x);
-        list.add(this.internalLiteral(y));
-        return new FunctionExpressionImpl(this.metamodel, ClassConstants.STRING, ((InternalSelection)x).getCurrentNode().concat(y), list, CONCAT);
+        return new FunctionExpressionImpl(this.metamodel, ClassConstants.STRING, ((InternalSelection)x).getCurrentNode().concat(y), buildList(x, internalLiteral(y)), CONCAT);
 
     }
 
@@ -1993,11 +1908,8 @@
      */
     @Override
     public Expression<String> concat(String x, Expression<String> y){
-        List<Expression<?>> list = new ArrayList<>();
-        ExpressionImpl literal = (ExpressionImpl) this.internalLiteral(x);
-        list.add(literal);
-        list.add(y);
-        return new FunctionExpressionImpl(this.metamodel, ClassConstants.STRING, ((InternalSelection)literal).getCurrentNode().concat(((InternalSelection)y).getCurrentNode()), list, CONCAT);
+        Expression literal = internalLiteral(x);
+        return new FunctionExpressionImpl(this.metamodel, ClassConstants.STRING, ((InternalSelection)literal).getCurrentNode().concat(((InternalSelection)y).getCurrentNode()), buildList(literal, y), CONCAT);
     }
 
     /**
@@ -2074,8 +1986,7 @@
      */
     @Override
     public Expression<String> trim(Expression<String> x){
-        List<Expression<?>> list = this.buildList(x);
-        return new FunctionExpressionImpl(this.metamodel, ClassConstants.STRING, ((InternalSelection)x).getCurrentNode().trim(), list, "trim");
+        return new FunctionExpressionImpl(this.metamodel, ClassConstants.STRING, ((InternalSelection)x).getCurrentNode().trim(), buildList(x), "trim");
     }
 
     /**
@@ -2089,14 +2000,12 @@
      */
     @Override
     public Expression<String> trim(Trimspec ts, Expression<String> x){
-        List<Expression<?>> list = this.buildList(x);
-
         if(ts == Trimspec.LEADING) {
-            return new FunctionExpressionImpl(this.metamodel, ClassConstants.STRING, ((InternalSelection)x).getCurrentNode().leftTrim(), list, "leftTrim");
+            return new FunctionExpressionImpl(this.metamodel, ClassConstants.STRING, ((InternalSelection)x).getCurrentNode().leftTrim(), buildList(x), "leftTrim");
         } else if(ts == Trimspec.TRAILING) {
-            return new FunctionExpressionImpl(this.metamodel, ClassConstants.STRING, ((InternalSelection)x).getCurrentNode().rightTrim(), list, "rightTrim");
+            return new FunctionExpressionImpl(this.metamodel, ClassConstants.STRING, ((InternalSelection)x).getCurrentNode().rightTrim(), buildList(x), "rightTrim");
     }
-        return new FunctionExpressionImpl(this.metamodel, ClassConstants.STRING, ((InternalSelection)x).getCurrentNode().rightTrim().leftTrim(), list, "bothTrim");
+        return new FunctionExpressionImpl(this.metamodel, ClassConstants.STRING, ((InternalSelection)x).getCurrentNode().rightTrim().leftTrim(), buildList(x), "bothTrim");
 
     }
 
@@ -2111,8 +2020,7 @@
      */
     @Override
     public Expression<String> trim(Expression<Character> t, Expression<String> x){
-        List<Expression<?>> list = this.buildList(x, t);
-        return new FunctionExpressionImpl(this.metamodel, ClassConstants.STRING, ((InternalSelection)x).getCurrentNode().trim(((InternalSelection)t).getCurrentNode()), list, "trim");
+        return new FunctionExpressionImpl(this.metamodel, ClassConstants.STRING, ((InternalSelection)x).getCurrentNode().trim(((InternalSelection)t).getCurrentNode()), buildList(x, t), "trim");
     }
 
     /**
@@ -2128,17 +2036,15 @@
      */
     @Override
     public Expression<String> trim(Trimspec ts, Expression<Character> t, Expression<String> x){
-        List<Expression<?>> list = this.buildList(x, t);
-
         if(ts == Trimspec.LEADING) {
             return new FunctionExpressionImpl(this.metamodel, ClassConstants.STRING,
-                ((InternalSelection)x).getCurrentNode().leftTrim(((InternalSelection)t).getCurrentNode()), list, "leftTrim");
+                ((InternalSelection)x).getCurrentNode().leftTrim(((InternalSelection)t).getCurrentNode()), buildList(x, t), "leftTrim");
         } else if(ts == Trimspec.TRAILING) {
             return new FunctionExpressionImpl(this.metamodel, ClassConstants.STRING,
-                ((InternalSelection)x).getCurrentNode().rightTrim(((InternalSelection)t).getCurrentNode()), list, "rightTrim");
+                ((InternalSelection)x).getCurrentNode().rightTrim(((InternalSelection)t).getCurrentNode()), buildList(x, t), "rightTrim");
     }
         return new FunctionExpressionImpl(this.metamodel, ClassConstants.STRING,
-            ((InternalSelection)x).getCurrentNode().rightTrim(((InternalSelection)t).getCurrentNode()).leftTrim(((InternalSelection)t).getCurrentNode()), list, "bothTrim");
+            ((InternalSelection)x).getCurrentNode().rightTrim(((InternalSelection)t).getCurrentNode()).leftTrim(((InternalSelection)t).getCurrentNode()), buildList(x, t), "bothTrim");
     }
 
     /**
@@ -2180,8 +2086,7 @@
      */
     @Override
     public Expression<String> lower(Expression<String> x){
-        List<Expression<?>> list = this.buildList(x);
-        return new FunctionExpressionImpl(this.metamodel, ClassConstants.STRING, ((InternalSelection)x).getCurrentNode().toLowerCase(), list, "lower");
+        return new FunctionExpressionImpl(this.metamodel, ClassConstants.STRING, ((InternalSelection)x).getCurrentNode().toLowerCase(), buildList(x), "lower");
     }
 
     /**
@@ -2193,8 +2098,7 @@
      */
     @Override
     public Expression<String> upper(Expression<String> x){
-        List<Expression<?>> list = this.buildList(x);
-        return new FunctionExpressionImpl(this.metamodel, ClassConstants.STRING, ((InternalSelection)x).getCurrentNode().toUpperCase(), list, "upper");
+        return new FunctionExpressionImpl(this.metamodel, ClassConstants.STRING, ((InternalSelection)x).getCurrentNode().toUpperCase(), buildList(x), "upper");
     }
 
     /**
@@ -2352,9 +2256,7 @@
      */
     @Override
     public <T> In<T> in(Expression<? extends T> expression){
-        List<Expression<?>> list = new ArrayList<>();
-        list.add(expression);
-        return new InImpl(metamodel, (ExpressionImpl) expression, new ArrayList<>(), list);
+        return new InImpl(metamodel, (ExpressionImpl) expression, new ArrayList<>(), buildList(expression));
     }
 
     // coalesce, nullif: