This is an automated email from the ASF dual-hosted git repository.

jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git


The following commit(s) were added to refs/heads/master by this push:
     new ef8410d521 New BeanCreator API
ef8410d521 is described below

commit ef8410d521fef0564d84fa6ad2d18886568e0cb9
Author: James Bognar <[email protected]>
AuthorDate: Wed Jan 21 11:05:05 2026 -0500

    New BeanCreator API
---
 .../juneau/commons/reflect/ParameterInfo.java      | 77 +++++++++++++++++-
 .../commons/reflect/ExecutableInfo_Test.java       | 17 +++-
 .../juneau/commons/reflect/ParameterInfo_Test.java | 90 +++++++++++++++++++++-
 3 files changed, 177 insertions(+), 7 deletions(-)

diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/ParameterInfo.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/ParameterInfo.java
index f24312c370..e8af8326e8 100644
--- 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/ParameterInfo.java
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/ParameterInfo.java
@@ -16,6 +16,8 @@
  */
 package org.apache.juneau.commons.reflect;
 
+import static org.apache.juneau.commons.reflect.ClassArrayFormat.*;
+import static org.apache.juneau.commons.reflect.ClassNameFormat.*;
 import static org.apache.juneau.commons.utils.AssertionUtils.*;
 import static org.apache.juneau.commons.utils.CollectionUtils.*;
 import static org.apache.juneau.commons.utils.ThrowableUtils.*;
@@ -155,6 +157,8 @@ public class ParameterInfo extends ElementInfo implements 
Annotatable {
 
        private final ResettableSupplier<String> resolvedQualifier = 
memr(this::findQualifierInternal);  // Resolved qualifier from @Named or 
@Qualifier annotation.
 
+       private final Supplier<String> toString;  // String representation with 
modifiers, type, name, and varargs flag.
+
        /**
         * Constructor.
         *
@@ -177,6 +181,7 @@ public class ParameterInfo extends ElementInfo implements 
Annotatable {
                this.type = type;
                this.annotations = mem(() -> 
stream(inner.getAnnotations()).flatMap(a -> 
AnnotationUtils.streamRepeated(a)).map(a -> ai(this, a)).toList());
                this.matchingParameters = mem(this::findMatchingParameters);
+               this.toString = mem(this::findToString);
        }
 
        /**
@@ -612,9 +617,79 @@ public class ParameterInfo extends ElementInfo implements 
Annotatable {
         */
        public boolean isVarArgs() { return inner.isVarArgs(); }
 
+       /**
+        * Returns a detailed string representation of this parameter.
+        *
+        * <p>
+        * The returned string includes:
+        * <ul>
+        *      <li>Modifiers (final)
+        *      <li>Parameter type with generics (e.g., "List&lt;String&gt;")
+        *      <li>Parameter name (if available)
+        *      <li>Varargs indicator (if applicable)
+        * </ul>
+        *
+        * <h5 class='section'>Examples:</h5>
+        * <p class='bjava'>
+        *      <jc>// Simple parameter</jc>
+        *      ParameterInfo <jv>pi</jv> = ...;
+        *      <jv>pi</jv>.toString();
+        *      <jc>// Returns: "java.lang.String name"</jc>
+        *
+        *      <jc>// Final parameter</jc>
+        *      <jc>// Returns: "final java.lang.String name"</jc>
+        *
+        *      <jc>// Generic parameter</jc>
+        *      <jc>// Returns: "java.util.List&lt;java.lang.String&gt; 
items"</jc>
+        *
+        *      <jc>// Varargs parameter</jc>
+        *      <jc>// Returns: "java.lang.String... values"</jc>
+        *
+        *      <jc>// Parameter without name (fallback)</jc>
+        *      <jc>// Returns: "int arg0"</jc>
+        * </p>
+        *
+        * @return A detailed string representation including modifiers, type, 
name, and varargs flag.
+        */
        @Override
        public String toString() {
-               return (executable.getNameSimple()) + "[" + index + "]";
+               return toString.get();
+       }
+
+       private String findToString() {
+               var sb = new StringBuilder(128);
+
+               // Modifiers (final is common for parameters)
+               var mods = Modifier.toString(getModifiers());
+               if (nn(mods) && ! mods.isEmpty()) {
+                       sb.append(mods).append(" ");
+               }
+
+               // Parameter type (use generic type if available to show 
generics)
+               var paramType = getParameterizedType();
+               
+               // For varargs, we need to get the component type and display 
it with "..." instead of "[]"
+               if (isVarArgs()) {
+                       // Get the component type of the array
+                       var typeInfo = ClassInfo.of(paramType);
+                       var componentType = typeInfo.getComponentType();
+                       // Display the component type without array brackets, 
then add "..."
+                       componentType.appendNameFormatted(sb, FULL, true, '$', 
BRACKETS);
+                       sb.append("...");
+               } else {
+                       ClassInfo.of(paramType).appendNameFormatted(sb, FULL, 
true, '$', BRACKETS);
+               }
+
+               // Parameter name (if available)
+               var name = getResolvedName();
+               if (nn(name)) {
+                       sb.append(" ").append(name);
+               } else {
+                       // Fallback to index-based name if no name available
+                       sb.append(" arg").append(index);
+               }
+
+               return sb.toString();
        }
 
        private List<ParameterInfo> findMatchingParameters() {
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/ExecutableInfo_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/ExecutableInfo_Test.java
index f55ab88433..f153989501 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/ExecutableInfo_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/ExecutableInfo_Test.java
@@ -343,8 +343,13 @@ class ExecutableInfo_Test extends TestBase {
        
//====================================================================================================
        @Test
        void a011_getParameter() {
-               check("B[0]", b_c2.getParameter(0));
-               check("m[0]", b_m2.getParameter(0));
+               // b_c2 is B(String s) constructor, parameter name may or may 
not be available in bytecode
+               var param1 = b_c2.getParameter(0).toString();
+               assertTrue(param1.equals("java.lang.String s") || 
param1.equals("java.lang.String arg0"), "Expected 'java.lang.String s' or 
'java.lang.String arg0', got: " + param1);
+               
+               // b_m2 is m(String s) method, parameter name may or may not be 
available in bytecode
+               var param2 = b_m2.getParameter(0).toString();
+               assertTrue(param2.equals("java.lang.String s") || 
param2.equals("java.lang.String arg0"), "Expected 'java.lang.String s' or 
'java.lang.String arg0', got: " + param2);
                
                // Index out of bounds
                assertThrowsWithMessage(IndexOutOfBoundsException.class, 
"Invalid index '0'.  No parameters.", ()->b_c1.getParameter(0));
@@ -369,9 +374,13 @@ class ExecutableInfo_Test extends TestBase {
        @Test
        void a013_getParameters() {
                check("", b_c1.getParameters());
-               check("B[0]", b_c2.getParameters());
+               // b_c2 is B(String s) constructor, parameter name may or may 
not be available in bytecode
+               var params1 = 
b_c2.getParameters().stream().map(ParameterInfo::toString).collect(Collectors.joining(","));
+               assertTrue(params1.equals("java.lang.String s") || 
params1.equals("java.lang.String arg0"), "Expected 'java.lang.String s' or 
'java.lang.String arg0', got: " + params1);
                check("", b_m1.getParameters());
-               check("m[0]", b_m2.getParameters());
+               // b_m2 is m(String s) method, parameter name may or may not be 
available in bytecode
+               var params2 = 
b_m2.getParameters().stream().map(ParameterInfo::toString).collect(Collectors.joining(","));
+               assertTrue(params2.equals("java.lang.String s") || 
params2.equals("java.lang.String arg0"), "Expected 'java.lang.String s' or 
'java.lang.String arg0', got: " + params2);
                
                // Test caching - should return same result
                check("", b_c1.getParameters());
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/ParameterInfo_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/ParameterInfo_Test.java
index 6f42a82965..8071272d65 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/ParameterInfo_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/ParameterInfo_Test.java
@@ -267,7 +267,22 @@ class ParameterInfo_Test extends TestBase {
                public PC4(String foo, int bar) {}  // NOSONAR
        }
        public static class PC5 extends PC4 {
-               public PC5(String foo) { super(foo, 0); }  // NOSONAR
+               public PC5(String foo) { super(foo, 0); }
+       }
+
+       // Test class for toString() comprehensive tests
+       public static class ToStringTestClass {
+               public void basicMethod(int a, String b) {}  // NOSONAR
+               public void namedMethod(@org.apache.juneau.annotation.Name("x") 
int x, @org.apache.juneau.annotation.Name("y") String y) {}  // NOSONAR
+               public void finalMethod(final int value) {}  // NOSONAR
+               public void 
genericMethod(@org.apache.juneau.annotation.Name("list") java.util.List<String> 
list, @org.apache.juneau.annotation.Name("map") java.util.Map<String, Integer> 
map) {}  // NOSONAR
+               public void 
varargsMethod(@org.apache.juneau.annotation.Name("values") String... values) {} 
 // NOSONAR
+               public void finalVarargsMethod(final 
@org.apache.juneau.annotation.Name("args") String... args) {}  // NOSONAR
+               public void 
arrayMethod(@org.apache.juneau.annotation.Name("numbers") int[] numbers, 
@org.apache.juneau.annotation.Name("matrix") String[][] matrix) {}  // NOSONAR
+               public void 
genericArrayMethod(@org.apache.juneau.annotation.Name("lists") 
java.util.List<String>[] lists) {}  // NOSONAR
+               public void 
primitiveMethod(@org.apache.juneau.annotation.Name("flag") boolean flag, 
@org.apache.juneau.annotation.Name("value") double value, 
@org.apache.juneau.annotation.Name("count") long count) {}  // NOSONAR
+               public 
ToStringTestClass(@org.apache.juneau.annotation.Name("id") int id, 
@org.apache.juneau.annotation.Name("name") String name) {}  // NOSONAR
+               public void unnamedMethod(int param1, String param2) {}  // 
NOSONAR - no @Name annotations, will fallback to arg0, arg1
        }
 
        public static class PC6 {
@@ -864,7 +879,78 @@ class ParameterInfo_Test extends TestBase {
        
//====================================================================================================
        @Test
        void a029_toString() {
-               assertEquals("a1[1]", e_a1_b.toString());
+               // e_a1_b is the second parameter of method a1(int a, 
@Name("b") int b)
+               // It has @Name("b") annotation, so resolved name is "b"
+               assertEquals("int b", e_a1_b.toString());
+       }
+
+       @Test
+       void a030_toString_comprehensive() {
+               var ci = ClassInfo.of(ToStringTestClass.class);
+
+               // Basic parameters (names may or may not be available in 
bytecode)
+               var method1 = ci.getPublicMethod(x -> 
x.hasName("basicMethod")).get();
+               var param1_0 = method1.getParameter(0).toString();
+               assertTrue(param1_0.equals("int a") || param1_0.equals("int 
arg0"), "Expected 'int a' or 'int arg0', got: " + param1_0);
+               var param1_1 = method1.getParameter(1).toString();
+               assertTrue(param1_1.equals("java.lang.String b") || 
param1_1.equals("java.lang.String arg1"), "Expected 'java.lang.String b' or 
'java.lang.String arg1', got: " + param1_1);
+
+               // Parameters with @Name annotation (always have names)
+               var method2 = ci.getPublicMethod(x -> 
x.hasName("namedMethod")).get();
+               assertEquals("int x", method2.getParameter(0).toString());
+               assertEquals("java.lang.String y", 
method2.getParameter(1).toString());
+
+               // Final parameters (final modifier may or may not appear 
depending on JVM/environment)
+               // Accept both with and without final modifier
+               var method3 = ci.getPublicMethod(x -> 
x.hasName("finalMethod")).get();
+               var param3_0 = method3.getParameter(0).toString();
+               assertTrue(
+                       param3_0.equals("int value") || param3_0.equals("int 
arg0") ||
+                       param3_0.equals("final int value") || 
param3_0.equals("final int arg0"),
+                       "Expected 'int value', 'int arg0', 'final int value', 
or 'final int arg0', got: " + param3_0);
+
+               // Generic parameters
+               var method4 = ci.getPublicMethod(x -> 
x.hasName("genericMethod")).get();
+               assertEquals("java.util.List<java.lang.String> list", 
method4.getParameter(0).toString());
+               assertEquals("java.util.Map<java.lang.String,java.lang.Integer> 
map", method4.getParameter(1).toString());
+
+               // Varargs parameter
+               var method5 = ci.getPublicMethod(x -> 
x.hasName("varargsMethod")).get();
+               assertEquals("java.lang.String... values", 
method5.getParameter(0).toString());
+
+               // Final varargs parameter (final modifier may or may not 
appear depending on JVM/environment)
+               var method6 = ci.getPublicMethod(x -> 
x.hasName("finalVarargsMethod")).get();
+               var param6_0 = method6.getParameter(0).toString();
+               assertTrue(
+                       param6_0.equals("java.lang.String... args") || 
param6_0.equals("final java.lang.String... args"),
+                       "Expected 'java.lang.String... args' or 'final 
java.lang.String... args', got: " + param6_0);
+
+               // Array parameters
+               var method7 = ci.getPublicMethod(x -> 
x.hasName("arrayMethod")).get();
+               assertEquals("int[] numbers", 
method7.getParameter(0).toString());
+               assertEquals("java.lang.String[][] matrix", 
method7.getParameter(1).toString());
+
+               // Generic array parameters
+               var method8 = ci.getPublicMethod(x -> 
x.hasName("genericArrayMethod")).get();
+               assertEquals("java.util.List<java.lang.String>[] lists", 
method8.getParameter(0).toString());
+
+               // Primitive types
+               var method9 = ci.getPublicMethod(x -> 
x.hasName("primitiveMethod")).get();
+               assertEquals("boolean flag", 
method9.getParameter(0).toString());
+               assertEquals("double value", 
method9.getParameter(1).toString());
+               assertEquals("long count", method9.getParameter(2).toString());
+
+               // Constructor parameters (with @Name annotations, always have 
names)
+               var ctor1 = ci.getPublicConstructor(x -> x.getParameterCount() 
== 2).get();
+               assertEquals("int id", ctor1.getParameter(0).toString());
+               assertEquals("java.lang.String name", 
ctor1.getParameter(1).toString());
+
+               // Parameters without @Name annotations (names may or may not 
be available in bytecode)
+               var method10 = ci.getPublicMethod(x -> 
x.hasName("unnamedMethod")).get();
+               var param10_0 = method10.getParameter(0).toString();
+               assertTrue(param10_0.equals("int param1") || 
param10_0.equals("int arg0"), "Expected 'int param1' or 'int arg0', got: " + 
param10_0);
+               var param10_1 = method10.getParameter(1).toString();
+               assertTrue(param10_1.equals("java.lang.String param2") || 
param10_1.equals("java.lang.String arg1"), "Expected 'java.lang.String param2' 
or 'java.lang.String arg1', got: " + param10_1);
        }
 
        
//====================================================================================================

Reply via email to