Repository: primefaces/primefaces (java)

Issue:
InputNumber: `Number` identified as non-decimal
### Describe the bug

a PRO reported an issue related to InputNumberRenderer.isIntegral method. Will we add decimal type checks for Number type?

```java
// InputNumberRenderer.java
private boolean isIntegral(FacesContext context, InputNumber inputNumber, Object value) {
        if (value != null) {
            return value instanceof Long
                    || value instanceof Integer
                    || value instanceof Short
                    || value instanceof BigInteger
                    || value instanceof Byte;
        }

        Class<?> type = getTypeFromValueExpression(context, inputNumber);
        if (type == null) {
            return false;
        }

        return type.isAssignableFrom(Long.class)
                || type.isAssignableFrom(Integer.class)
                || type.isAssignableFrom(Short.class)
                || type.isAssignableFrom(BigInteger.class)
                || type.isAssignableFrom(Byte.class);
    }
```

As you know, java.lang.Number is a superclass of Integer, Long, Short, [...].
Since the upgrade from 11.0.7 to 13.0.8 we face the issue that p:inputNumber defaults to 0 decimalPlaces when using a java.lang.Number (initial value null) as value.
This seems to happen because the check for integral, with a null value, tests for "isAssignableFrom(Integer.class)" etc.
Thus, it returns true, even though java.lang.Number can have decimalPlaces.

### Reproducer

```java
private Number number;
```

```xml
<p:inputNumber value="#{testView.number}" />
```

### Expected behavior

_No response_

### PrimeFaces edition

Community

### PrimeFaces version

13.0.8

### Theme

_No response_

### JSF implementation

Mojarra

### JSF version

2.3

### Java version

11

### Browser(s)

_No response_

Pull request:
Fix #11791: InputNumber allow Number.class to be decimal
Fix #11791: InputNumber all Number.class to be decimal

With unit tests showing the fix

Patch:
diff --git a/pom.xml b/pom.xml
index 27e55af500..5548af882a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -128,7 +128,7 @@
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-jar-plugin</artifactId>
-                <version>3.4.0</version>
+                <version>3.4.1</version>
             </plugin>
 
             <plugin>
diff --git a/primefaces/src/main/java/org/primefaces/component/inputnumber/InputNumberRenderer.java b/primefaces/src/main/java/org/primefaces/component/inputnumber/InputNumberRenderer.java
index 4a230ff027..7c7d291e8e 100644
--- a/primefaces/src/main/java/org/primefaces/component/inputnumber/InputNumberRenderer.java
+++ b/primefaces/src/main/java/org/primefaces/component/inputnumber/InputNumberRenderer.java
@@ -392,7 +392,7 @@ public class InputNumberRenderer extends InputRenderer {
         return formatForPlugin(maximum);
     }
 
-    private boolean isIntegral(FacesContext context, InputNumber inputNumber, Object value) {
+    protected boolean isIntegral(FacesContext context, InputNumber inputNumber, Object value) {
         if (value != null) {
             return value instanceof Long
                     || value instanceof Integer
@@ -402,7 +402,9 @@ public class InputNumberRenderer extends InputRenderer {
         }
 
         Class<?> type = getTypeFromValueExpression(context, inputNumber);
-        if (type == null) {
+
+        // #11791 Number is the superclass for all the types so it could be a decimal
+        if (type == null || type == Number.class) {
             return false;
         }
 


Test patch:
diff --git a/primefaces/src/test/java/org/primefaces/component/inputnumber/InputNumberTest.java b/primefaces/src/test/java/org/primefaces/component/inputnumber/InputNumberTest.java
index 8ac3821dc2..51cd418d35 100644
--- a/primefaces/src/test/java/org/primefaces/component/inputnumber/InputNumberTest.java
+++ b/primefaces/src/test/java/org/primefaces/component/inputnumber/InputNumberTest.java
@@ -26,9 +26,13 @@ package org.primefaces.component.inputnumber;
 import static org.junit.jupiter.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.doCallRealMethod;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
+import java.math.BigDecimal;
+import java.math.BigInteger;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -53,7 +57,7 @@ class InputNumberTest {
 
     @BeforeEach
     void setup() {
-        renderer = new InputNumberRenderer();
+        renderer = spy(new InputNumberRenderer());
         context = mock(FacesContext.class);
         externalContext = mock(ExternalContext.class);
         elContext = mock(ELContext.class);
@@ -196,4 +200,32 @@ class InputNumberTest {
         assertNull(inputNumber.getSubmittedValue());
     }
 
+    @Test
+    void isIntegral() {
+        // values
+        doReturn(BigDecimal.class).when(renderer).getTypeFromValueExpression(context, inputNumber);
+        assertFalse(renderer.isIntegral(context, inputNumber, BigDecimal.valueOf(5.5)));
+        doReturn(Number.class).when(renderer).getTypeFromValueExpression(context, inputNumber);
+        assertFalse(renderer.isIntegral(context, inputNumber, BigDecimal.valueOf(5.5)));
+        doReturn(Number.class).when(renderer).getTypeFromValueExpression(context, inputNumber);
+        assertTrue(renderer.isIntegral(context, inputNumber, Integer.valueOf(3)));
+
+        // nulls
+        doReturn(Integer.class).when(renderer).getTypeFromValueExpression(context, inputNumber);
+        assertTrue(renderer.isIntegral(context, inputNumber, null));
+        doReturn(Short.class).when(renderer).getTypeFromValueExpression(context, inputNumber);
+        assertTrue(renderer.isIntegral(context, inputNumber, null));
+        doReturn(Byte.class).when(renderer).getTypeFromValueExpression(context, inputNumber);
+        assertTrue(renderer.isIntegral(context, inputNumber, null));
+        doReturn(BigInteger.class).when(renderer).getTypeFromValueExpression(context, inputNumber);
+        assertTrue(renderer.isIntegral(context, inputNumber, null));
+        doReturn(Long.class).when(renderer).getTypeFromValueExpression(context, inputNumber);
+        assertTrue(renderer.isIntegral(context, inputNumber, null));
+        doReturn(BigDecimal.class).when(renderer).getTypeFromValueExpression(context, inputNumber);
+        assertFalse(renderer.isIntegral(context, inputNumber, null));
+        // GitHub #11791
+        doReturn(Number.class).when(renderer).getTypeFromValueExpression(context, inputNumber);
+        assertFalse(renderer.isIntegral(context, inputNumber, null));
+    }
+
 }