Bug 579726: CriteriaBuilder neg() only returns Integer type, instead of it's argument expression type. #1485

Signed-off-by: Joe Grassel <fyrewyld@gmail.com>
diff --git a/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/criteria/TestNegFunction.java b/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/criteria/TestNegFunction.java
new file mode 100644
index 0000000..35856c8
--- /dev/null
+++ b/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/criteria/TestNegFunction.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022 IBM Corporation. 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:
+//     04/19/2022: Jody Grassel
+//       - Issue 579726: CriteriaBuilder neg() only returns Integer type, instead of it's argument expression type.
+package org.eclipse.persistence.jpa.test.criteria;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.EntityManagerFactory;
+import jakarta.persistence.criteria.CriteriaBuilder;
+import jakarta.persistence.criteria.CriteriaQuery;
+import jakarta.persistence.criteria.Expression;
+import jakarta.persistence.criteria.Root;
+import jakarta.persistence.criteria.Selection;
+
+import org.eclipse.persistence.jpa.test.criteria.model.CoalesceEntity;
+import org.eclipse.persistence.jpa.test.criteria.model.CritEntity;
+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.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(EmfRunner.class)
+public class TestNegFunction {
+    @Emf(createTables = DDLGen.DROP_CREATE, classes = { CritEntity.class })
+    private EntityManagerFactory emf;
+
+    @Test
+    public void testNegFunction() throws Exception {
+        EntityManager em = emf.createEntityManager();
+
+        try {
+            CritEntity ce = new CritEntity();
+            ce.setId(1);
+            ce.setValue(new BigDecimal("3.14"));
+
+            em.getTransaction().begin();
+            em.persist(ce);;
+            em.getTransaction().commit();
+            em.clear();
+
+            CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
+            CriteriaQuery<DecHolder> criteriaQuery = criteriaBuilder.createQuery(DecHolder.class);
+            Root<CritEntity> entityRoot = criteriaQuery.from(CritEntity.class);
+
+            Collection<Selection<?>> selections = new ArrayList<Selection<?>>();
+
+            Expression<BigDecimal> valExpr = entityRoot.get("value");
+
+            selections.add(criteriaBuilder.sum(
+                  criteriaBuilder.<BigDecimal> selectCase()
+                        .when(criteriaBuilder.equal(entityRoot.get("id"), 0), valExpr)
+                        .otherwise(criteriaBuilder.neg(valExpr))));
+
+            criteriaQuery.multiselect(selections.toArray(new Selection[] {}));
+
+            List<DecHolder> retList = em.createQuery(criteriaQuery).getResultList();
+        } finally {
+            if (em.getTransaction().isActive()) {
+                em.getTransaction().rollback();
+            }
+            if(em.isOpen()) {
+                em.close();
+            }
+        }
+    }
+
+    public static class DecHolder {
+        private BigDecimal value;
+
+        public DecHolder(Object value) {
+            super();
+            this.value = (BigDecimal) value;
+        }
+
+        public BigDecimal getValue() {
+            return value;
+         }
+
+         public void setValue(BigDecimal value) {
+            this.value = value;
+         }
+
+         @Override
+         public String toString() {
+            return "DecHolder [value=" + value + "]";
+         }
+    }
+}
diff --git a/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/criteria/model/CritEntity.java b/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/criteria/model/CritEntity.java
new file mode 100644
index 0000000..fc6e3b6
--- /dev/null
+++ b/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/criteria/model/CritEntity.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022 IBM Corporation. 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:
+//     04/19/2022: Jody Grassel
+//       - Issue 579726: CriteriaBuilder neg() only returns Integer type, instead of it's argument expression type.
+package org.eclipse.persistence.jpa.test.criteria.model;
+
+import java.math.BigDecimal;
+
+import jakarta.persistence.Basic;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+
+@Entity
+public class CritEntity {
+    @Id
+    private int id;
+
+    @Basic
+    @Column(precision = 10, scale = 2)
+    private BigDecimal value;
+
+    public CritEntity() {
+
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public BigDecimal getValue() {
+        return value;
+    }
+
+    public void setValue(BigDecimal bigDec) {
+        this.value = bigDec;
+    }
+
+    @Override
+    public String toString() {
+        return "CritEntity [id=" + id + ", value=" + value + "]";
+    }
+
+
+}
+
+
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 dc8b8a5..6a76e6a 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
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2009, 2022 Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2020, 2021 IBM Corporation. All rights reserved.
+ * Copyright (c) 2020, 2022 IBM Corporation. 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
@@ -15,6 +15,8 @@
 //     Gordon Yorke - Initial development
 //     02/01/2022: Tomas Kraus
 //       - Issue 1442: Implement New JPA API 3.1.0 Features
+//     04/19/2022: Jody Grassel
+//       - Issue 579726: CriteriaBuilder neg() only returns Integer type, instead of it's argument expression type.
 package org.eclipse.persistence.internal.jpa.querydef;
 
 import java.io.Serializable;
@@ -648,7 +650,7 @@
         if (((InternalSelection)x).getCurrentNode() == null){
             throw new IllegalArgumentException(ExceptionLocalization.buildMessage("OPERATOR_EXPRESSION_IS_CONJUNCTION"));
         }
-        if (y instanceof ParameterExpression) 
+        if (y instanceof ParameterExpression)
             return this.equal(x, (ParameterExpression)y);
 
         return new CompoundExpressionImpl(this.metamodel, ((InternalSelection)x).getCurrentNode().equal(y), buildList(x, internalLiteral(y)), "equal");
@@ -668,7 +670,7 @@
         if (((InternalSelection)x).getCurrentNode() == null){
             throw new IllegalArgumentException(ExceptionLocalization.buildMessage("OPERATOR_EXPRESSION_IS_CONJUNCTION"));
         }
-        if (y instanceof ParameterExpression) 
+        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");
@@ -997,7 +999,7 @@
      */
     @Override
     public <N extends Number> Expression<N> neg(Expression<N> x){
-        return new FunctionExpressionImpl(this.metamodel, ClassConstants.INTEGER, ExpressionMath.negate(((InternalSelection)x).getCurrentNode()), buildList(x), "neg");
+        return new FunctionExpressionImpl(this.metamodel, (Class<N>) x.getJavaType(), ExpressionMath.negate(((InternalSelection)x).getCurrentNode()), buildList(x), "neg");
     }
 
     /**