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 0c3a1ea4fe New BeanCreator API
0c3a1ea4fe is described below
commit 0c3a1ea4febca7a89902fb399b683c31a2054f68
Author: James Bognar <[email protected]>
AuthorDate: Wed Jan 21 11:09:48 2026 -0500
New BeanCreator API
---
.../juneau/commons/reflect/AnnotationInfo.java | 2 +-
.../apache/juneau/commons/reflect/FieldInfo.java | 53 +++++++++++-
.../juneau/commons/reflect/FieldInfo_Test.java | 95 +++++++++++++++++++++-
3 files changed, 147 insertions(+), 3 deletions(-)
diff --git
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/AnnotationInfo.java
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/AnnotationInfo.java
index da01c79b6a..ff43510ff0 100644
---
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/AnnotationInfo.java
+++
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/AnnotationInfo.java
@@ -697,7 +697,7 @@ public class AnnotationInfo<T extends Annotation> {
*
* @return A new map showing the attributes of this annotation info.
*/
- protected FluentMap<String,Object> properties() {
+ public FluentMap<String,Object> properties() {
// @formatter:off
var ca = info(a.annotationType());
var ja = mapb().sorted().buildFluent(); // NOAI
diff --git
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/FieldInfo.java
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/FieldInfo.java
index 5c43f8bba3..a6ea07b7b7 100644
---
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/FieldInfo.java
+++
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/FieldInfo.java
@@ -131,6 +131,7 @@ public class FieldInfo extends AccessibleInfo implements
Comparable<FieldInfo>,
private final Supplier<ClassInfo> type;
private final Supplier<List<AnnotationInfo<Annotation>>> annotations;
// All annotations declared directly on this field.
private final Supplier<String> fullName; // Fully qualified field name
(declaring-class.field-name).
+ private final Supplier<String> toString; // String representation with
modifiers, type, and full name.
/**
* Constructor.
@@ -151,6 +152,7 @@ public class FieldInfo extends AccessibleInfo implements
Comparable<FieldInfo>,
this.type = mem(() -> ClassInfo.of(inner.getType(),
inner.getGenericType()));
this.annotations = mem(() ->
stream(inner.getAnnotations()).flatMap(a ->
AnnotationUtils.streamRepeated(a)).map(a -> ai(this, a)).toList());
this.fullName = mem(this::findFullName);
+ this.toString = mem(this::findToString);
}
/**
@@ -480,9 +482,58 @@ public class FieldInfo extends AccessibleInfo implements
Comparable<FieldInfo>,
// Annotatable interface methods
//-----------------------------------------------------------------------------------------------------------------
+ /**
+ * Returns a detailed string representation of this field.
+ *
+ * <p>
+ * The returned string includes:
+ * <ul>
+ * <li>Modifiers (public, private, protected, static, final,
volatile, transient)
+ * <li>Field type with generics (e.g., "List<String>")
+ * <li>Fully qualified field name (declaring-class.field-name)
+ * </ul>
+ *
+ * <h5 class='section'>Examples:</h5>
+ * <p class='bjava'>
+ * <jc>// Simple field</jc>
+ * FieldInfo <jv>fi</jv> = ...;
+ * <jv>fi</jv>.toString();
+ * <jc>// Returns: "public java.lang.String
org.example.MyClass.name"</jc>
+ *
+ * <jc>// Static final field</jc>
+ * <jc>// Returns: "public static final int
org.example.MyClass.MAX_VALUE"</jc>
+ *
+ * <jc>// Generic field</jc>
+ * <jc>// Returns: "private java.util.List<java.lang.String>
org.example.MyClass.items"</jc>
+ *
+ * <jc>// Volatile field</jc>
+ * <jc>// Returns: "volatile boolean org.example.MyClass.flag"</jc>
+ * </p>
+ *
+ * @return A detailed string representation including modifiers, type,
and full name.
+ */
@Override
public String toString() {
- return cn(inner.getDeclaringClass()) + "." + inner.getName();
+ return toString.get();
+ }
+
+ private String findToString() {
+ var sb = new StringBuilder(256);
+
+ // Modifiers
+ var mods = Modifier.toString(getModifiers());
+ if (nn(mods) && ! mods.isEmpty()) {
+ sb.append(mods).append(" ");
+ }
+
+ // Field type (use generic type to show generics)
+ var genericType = inner.getGenericType();
+ ClassInfo.of(genericType).appendNameFormatted(sb, FULL, true,
'$', BRACKETS);
+
+ // Fully qualified field name
+ sb.append(" ").append(getNameFull());
+
+ return sb.toString();
}
private String findFullName() {
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/FieldInfo_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/FieldInfo_Test.java
index 450f7e773c..378d981b24 100644
---
a/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/FieldInfo_Test.java
+++
b/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/FieldInfo_Test.java
@@ -670,7 +670,100 @@ class FieldInfo_Test extends TestBase {
//====================================================================================================
@Test
void a031_toString() {
-
assertEquals("org.apache.juneau.commons.reflect.FieldInfo_Test$E.a1",
e_a1.toString());
+ // e_a1 is a public int field, new toString() includes
modifiers and type
+ assertEquals("public int
org.apache.juneau.commons.reflect.FieldInfo_Test$E.a1", e_a1.toString());
+ }
+
+ @Test
+ void a032_toString_comprehensive() {
+ var ci = ClassInfo.of(ToStringTestClass.class);
+
+ // Public field
+ var publicField = ci.getPublicField(x ->
x.hasName("publicField")).get();
+ assertEquals("public int
org.apache.juneau.commons.reflect.FieldInfo_Test$ToStringTestClass.publicField",
publicField.toString());
+
+ // Private field
+ var privateField = ci.getDeclaredField(x ->
x.hasName("privateField")).get();
+ assertEquals("private java.lang.String
org.apache.juneau.commons.reflect.FieldInfo_Test$ToStringTestClass.privateField",
privateField.toString());
+
+ // Protected field
+ var protectedField = ci.getDeclaredField(x ->
x.hasName("protectedField")).get();
+ assertEquals("protected boolean
org.apache.juneau.commons.reflect.FieldInfo_Test$ToStringTestClass.protectedField",
protectedField.toString());
+
+ // Package-private field
+ var packageField = ci.getDeclaredField(x ->
x.hasName("packageField")).get();
+ assertEquals("double
org.apache.juneau.commons.reflect.FieldInfo_Test$ToStringTestClass.packageField",
packageField.toString());
+
+ // Static field
+ var staticField = ci.getPublicField(x ->
x.hasName("staticField")).get();
+ assertEquals("public static long
org.apache.juneau.commons.reflect.FieldInfo_Test$ToStringTestClass.staticField",
staticField.toString());
+
+ // Final field
+ var finalField = ci.getPublicField(x ->
x.hasName("finalField")).get();
+ assertEquals("public static final int
org.apache.juneau.commons.reflect.FieldInfo_Test$ToStringTestClass.finalField",
finalField.toString());
+
+ // Volatile field
+ var volatileField = ci.getPublicField(x ->
x.hasName("volatileField")).get();
+ assertEquals("public volatile boolean
org.apache.juneau.commons.reflect.FieldInfo_Test$ToStringTestClass.volatileField",
volatileField.toString());
+
+ // Transient field
+ var transientField = ci.getPublicField(x ->
x.hasName("transientField")).get();
+ assertEquals("public transient java.lang.Object
org.apache.juneau.commons.reflect.FieldInfo_Test$ToStringTestClass.transientField",
transientField.toString());
+
+ // Generic field (private, so use getDeclaredField)
+ var genericField = ci.getDeclaredField(x ->
x.hasName("genericField")).get();
+ assertEquals("private java.util.List<java.lang.String>
org.apache.juneau.commons.reflect.FieldInfo_Test$ToStringTestClass.genericField",
genericField.toString());
+
+ // Generic field with multiple type parameters (private, so use
getDeclaredField)
+ var mapField = ci.getDeclaredField(x ->
x.hasName("mapField")).get();
+ assertEquals("private
java.util.Map<java.lang.String,java.lang.Integer>
org.apache.juneau.commons.reflect.FieldInfo_Test$ToStringTestClass.mapField",
mapField.toString());
+
+ // Array field
+ var arrayField = ci.getPublicField(x ->
x.hasName("arrayField")).get();
+ assertEquals("public int[]
org.apache.juneau.commons.reflect.FieldInfo_Test$ToStringTestClass.arrayField",
arrayField.toString());
+
+ // Multi-dimensional array field
+ var matrixField = ci.getPublicField(x ->
x.hasName("matrixField")).get();
+ assertEquals("public java.lang.String[][]
org.apache.juneau.commons.reflect.FieldInfo_Test$ToStringTestClass.matrixField",
matrixField.toString());
+
+ // Generic array field
+ var genericArrayField = ci.getPublicField(x ->
x.hasName("genericArrayField")).get();
+ assertEquals("public java.util.List<java.lang.String>[]
org.apache.juneau.commons.reflect.FieldInfo_Test$ToStringTestClass.genericArrayField",
genericArrayField.toString());
+
+ // Primitive types
+ var byteField = ci.getPublicField(x ->
x.hasName("byteField")).get();
+ assertEquals("public byte
org.apache.juneau.commons.reflect.FieldInfo_Test$ToStringTestClass.byteField",
byteField.toString());
+
+ var charField = ci.getPublicField(x ->
x.hasName("charField")).get();
+ assertEquals("public char
org.apache.juneau.commons.reflect.FieldInfo_Test$ToStringTestClass.charField",
charField.toString());
+
+ var floatField = ci.getPublicField(x ->
x.hasName("floatField")).get();
+ assertEquals("public float
org.apache.juneau.commons.reflect.FieldInfo_Test$ToStringTestClass.floatField",
floatField.toString());
+
+ // Multiple modifiers
+ var staticFinalField = ci.getPublicField(x ->
x.hasName("staticFinalField")).get();
+ assertEquals("public static final java.lang.String
org.apache.juneau.commons.reflect.FieldInfo_Test$ToStringTestClass.staticFinalField",
staticFinalField.toString());
+ }
+
+ // Test class for toString() comprehensive tests
+ public static class ToStringTestClass {
+ public int publicField;
+ private String privateField;
+ protected boolean protectedField;
+ double packageField;
+ public static long staticField;
+ public static final int finalField = 42;
+ public volatile boolean volatileField;
+ public transient Object transientField;
+ private java.util.List<String> genericField;
+ private java.util.Map<String, Integer> mapField;
+ public int[] arrayField;
+ public String[][] matrixField;
+ public java.util.List<String>[] genericArrayField;
+ public byte byteField;
+ public char charField;
+ public float floatField;
+ public static final String staticFinalField = "constant";
}
//====================================================================================================