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

commit 7fb9b0aa6879487d236fe9fc3839e109278d74b8
Author: James Bognar <[email protected]>
AuthorDate: Sat Dec 6 10:38:22 2025 -0500

    Marshall module improvements
---
 .../a/rttests/NameProperty_RoundTripTest.java      | 105 ++++++++++++++++++---
 .../a/rttests/ParentProperty_RoundTripTest.java    | 100 ++++++++++++++++++--
 .../annotation/NamePropertyAnnotation_Test.java    |  26 +++++
 .../annotation/ParentPropertyAnnotation_Test.java  |  29 ++++++
 4 files changed, 239 insertions(+), 21 deletions(-)

diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/a/rttests/NameProperty_RoundTripTest.java
 
b/juneau-utest/src/test/java/org/apache/juneau/a/rttests/NameProperty_RoundTripTest.java
index e73c2c1608..fc844d2791 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/a/rttests/NameProperty_RoundTripTest.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/a/rttests/NameProperty_RoundTripTest.java
@@ -38,28 +38,28 @@ class NameProperty_RoundTripTest extends RoundTripTest_Base 
{
        @ParameterizedTest
        @MethodSource("testers")
        void a01_nameProperty(RoundTrip_Tester t) throws Exception {
-               var x = new A().init();
+               var x = new NamePropertyMethodContainer().init();
                x = t.roundTrip(x);
-               assertBean(x, "a2{f2},m{k1{f2}}", "{2},{{2}}");
+               assertBean(x, "bean{f2},m{k1{f2}}", "{2},{{2}}");
                if (t.isValidationOnly())
                        return;
-               assertBean(x, "a2{name}", "{a2}");
+               assertBean(x, "bean{name}", "{bean}");
                assertBean(x, "m{k1{name}}", "{{k1}}");
        }
 
-       public static class A {
-               public A2 a2;
-               public Map<String,A2> m;
+       public static class NamePropertyMethodContainer {
+               public NamePropertyMethodBean bean;
+               public Map<String,NamePropertyMethodBean> m;
 
-               A init() {
-                       a2 = new A2().init();
+               NamePropertyMethodContainer init() {
+                       bean = new NamePropertyMethodBean().init();
                        m = new LinkedHashMap<>();
-                       m.put("k1", new A2().init());
+                       m.put("k1", new NamePropertyMethodBean().init());
                        return this;
                }
 
        }
-       public static class A2 {
+       public static class NamePropertyMethodBean {
                String name;
                public int f2;
 
@@ -68,7 +68,90 @@ class NameProperty_RoundTripTest extends RoundTripTest_Base {
                        this.name = name;
                }
 
-               A2 init() {
+               NamePropertyMethodBean init() {
+                       f2 = 2;
+                       return this;
+               }
+       }
+
+       
//====================================================================================================
+       // @NameProperty field.
+       
//====================================================================================================
+
+       @ParameterizedTest
+       @MethodSource("testers")
+       void a02_namePropertyField(RoundTrip_Tester t) throws Exception {
+               var x = new NamePropertyFieldContainer().init();
+               x = t.roundTrip(x);
+               assertBean(x, "bean{f2},m{k1{f2}}", "{2},{{2}}");
+               if (t.isValidationOnly())
+                       return;
+               assertBean(x, "bean{name}", "{bean}");
+               assertBean(x, "m{k1{name}}", "{{k1}}");
+       }
+
+       public static class NamePropertyFieldContainer {
+               public NamePropertyFieldBean bean;
+               public Map<String,NamePropertyFieldBean> m;
+
+               NamePropertyFieldContainer init() {
+                       bean = new NamePropertyFieldBean().init();
+                       m = new LinkedHashMap<>();
+                       m.put("k1", new NamePropertyFieldBean().init());
+                       return this;
+               }
+       }
+       public static class NamePropertyFieldBean {
+               @NameProperty
+               public String name;
+               public int f2;
+
+               NamePropertyFieldBean init() {
+                       f2 = 2;
+                       return this;
+               }
+       }
+
+       
//====================================================================================================
+       // @NameProperty read-only (getter only, no setter).
+       
//====================================================================================================
+
+       @ParameterizedTest
+       @MethodSource("testers")
+       void a03_readOnlyNameProperty(RoundTrip_Tester t) throws Exception {
+               var x = new ReadOnlyNamePropertyContainer().init();
+               var originalName = x.bean.getName(); // Should be "initialName"
+               x = t.roundTrip(x);
+               assertBean(x, "bean{f2},m{k1{f2}}", "{2},{{2}}");
+               if (t.isValidationOnly())
+                       return;
+               // The name should NOT have changed because the property is 
read-only
+               assertEquals(originalName, x.bean.getName(), "Read-only name 
property should not be set by parser");
+               assertBean(x, "bean{name}", "{initialName}");
+               assertBean(x, "m{k1{name}}", "{{initialName}}");
+       }
+
+       public static class ReadOnlyNamePropertyContainer {
+               public ReadOnlyNamePropertyBean bean;
+               public Map<String,ReadOnlyNamePropertyBean> m;
+
+               ReadOnlyNamePropertyContainer init() {
+                       bean = new ReadOnlyNamePropertyBean().init();
+                       m = new LinkedHashMap<>();
+                       m.put("k1", new ReadOnlyNamePropertyBean().init());
+                       return this;
+               }
+       }
+       public static class ReadOnlyNamePropertyBean {
+               private String name = "initialName";
+               public int f2;
+
+               @NameProperty
+               public String getName() {
+                       return name;
+               }
+
+               ReadOnlyNamePropertyBean init() {
                        f2 = 2;
                        return this;
                }
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/a/rttests/ParentProperty_RoundTripTest.java
 
b/juneau-utest/src/test/java/org/apache/juneau/a/rttests/ParentProperty_RoundTripTest.java
index c460a87f03..1c34b97d35 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/a/rttests/ParentProperty_RoundTripTest.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/a/rttests/ParentProperty_RoundTripTest.java
@@ -35,34 +35,114 @@ class ParentProperty_RoundTripTest extends 
RoundTripTest_Base {
        @ParameterizedTest
        @MethodSource("testers")
        void a01_parentProperty(RoundTrip_Tester t) throws Exception {
-               var x = new B().init();
+               var x = new ParentPropertyMethodContainer().init();
                x = t.roundTrip(x);
                if (t.isValidationOnly())
                        return;
-               assertEquals(x.f1, x.b2.parent.f1);
+               assertEquals(x.f1, x.bean.parent.f1);
        }
 
-       public static class B {
+       public static class ParentPropertyMethodContainer {
                public int f1;
-               public B2 b2;
+               public ParentPropertyMethodBean bean;
 
-               B init() {
+               ParentPropertyMethodContainer init() {
                        f1 = 1;
-                       b2 = new B2().init();
+                       bean = new ParentPropertyMethodBean().init();
                        return this;
                }
 
        }
-       public static class B2 {
-               B parent;
+       public static class ParentPropertyMethodBean {
+               ParentPropertyMethodContainer parent;
                public int f2;
 
                @ParentProperty
-               protected void setParent(B v) {
+               protected void setParent(ParentPropertyMethodContainer v) {
                        parent = v;
                }
 
-               B2 init() {
+               ParentPropertyMethodBean init() {
+                       f2 = 2;
+                       return this;
+               }
+       }
+
+       
//====================================================================================================
+       // @ParentProperty field.
+       
//====================================================================================================
+
+       @ParameterizedTest
+       @MethodSource("testers")
+       void a02_parentPropertyField(RoundTrip_Tester t) throws Exception {
+               var x = new ParentPropertyFieldContainer().init();
+               x = t.roundTrip(x);
+               if (t.isValidationOnly())
+                       return;
+               assertEquals(x.f1, x.bean.parent.f1);
+       }
+
+       public static class ParentPropertyFieldContainer {
+               public int f1;
+               public ParentPropertyFieldBean bean;
+
+               ParentPropertyFieldContainer init() {
+                       f1 = 1;
+                       bean = new ParentPropertyFieldBean().init();
+                       return this;
+               }
+       }
+       public static class ParentPropertyFieldBean {
+               @ParentProperty
+               public ParentPropertyFieldContainer parent;
+               public int f2;
+
+               ParentPropertyFieldBean init() {
+                       f2 = 2;
+                       return this;
+               }
+       }
+
+       
//====================================================================================================
+       // @ParentProperty read-only (getter only, no setter).
+       
//====================================================================================================
+
+       @ParameterizedTest
+       @MethodSource("testers")
+       void a03_readOnlyParentProperty(RoundTrip_Tester t) throws Exception {
+               var x = new ReadOnlyParentPropertyContainer().init();
+               // Initially, parent should be null (read-only property, can't 
be set)
+               assertNull(x.bean.getParent(), "Read-only parent property 
should initially be null");
+               x = t.roundTrip(x);
+               if (t.isValidationOnly())
+                       return;
+               // After round-trip, parent should still be null because parser 
won't set read-only properties
+               assertNull(x.bean.getParent(), "Read-only parent property 
should not be set by parser");
+               // Verify the object structure is still correct
+               assertEquals(1, x.f1);
+               assertEquals(2, x.bean.f2);
+       }
+
+       public static class ReadOnlyParentPropertyContainer {
+               public int f1;
+               public ReadOnlyParentPropertyBean bean;
+
+               ReadOnlyParentPropertyContainer init() {
+                       f1 = 1;
+                       bean = new ReadOnlyParentPropertyBean().init();
+                       return this;
+               }
+       }
+       public static class ReadOnlyParentPropertyBean {
+               private ReadOnlyParentPropertyContainer parent;
+               public int f2;
+
+               @ParentProperty
+               public ReadOnlyParentPropertyContainer getParent() {
+                       return parent;
+               }
+
+               ReadOnlyParentPropertyBean init() {
                        f2 = 2;
                        return this;
                }
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/annotation/NamePropertyAnnotation_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/annotation/NamePropertyAnnotation_Test.java
index f8455e4cd0..ed4a917751 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/annotation/NamePropertyAnnotation_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/annotation/NamePropertyAnnotation_Test.java
@@ -21,6 +21,7 @@ import static org.apache.juneau.junit.bct.BctAssertions.*;
 import static org.junit.jupiter.api.Assertions.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.commons.reflect.ExecutableException;
 import org.junit.jupiter.api.*;
 
 class NamePropertyAnnotation_Test extends TestBase {
@@ -210,4 +211,29 @@ class NamePropertyAnnotation_Test extends TestBase {
                assertEquals(42, prop.get(bean));
                assertEquals(Integer.valueOf(42), bean.getId());
        }
+
+       public static class TestBeanWithReadOnlyNameProperty {
+               private String name = "defaultName";
+
+               @NameProperty
+               public String getName() {
+                       return name;
+               }
+       }
+
+       @Test void e06_readOnlyNameProperty() throws Exception {
+               var bc = BeanContext.DEFAULT;
+               var cm = 
bc.getClassMeta(TestBeanWithReadOnlyNameProperty.class);
+               var prop = cm.getNameProperty();
+               assertNotNull(prop, "NameProperty should be found even if 
read-only");
+               assertFalse(prop.canWrite(), "Should not have setter");
+               assertTrue(prop.canRead(), "Should have getter");
+
+               var bean = new TestBeanWithReadOnlyNameProperty();
+               assertEquals("defaultName", prop.get(bean));
+
+               // Verify that set() throws an exception
+               var ex = assertThrows(ExecutableException.class, () -> 
prop.set(bean, "newName"));
+               assertTrue(ex.getMessage().contains("No setter defined"), 
"Should throw exception when trying to set read-only property");
+       }
 }
\ No newline at end of file
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/annotation/ParentPropertyAnnotation_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/annotation/ParentPropertyAnnotation_Test.java
index 51fd3565a2..cb7f675042 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/annotation/ParentPropertyAnnotation_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/annotation/ParentPropertyAnnotation_Test.java
@@ -21,6 +21,7 @@ import static org.apache.juneau.junit.bct.BctAssertions.*;
 import static org.junit.jupiter.api.Assertions.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.commons.reflect.ExecutableException;
 import org.junit.jupiter.api.*;
 
 class ParentPropertyAnnotation_Test extends TestBase {
@@ -170,4 +171,32 @@ class ParentPropertyAnnotation_Test extends TestBase {
                var prop = cm.getParentProperty();
                assertNull(prop, "ParentProperty should not be found on String 
class");
        }
+
+       public static class TestBeanWithReadOnlyParentProperty {
+               private ParentBean parent = new ParentBean();
+
+               @ParentProperty
+               public ParentBean getParent() {
+                       return parent;
+               }
+       }
+
+       @Test void e04_readOnlyParentProperty() throws Exception {
+               var bc = BeanContext.DEFAULT;
+               var cm = 
bc.getClassMeta(TestBeanWithReadOnlyParentProperty.class);
+               var prop = cm.getParentProperty();
+               assertNotNull(prop, "ParentProperty should be found even if 
read-only");
+               assertFalse(prop.canWrite(), "Should not have setter");
+               assertTrue(prop.canRead(), "Should have getter");
+
+               var bean = new TestBeanWithReadOnlyParentProperty();
+               var parent = (ParentBean)prop.get(bean);
+               assertNotNull(parent, "Should be able to get parent");
+               assertEquals(42, parent.value);
+
+               // Verify that set() throws an exception
+               var newParent = new ParentBean();
+               var ex = assertThrows(ExecutableException.class, () -> 
prop.set(bean, newParent));
+               assertTrue(ex.getMessage().contains("No setter defined"), 
"Should throw exception when trying to set read-only property");
+       }
 }
\ No newline at end of file

Reply via email to