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 d40470594d Marshall module improvements
d40470594d is described below

commit d40470594de2e7ce017984c2501b403ef4e333fd
Author: James Bognar <[email protected]>
AuthorDate: Thu Dec 11 18:26:15 2025 -0500

    Marshall module improvements
---
 .../juneau/commons/reflect/ExecutableInfo.java     | 22 +++++++++++++
 .../src/main/java/org/apache/juneau/BeanMeta.java  | 28 +++++++++--------
 .../java/org/apache/juneau/BeanPropertyMeta.java   | 36 +++++++++++-----------
 .../apache/juneau/html/HtmlBeanPropertyMeta.java   |  2 +-
 .../commons/reflect/ExecutableInfo_Test.java       | 32 +++++++++++++++++++
 5 files changed, 89 insertions(+), 31 deletions(-)

diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/ExecutableInfo.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/ExecutableInfo.java
index 653a21462d..8d6f5f0051 100644
--- 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/ExecutableInfo.java
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/ExecutableInfo.java
@@ -87,6 +87,7 @@ public abstract class ExecutableInfo extends AccessibleInfo {
        private final boolean isConstructor;
 
        private final Supplier<List<ParameterInfo>> parameters;  // All 
parameters of this executable.
+       private final Supplier<List<ClassInfo>> parameterTypes;  // All 
parameter types of this executable.
        private final Supplier<List<ClassInfo>> exceptions;  // All exceptions 
declared by this executable.
        private final Supplier<List<AnnotationInfo<Annotation>>> 
declaredAnnotations;  // All annotations declared directly on this executable.
        private final Supplier<String> shortName;  // Short name 
(method/constructor name with parameters).
@@ -109,6 +110,7 @@ public abstract class ExecutableInfo extends AccessibleInfo 
{
                this.inner = inner;
                this.isConstructor = inner instanceof Constructor;
                this.parameters = memoize(this::findParameters);
+               this.parameterTypes = memoize(() -> 
getParameters().stream().map(ParameterInfo::getParameterType).toList());
                this.exceptions = memoize(() -> 
stream(inner.getExceptionTypes()).map(ClassInfo::of).map(ClassInfo.class::cast).toList());
                this.declaredAnnotations = memoize(() -> 
stream(inner.getDeclaredAnnotations()).flatMap(a -> 
AnnotationUtils.streamRepeated(a)).map(a -> ai((Annotatable)this, a)).toList());
                this.shortName = memoize(() -> f("{0}({1})", getSimpleName(), 
getParameters().stream().map(p -> 
p.getParameterType().getNameSimple()).collect(joining(","))));
@@ -321,6 +323,26 @@ public abstract class ExecutableInfo extends 
AccessibleInfo {
         */
        public final List<ParameterInfo> getParameters() { return 
parameters.get(); }
 
+       /**
+        * Returns the parameter types for this executable.
+        *
+        * <p>
+        * This is a convenience method that extracts the parameter types from 
{@link #getParameters()}.
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bjava'>
+        *      <jc>// Get parameter types: void myMethod(String s, int i)</jc>
+        *      MethodInfo <jv>mi</jv> = 
ClassInfo.<jsm>of</jsm>(MyClass.<jk>class</jk>).getMethod(<js>"myMethod"</js>, 
String.<jk>class</jk>, <jk>int</jk>.<jk>class</jk>);
+        *      List&lt;ClassInfo&gt; <jv>paramTypes</jv> = 
<jv>mi</jv>.getParameterTypes();
+        *      <jc>// paramTypes contains ClassInfo for String and int</jc>
+        * </p>
+        *
+        * @return A list of parameter types, never <jk>null</jk>.
+        */
+       public final List<ClassInfo> getParameterTypes() {
+               return parameterTypes.get();
+       }
+
        /**
         * Returns the short name of this executable.
         *
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java
index 84298891aa..37612e492d 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java
@@ -120,11 +120,11 @@ public class BeanMeta<T> {
                                return true;
 
                        // Get the bean property type from the getter/field.
-                       var pt = (Class<?>)null;
+                       var pt = (Class<?>)null;  // TODO - Convert to ClassInfo
                        if (nn(b.getter))
-                               pt = b.getter.getReturnType();
+                               pt = b.getter.getReturnType().inner(); 
                        else if (nn(b.field))
-                               pt = b.field.inner().getType();  // TODO - 
Convert to FieldInfo
+                               pt = b.field.inner().getType();
 
                        // Matches if only a setter is defined.
                        if (pt == null)
@@ -403,7 +403,7 @@ public class BeanMeta<T> {
                var _notABeanReason = (String)null;
                var _properties = Value.<Map<String,BeanPropertyMeta>>empty();
                var _hiddenProperties = 
CollectionUtils.<String,BeanPropertyMeta>map();
-               var _getterProps = CollectionUtils.<Method,String>map();
+               var _getterProps = CollectionUtils.<Method,String>map();  // 
Convert to MethodInfo keys
                var _setterProps = CollectionUtils.<Method,String>map();
                var _dynaProperty = Value.<BeanPropertyMeta>empty();
                var _sortProperties = false;
@@ -435,7 +435,11 @@ public class BeanMeta<T> {
                                        bi = 
Introspector.getBeanInfo(c2.inner(), null);
                                if (nn(bi)) {
                                        for (var pd : 
bi.getPropertyDescriptors()) {
-                                               
normalProps.computeIfAbsent(pd.getName(), n -> BeanPropertyMeta.builder(this, 
n)).setGetter(pd.getReadMethod()).setSetter(pd.getWriteMethod());
+                                               var builder = 
normalProps.computeIfAbsent(pd.getName(), n -> BeanPropertyMeta.builder(this, 
n));
+                                               if (pd.getReadMethod() != null)
+                                                       
builder.setGetter(info(pd.getReadMethod()));
+                                               if (pd.getWriteMethod() != null)
+                                                       
builder.setSetter(pd.getWriteMethod());
                                        }
                                }
 
@@ -458,20 +462,20 @@ public class BeanMeta<T> {
                                // Iterate through all the getters.
                                bms.forEach(x -> {
                                        var pn = x.propertyName;
-                                       var m = x.method;
+                                       var m = x.method;  // TODO - Convert to 
MethodInfo
                                        var mi = info(m);
                                        var bpm = 
normalProps.computeIfAbsent(pn, k -> new BeanPropertyMeta.Builder(this, k));
 
                                        if (x.methodType == GETTER) {
                                                // Two getters.  Pick the best.
                                                if (nn(bpm.getter)) {
-                                                       if (! 
ap.has(Beanp.class, mi) && ap.has(Beanp.class, info(bpm.getter))) {
-                                                               m = bpm.getter; 
 // @Beanp annotated method takes precedence.
-                                                       } else if 
(m.getName().startsWith("is") && bpm.getter.getName().startsWith("get")) {
-                                                               m = bpm.getter; 
 // getX() overrides isX().
+                                                       if (! 
ap.has(Beanp.class, mi) && ap.has(Beanp.class, bpm.getter)) {
+                                                               m = 
bpm.getter.inner();  // @Beanp annotated method takes precedence.
+                                                       } else if 
(m.getName().startsWith("is") && bpm.getter.getSimpleName().startsWith("get")) {
+                                                               m = 
bpm.getter.inner();  // getX() overrides isX().
                                                        }
                                                }
-                                               bpm.setGetter(m);
+                                               bpm.setGetter(info(m));
                                        }
                                });
 
@@ -500,7 +504,7 @@ public class BeanMeta<T> {
                                        if (p.validate(beanContext, 
beanRegistry.get(), typeVarImpls, readOnlyProps, writeOnlyProps)) {
 
                                                if (nn(p.getter))
-                                                       
_getterProps.put(p.getter, p.name);
+                                                       
_getterProps.put(p.getter.inner(), p.name);
 
                                                if (nn(p.setter))
                                                        
_setterProps.put(p.setter, p.name);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java
index 2baaa04d62..fdc9c12ab3 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java
@@ -67,7 +67,8 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
                String name;  // Package-private for BeanMeta access
                FieldInfo field;  // Package-private for BeanMeta access
                FieldInfo innerField;  // Package-private for BeanMeta access
-               Method getter, setter, extraKeys;  // Package-private for 
BeanMeta access. TODO - Replace with MethodInfo fields
+               MethodInfo getter;  // Package-private for BeanMeta access
+               Method setter, extraKeys;  // Package-private for BeanMeta 
access. TODO - Replace with MethodInfo fields
                private boolean isConstructorArg, isUri, isDyna, 
isDynaGetterMap;
                private ClassMeta<?> rawTypeMeta, typeMeta;
                private List<String> properties;
@@ -215,22 +216,20 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
         */
        public BeanPropertyMeta.Builder setField(FieldInfo value) {
                assertArgNotNull("value", value);
-               value.accessible();
-               this.field = value;
-               this.innerField = value;
+               this.field = value.accessible();
+               this.innerField = this.field;
                return this;
        }
 
        /**
         * Sets the getter method for this bean property.
         *
-        * @param value The getter method for this bean property.
+        * @param value The getter method info for this bean property.
         * @return This object.
         */
-       public BeanPropertyMeta.Builder setGetter(Method value) {
+       public BeanPropertyMeta.Builder setGetter(MethodInfo value) {
                assertArgNotNull("value", value);
-               setAccessible(value);
-               this.getter = value;
+               this.getter = value.accessible();
                return this;
        }
 
@@ -297,7 +296,7 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
                        canWrite |= (nn(field) || nn(setter));
 
                        var ifi = innerField;
-                       var gi = getter == null ? null : info(getter);
+                       var gi = getter;
                        var si = setter == null ? null : info(setter);
 
                        if (nn(innerField)) {
@@ -327,7 +326,7 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
                        if (nn(getter)) {
                                var lp = ap.find(Beanp.class, 
gi).stream().map(AnnotationInfo::inner).toList();
                                if (rawTypeMeta == null)
-                                       rawTypeMeta = 
bc.resolveClassMeta(last(lp), getter.getGenericReturnType(), typeVarImpls);
+                                       rawTypeMeta = 
bc.resolveClassMeta(last(lp), getter.inner().getGenericReturnType(), 
typeVarImpls);
                                isUri |= (rawTypeMeta.isUri() || 
ap.has(Uri.class, gi));
                                lp.forEach(x -> {
                                        if (swap == null)
@@ -374,9 +373,9 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
                        if (nn(getter)) {
                                var pt = getter.getParameterTypes();
                                if (isDyna) {
-                                       if (ci.isChildOf(Map.class) && 
pt.length == 0) {
+                                       if (ci.isChildOf(Map.class) && 
isEmpty(pt)) {
                                                isDynaGetterMap = true;
-                                       } else if (pt.length == 1 && pt[0] == 
String.class) {
+                                       } else if (pt.size() == 1 && 
pt.get(0).is(String.class)) {
                                                // OK.
                                        } else {
                                                return false;
@@ -458,7 +457,8 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
        private final FieldInfo field;                                // The 
bean property field (if it has one).
        private final FieldInfo innerField;                                // 
The bean property field (if it has one).
 
-       private final Method getter, setter, extraKeys;           // The bean 
property getter and setter.
+       private final MethodInfo getter;           // The bean property getter.
+       private final Method setter, extraKeys;           // The bean property 
setter and extraKeys.
 
        private final boolean isUri;                              // True if 
this is a URL/URI or annotated with @URI.
        private final boolean isDyna, isDynaGetterMap;            // This is a 
dyna property (i.e. name="*")
@@ -719,7 +719,7 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
                        if (nn(field))
                                ap.find(a, 
field).stream().map(AnnotationInfo::inner).filter(filter).forEach(action);
                        if (nn(getter))
-                               ap.find(a, info(getter), SELF, 
MATCHING_METHODS, RETURN_TYPE, 
PACKAGE).stream().map(AnnotationInfo::inner).filter(filter).forEach(action);
+                               ap.find(a, getter, SELF, MATCHING_METHODS, 
RETURN_TYPE, 
PACKAGE).stream().map(AnnotationInfo::inner).filter(filter).forEach(action);
                        if (nn(setter))
                                ap.find(a, info(setter), SELF, 
MATCHING_METHODS, RETURN_TYPE, 
PACKAGE).stream().map(AnnotationInfo::inner).filter(filter).forEach(action);
                }
@@ -761,7 +761,7 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
                var l = new LinkedList<A>();
                var ap = bc.getAnnotationProvider();
                var fi = field;
-               var gi = getter == null ? null : info(getter);
+               var gi = getter;
                var si = setter == null ? null : info(setter);
                if (a == null)
                        return l;
@@ -772,7 +772,7 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
                }
                if (nn(gi)) {
                        // Walk up the inheritance hierarchy for the getter 
method
-                       forEachParentMethod(getter, parentGetter -> {
+                       forEachParentMethod(getter.inner(), parentGetter -> {
                                ap.find(a, info(parentGetter), SELF, 
MATCHING_METHODS, RETURN_TYPE, PACKAGE).forEach(x -> l.add(x.inner()));
                        });
                        ap.find(a, gi, SELF, MATCHING_METHODS, RETURN_TYPE, 
PACKAGE).forEach(x -> l.add(x.inner()));
@@ -881,9 +881,9 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
        /**
         * Returns the getter method for this property.
         *
-        * @return The getter method for this bean property, or <jk>null</jk> 
if there is no getter method.
+        * @return The getter method info for this bean property, or 
<jk>null</jk> if there is no getter method.
         */
-       public Method getGetter() { return getter; }
+       public MethodInfo getGetter() { return getter; }
 
        /**
         * Returns the field for this property even if the field is private.
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlBeanPropertyMeta.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlBeanPropertyMeta.java
index 608acd1458..2f1aae7f68 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlBeanPropertyMeta.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlBeanPropertyMeta.java
@@ -85,7 +85,7 @@ public class HtmlBeanPropertyMeta extends 
ExtendedBeanPropertyMeta {
                if (nn(bpm.getInnerField()))
                        ap.find(Html.class, bpm.getInnerField()).forEach(x -> 
b.findHtmlInfo(x.inner()));
                if (nn(bpm.getGetter()))
-                       ap.find(Html.class, info(bpm.getGetter())).forEach(x -> 
b.findHtmlInfo(x.inner()));
+                       ap.find(Html.class, bpm.getGetter()).forEach(x -> 
b.findHtmlInfo(x.inner()));
                if (nn(bpm.getSetter()))
                        ap.find(Html.class, info(bpm.getSetter())).forEach(x -> 
b.findHtmlInfo(x.inner()));
 
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 d30f8963d1..f0644a01a4 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
@@ -381,6 +381,38 @@ class ExecutableInfo_Test extends TestBase {
                check("String,int", 
b1.getDeclaredConstructors().get(0).getParameters().stream().map(ParameterInfo::getParameterType).toList());
        }
 
+       
//====================================================================================================
+       // getParameterTypes()
+       
//====================================================================================================
+       @Test
+       void a013a_getParameterTypes() {
+               // Test with no parameters
+               check("", b_c1.getParameterTypes());
+               check("", b_m1.getParameterTypes());
+               
+               // Test with single parameter
+               check("String", b_c2.getParameterTypes());
+               check("String", b_m2.getParameterTypes());
+               
+               // Test with multiple parameters
+               var b1 = ClassInfo.of(B1.class);
+               check("String,int", 
b1.getDeclaredConstructors().get(0).getParameterTypes());
+               
+               // Test with different parameter types
+               check("int", c_c3.getParameterTypes());
+               check("int", c_m3.getParameterTypes());
+               
+               // Test caching - should return same result
+               var types1 = b_c2.getParameterTypes();
+               var types2 = b_c2.getParameterTypes();
+               assertSame(types1, types2, "getParameterTypes() should return 
cached result");
+               
+               // Verify that getParameterTypes() returns the same types as 
getParameters().stream().map(ParameterInfo::getParameterType)
+               var typesFromMethod = b_c2.getParameterTypes();
+               var typesFromParams = 
b_c2.getParameters().stream().map(ParameterInfo::getParameterType).toList();
+               assertEquals(typesFromMethod, typesFromParams, 
"getParameterTypes() should match types from getParameters()");
+       }
+
        
//====================================================================================================
        // getShortName()
        
//====================================================================================================

Reply via email to