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

commit cb048854556ffa2e397718b1eec6f4f1eb97ad72
Author: James Bognar <[email protected]>
AuthorDate: Mon Dec 8 13:36:59 2025 -0500

    Marshall module improvements
---
 .../org/apache/juneau/commons/function/Tuple1.java | 20 ++++++
 .../org/apache/juneau/commons/function/Tuple2.java | 38 +++++++++++
 .../org/apache/juneau/commons/function/Tuple3.java | 29 +++++++++
 .../org/apache/juneau/commons/function/Tuple4.java | 38 +++++++++++
 .../org/apache/juneau/commons/function/Tuple5.java | 47 ++++++++++++++
 .../src/main/java/org/apache/juneau/BeanMeta.java  |  9 +++
 .../src/main/java/org/apache/juneau/ClassMeta.java | 61 +++++++++++++++---
 .../juneau/commons/function/Tuple1_Test.java       | 17 +++++
 .../juneau/commons/function/Tuple2_Test.java       | 31 +++++++++
 .../juneau/commons/function/Tuple3_Test.java       | 45 +++++++++++++
 .../juneau/commons/function/Tuple4_Test.java       | 59 +++++++++++++++++
 .../juneau/commons/function/Tuple5_Test.java       | 73 ++++++++++++++++++++++
 12 files changed, 459 insertions(+), 8 deletions(-)

diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/function/Tuple1.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/function/Tuple1.java
index 86d3df7fdb..0e00ba0feb 100644
--- 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/function/Tuple1.java
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/function/Tuple1.java
@@ -18,6 +18,8 @@ package org.apache.juneau.commons.function;
 
 import static org.apache.juneau.commons.utils.Utils.*;
 
+import java.util.Optional;
+
 import org.apache.juneau.commons.utils.*;
 
 /**
@@ -131,6 +133,24 @@ public class Tuple1<A> {
         */
        public A getA() { return a; }
 
+       /**
+        * Returns the value contained in this tuple wrapped in an {@link 
Optional}.
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bjava'>
+        *      Tuple1&lt;String&gt; <jv>tuple</jv> = 
Tuple1.<jsm>of</jsm>(<js>"hello"</js>);
+        *      Optional&lt;String&gt; <jv>value</jv> = <jv>tuple</jv>.optA();  
<jc>// Returns Optional.of("hello")</jc>
+        *
+        *      Tuple1&lt;String&gt; <jv>tuple2</jv> = 
Tuple1.<jsm>of</jsm>(<jk>null</jk>);
+        *      Optional&lt;String&gt; <jv>value2</jv> = 
<jv>tuple2</jv>.optA();  <jc>// Returns Optional.empty()</jc>
+        * </p>
+        *
+        * @return The value wrapped in an Optional, or Optional.empty() if the 
value is null.
+        */
+       public Optional<A> optA() {
+               return Optional.ofNullable(a);
+       }
+
        @Override /* Overridden from Object */
        public int hashCode() {
                return hashCode;
diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/function/Tuple2.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/function/Tuple2.java
index 663e9269e6..b49e791d3a 100644
--- 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/function/Tuple2.java
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/function/Tuple2.java
@@ -18,6 +18,8 @@ package org.apache.juneau.commons.function;
 
 import static org.apache.juneau.commons.utils.Utils.*;
 
+import java.util.Optional;
+
 import org.apache.juneau.commons.utils.*;
 
 /**
@@ -152,6 +154,42 @@ public class Tuple2<A,B> {
         */
        public B getB() { return b; }
 
+       /**
+        * Returns the first value in this tuple wrapped in an {@link Optional}.
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bjava'>
+        *      Tuple2&lt;String,Integer&gt; <jv>tuple</jv> = 
Tuple2.<jsm>of</jsm>(<js>"hello"</js>, 42);
+        *      Optional&lt;String&gt; <jv>first</jv> = <jv>tuple</jv>.optA();  
<jc>// Returns Optional.of("hello")</jc>
+        *
+        *      Tuple2&lt;String,Integer&gt; <jv>tuple2</jv> = 
Tuple2.<jsm>of</jsm>(<jk>null</jk>, 42);
+        *      Optional&lt;String&gt; <jv>first2</jv> = 
<jv>tuple2</jv>.optA();  <jc>// Returns Optional.empty()</jc>
+        * </p>
+        *
+        * @return The first value wrapped in an Optional, or Optional.empty() 
if the value is null.
+        */
+       public Optional<A> optA() {
+               return Optional.ofNullable(a);
+       }
+
+       /**
+        * Returns the second value in this tuple wrapped in an {@link 
Optional}.
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bjava'>
+        *      Tuple2&lt;String,Integer&gt; <jv>tuple</jv> = 
Tuple2.<jsm>of</jsm>(<js>"hello"</js>, 42);
+        *      Optional&lt;Integer&gt; <jv>second</jv> = 
<jv>tuple</jv>.optB();  <jc>// Returns Optional.of(42)</jc>
+        *
+        *      Tuple2&lt;String,Integer&gt; <jv>tuple2</jv> = 
Tuple2.<jsm>of</jsm>(<js>"hello"</js>, <jk>null</jk>);
+        *      Optional&lt;Integer&gt; <jv>second2</jv> = 
<jv>tuple2</jv>.optB();  <jc>// Returns Optional.empty()</jc>
+        * </p>
+        *
+        * @return The second value wrapped in an Optional, or Optional.empty() 
if the value is null.
+        */
+       public Optional<B> optB() {
+               return Optional.ofNullable(b);
+       }
+
        @Override /* Overridden from Object */
        public int hashCode() {
                return hashCode;
diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/function/Tuple3.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/function/Tuple3.java
index 7c117e8a62..c7a7496a69 100644
--- 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/function/Tuple3.java
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/function/Tuple3.java
@@ -18,6 +18,8 @@ package org.apache.juneau.commons.function;
 
 import static org.apache.juneau.commons.utils.Utils.*;
 
+import java.util.Optional;
+
 import org.apache.juneau.commons.utils.*;
 
 /**
@@ -106,6 +108,33 @@ public class Tuple3<A,B,C> {
         */
        public C getC() { return c; }
 
+       /**
+        * Returns the first object in this tuple wrapped in an {@link 
Optional}.
+        *
+        * @return The first object wrapped in an Optional, or Optional.empty() 
if the value is null.
+        */
+       public Optional<A> optA() {
+               return Optional.ofNullable(a);
+       }
+
+       /**
+        * Returns the second object in this tuple wrapped in an {@link 
Optional}.
+        *
+        * @return The second object wrapped in an Optional, or 
Optional.empty() if the value is null.
+        */
+       public Optional<B> optB() {
+               return Optional.ofNullable(b);
+       }
+
+       /**
+        * Returns the third object in this tuple wrapped in an {@link 
Optional}.
+        *
+        * @return The third object wrapped in an Optional, or Optional.empty() 
if the value is null.
+        */
+       public Optional<C> optC() {
+               return Optional.ofNullable(c);
+       }
+
        @Override /* Overridden from Object */
        public int hashCode() {
                return hashCode;
diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/function/Tuple4.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/function/Tuple4.java
index ed30c392fa..5127cb6efc 100644
--- 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/function/Tuple4.java
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/function/Tuple4.java
@@ -18,6 +18,8 @@ package org.apache.juneau.commons.function;
 
 import static org.apache.juneau.commons.utils.Utils.*;
 
+import java.util.Optional;
+
 import org.apache.juneau.commons.utils.*;
 
 /**
@@ -119,6 +121,42 @@ public class Tuple4<A,B,C,D> {
         */
        public D getD() { return d; }
 
+       /**
+        * Returns the first object in this tuple wrapped in an {@link 
Optional}.
+        *
+        * @return The first object wrapped in an Optional, or Optional.empty() 
if the value is null.
+        */
+       public Optional<A> optA() {
+               return Optional.ofNullable(a);
+       }
+
+       /**
+        * Returns the second object in this tuple wrapped in an {@link 
Optional}.
+        *
+        * @return The second object wrapped in an Optional, or 
Optional.empty() if the value is null.
+        */
+       public Optional<B> optB() {
+               return Optional.ofNullable(b);
+       }
+
+       /**
+        * Returns the third object in this tuple wrapped in an {@link 
Optional}.
+        *
+        * @return The third object wrapped in an Optional, or Optional.empty() 
if the value is null.
+        */
+       public Optional<C> optC() {
+               return Optional.ofNullable(c);
+       }
+
+       /**
+        * Returns the fourth object in this tuple wrapped in an {@link 
Optional}.
+        *
+        * @return The fourth object wrapped in an Optional, or 
Optional.empty() if the value is null.
+        */
+       public Optional<D> optD() {
+               return Optional.ofNullable(d);
+       }
+
        @Override /* Overridden from Object */
        public int hashCode() {
                return hashCode;
diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/function/Tuple5.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/function/Tuple5.java
index 7b94bd5322..cdab0c8ad6 100644
--- 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/function/Tuple5.java
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/function/Tuple5.java
@@ -18,6 +18,8 @@ package org.apache.juneau.commons.function;
 
 import static org.apache.juneau.commons.utils.Utils.*;
 
+import java.util.Optional;
+
 import org.apache.juneau.commons.utils.*;
 
 /**
@@ -132,6 +134,51 @@ public class Tuple5<A,B,C,D,E> {
         */
        public E getE() { return e; }
 
+       /**
+        * Returns the first object in this tuple wrapped in an {@link 
Optional}.
+        *
+        * @return The first object wrapped in an Optional, or Optional.empty() 
if the value is null.
+        */
+       public Optional<A> optA() {
+               return Optional.ofNullable(a);
+       }
+
+       /**
+        * Returns the second object in this tuple wrapped in an {@link 
Optional}.
+        *
+        * @return The second object wrapped in an Optional, or 
Optional.empty() if the value is null.
+        */
+       public Optional<B> optB() {
+               return Optional.ofNullable(b);
+       }
+
+       /**
+        * Returns the third object in this tuple wrapped in an {@link 
Optional}.
+        *
+        * @return The third object wrapped in an Optional, or Optional.empty() 
if the value is null.
+        */
+       public Optional<C> optC() {
+               return Optional.ofNullable(c);
+       }
+
+       /**
+        * Returns the fourth object in this tuple wrapped in an {@link 
Optional}.
+        *
+        * @return The fourth object wrapped in an Optional, or 
Optional.empty() if the value is null.
+        */
+       public Optional<D> optD() {
+               return Optional.ofNullable(d);
+       }
+
+       /**
+        * Returns the fifth object in this tuple wrapped in an {@link 
Optional}.
+        *
+        * @return The fifth object wrapped in an Optional, or Optional.empty() 
if the value is null.
+        */
+       public Optional<E> optE() {
+               return Optional.ofNullable(e);
+       }
+
        @Override /* Overridden from Object */
        public int hashCode() {
                return hashCode;
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 a6a5043453..b6514f0228 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
@@ -792,6 +792,15 @@ public class BeanMeta<T> {
 
        private final OptionalSupplier<InvocationHandler> 
beanProxyInvocationHandler;  // The invocation handler for this bean (if it's 
an interface).
 
+       /**
+        * Returns the proxy invocation handler for this bean if it's an 
interface.
+        *
+        * @return The invocation handler, or <jk>null</jk> if this is not an 
interface or interface proxies are disabled.
+        */
+       public InvocationHandler getBeanProxyInvocationHandler() {
+               return beanProxyInvocationHandler.get();
+       }
+
        final String notABeanReason;                           // Readable 
string explaining why this class wasn't a bean.
 
        final BeanRegistry beanRegistry;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
index dbd83abf92..1c909bcaf8 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
@@ -154,7 +154,6 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
        private final Map<Class<?>,Mutater<?,T>> fromMutaters = new 
ConcurrentHashMap<>();
        private final OptionalSupplier<MethodInfo> fromStringMethod;            
   // Static fromString(String) or equivalent method
        private final OptionalSupplier<ClassInfoTyped<? extends T>> implClass;  
   // The implementation class to use if this is an interface.
-       private final OptionalSupplier<InvocationHandler> 
proxyInvocationHandler;  // The invocation handler for this class (if it has 
one).
        private final Supplier<Tuple2<ClassMeta<?>,ClassMeta<?>>> 
keyValueTypes;   // Key and value types for MAP types.
        private final SimpleReadWriteLock lock = new SimpleReadWriteLock(false);
        private final OptionalSupplier<MarshalledFilter> marshalledFilter;
@@ -166,7 +165,53 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
        private final OptionalSupplier<ConstructorInfo> stringConstructor;      
   // The X(String) constructor (if it has one).
        private final Supplier<List<ObjectSwap<T,?>>> swaps;                    
   // The object POJO swaps associated with this bean (if it has any).
        private final Map<Class<?>,Mutater<T,?>> toMutaters = new 
ConcurrentHashMap<>();
-       private final Supplier<Tuple2<BeanMeta<T>,String>> beanMeta;
+       private final OptionalSupplier<Tuple2<BeanMeta<T>,String>> beanMeta;
+
+       private static class KeyValueTypes extends 
Tuple2<ClassMeta<?>,ClassMeta<?>> {
+
+               public KeyValueTypes(ClassMeta<?> a, ClassMeta<?> b) {
+                       super(a, b);
+               }
+
+               public ClassMeta<?> getKeyType() {
+                       return getA();
+               }
+
+               public Optional<ClassMeta<?>> optKeyType() {
+                       return optA();
+               }
+
+               public ClassMeta<?> getValueType() {
+                       return getB();
+               }
+
+               public Optional<ClassMeta<?>> optValueType() {
+                       return optB();
+               }
+       }
+
+       private static class BeanMetaValue<T> extends 
Tuple2<BeanMeta<T>,String> {
+
+               public BeanMetaValue(BeanMeta<T> a, String b) {
+                       super(a, b);
+               }
+
+               public BeanMeta<T> getBeanMeta() {
+                       return getA();
+               }
+
+               public Optional<BeanMeta<T>> optBeanMeta() {
+                       return optA();
+               }
+
+               public String getNoArgReason() {
+                       return getB();
+               }
+
+               public Optional<String> optNoArgReason() {
+                       return optB();
+               }
+       }
 
        /**
         * Construct a new {@code ClassMeta} based on the specified {@link 
Class}.
@@ -256,8 +301,6 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
 
                        this.swaps = memoize(()->findSwaps());
 
-                       this.proxyInvocationHandler = 
()->(nn(beanMeta.get().getA()) && beanContext.isUseInterfaceProxies() && 
isInterface()) ? new BeanProxyInvocationHandler<>(beanMeta.get().getA()) : null;
-
                        this.childSwaps = memoize(()->findChildSwaps());
                        this.childUnswapMap = 
Cache.<Class<?>,ObjectSwap<?,?>>create().supplier(x -> findUnswap(x)).build();
                        this.childSwapMap = 
Cache.<Class<?>,ObjectSwap<?,?>>create().supplier(x -> findSwap(x)).build();
@@ -290,7 +333,6 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
                this.beanContext = null;
                this.elementType = memoize(()->findElementType());
                this.keyValueTypes = memoize(()->findKeyValueTypes());
-               this.proxyInvocationHandler = null;
                this.beanMeta = memoize(()->findBeanMeta());
                this.swaps = memoize(()->findSwaps());
                this.stringMutater = null;
@@ -326,7 +368,6 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
                this.beanContext = mainType.beanContext;
                this.elementType = elementType != null ? 
memoize(()->elementType) : mainType.elementType;
                this.keyValueTypes = (keyType != null || valueType != null) ? 
memoize(()->Tuple2.of(keyType, valueType)) : mainType.keyValueTypes;
-               this.proxyInvocationHandler = mainType.proxyInvocationHandler;
                this.beanMeta = mainType.beanMeta;
                this.swaps = mainType.swaps;
                this.exampleMethod = mainType.exampleMethod;
@@ -373,7 +414,8 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
        public boolean canCreateNewInstance() {
                if (isMemberClass() && isNotStatic())
                        return false;
-               if (noArgConstructor.isPresent() || 
proxyInvocationHandler.isPresent() || (isArray() && 
elementType.get().canCreateNewInstance()))
+               var bm = getBeanMeta();
+               if (noArgConstructor.isPresent() || (bm != null && 
bm.getBeanProxyInvocationHandler() != null) || (isArray() && 
elementType.get().canCreateNewInstance()))
                        return true;
                return false;
        }
@@ -716,7 +758,10 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
         *
         * @return The interface proxy invocation handler, or <jk>null</jk> if 
it does not exist.
         */
-       public InvocationHandler getProxyInvocationHandler() { return 
proxyInvocationHandler.get(); }
+       public InvocationHandler getProxyInvocationHandler() {
+               var bm = getBeanMeta();
+               return bm == null ? null : bm.getBeanProxyInvocationHandler();
+       }
 
        /**
         * Returns the transform for this class for creating instances from a 
Reader.
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/commons/function/Tuple1_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/commons/function/Tuple1_Test.java
index f6a0564ffe..e10164241e 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/commons/function/Tuple1_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/commons/function/Tuple1_Test.java
@@ -142,5 +142,22 @@ class Tuple1_Test extends TestBase {
                assertEquals(x1, x2);
                assertEquals(x1.hashCode(), x2.hashCode());
        }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // Optional methods tests.
+       
//------------------------------------------------------------------------------------------------------------------
+       @Test void a14_optA_withValue() {
+               var x = Tuple1.of("foo");
+               var opt = x.optA();
+               assertTrue(opt.isPresent());
+               assertEquals("foo", opt.get());
+       }
+
+       @Test void a15_optA_withNull() {
+               var x = Tuple1.of((String)null);
+               var opt = x.optA();
+               assertFalse(opt.isPresent());
+               assertTrue(opt.isEmpty());
+       }
 }
 
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/commons/function/Tuple2_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/commons/function/Tuple2_Test.java
index a972f11e11..8def11e1b5 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/commons/function/Tuple2_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/commons/function/Tuple2_Test.java
@@ -44,4 +44,35 @@ class Tuple2_Test extends TestBase {
                assertNotEquals(x1, x4);
                assertNotEquals(x1.hashCode(), x4.hashCode());
        }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // Optional methods tests.
+       
//------------------------------------------------------------------------------------------------------------------
+       @Test void a03_optA_withValue() {
+               var x = Tuple2.of("foo", 1);
+               var opt = x.optA();
+               assertTrue(opt.isPresent());
+               assertEquals("foo", opt.get());
+       }
+
+       @Test void a04_optA_withNull() {
+               var x = Tuple2.of(null, 1);
+               var opt = x.optA();
+               assertFalse(opt.isPresent());
+               assertTrue(opt.isEmpty());
+       }
+
+       @Test void a05_optB_withValue() {
+               var x = Tuple2.of("foo", 1);
+               var opt = x.optB();
+               assertTrue(opt.isPresent());
+               assertEquals(1, opt.get());
+       }
+
+       @Test void a06_optB_withNull() {
+               var x = Tuple2.of("foo", null);
+               var opt = x.optB();
+               assertFalse(opt.isPresent());
+               assertTrue(opt.isEmpty());
+       }
 }
\ No newline at end of file
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/commons/function/Tuple3_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/commons/function/Tuple3_Test.java
index d9eec9661b..f226ee08ac 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/commons/function/Tuple3_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/commons/function/Tuple3_Test.java
@@ -48,4 +48,49 @@ class Tuple3_Test extends TestBase {
                assertNotEquals(x1, x5);
                assertNotEquals(x1.hashCode(), x5.hashCode());
        }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // Optional methods tests.
+       
//------------------------------------------------------------------------------------------------------------------
+       @Test void a03_optA_withValue() {
+               var x = Tuple3.of("foo", 1, 2);
+               var opt = x.optA();
+               assertTrue(opt.isPresent());
+               assertEquals("foo", opt.get());
+       }
+
+       @Test void a04_optA_withNull() {
+               var x = Tuple3.of(null, 1, 2);
+               var opt = x.optA();
+               assertFalse(opt.isPresent());
+               assertTrue(opt.isEmpty());
+       }
+
+       @Test void a05_optB_withValue() {
+               var x = Tuple3.of("foo", 1, 2);
+               var opt = x.optB();
+               assertTrue(opt.isPresent());
+               assertEquals(1, opt.get());
+       }
+
+       @Test void a06_optB_withNull() {
+               var x = Tuple3.of("foo", null, 2);
+               var opt = x.optB();
+               assertFalse(opt.isPresent());
+               assertTrue(opt.isEmpty());
+       }
+
+       @Test void a07_optC_withValue() {
+               var x = Tuple3.of("foo", 1, 2);
+               var opt = x.optC();
+               assertTrue(opt.isPresent());
+               assertEquals(2, opt.get());
+       }
+
+       @Test void a08_optC_withNull() {
+               var x = Tuple3.of("foo", 1, null);
+               var opt = x.optC();
+               assertFalse(opt.isPresent());
+               assertTrue(opt.isEmpty());
+       }
 }
\ No newline at end of file
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/commons/function/Tuple4_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/commons/function/Tuple4_Test.java
index 9de3f27c90..c362114b19 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/commons/function/Tuple4_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/commons/function/Tuple4_Test.java
@@ -52,4 +52,63 @@ class Tuple4_Test extends TestBase {
                assertNotEquals(x1, x6);
                assertNotEquals(x1.hashCode(), x6.hashCode());
        }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // Optional methods tests.
+       
//------------------------------------------------------------------------------------------------------------------
+       @Test void a03_optA_withValue() {
+               var x = Tuple4.of("foo", 1, 2, 3);
+               var opt = x.optA();
+               assertTrue(opt.isPresent());
+               assertEquals("foo", opt.get());
+       }
+
+       @Test void a04_optA_withNull() {
+               var x = Tuple4.of(null, 1, 2, 3);
+               var opt = x.optA();
+               assertFalse(opt.isPresent());
+               assertTrue(opt.isEmpty());
+       }
+
+       @Test void a05_optB_withValue() {
+               var x = Tuple4.of("foo", 1, 2, 3);
+               var opt = x.optB();
+               assertTrue(opt.isPresent());
+               assertEquals(1, opt.get());
+       }
+
+       @Test void a06_optB_withNull() {
+               var x = Tuple4.of("foo", null, 2, 3);
+               var opt = x.optB();
+               assertFalse(opt.isPresent());
+               assertTrue(opt.isEmpty());
+       }
+
+       @Test void a07_optC_withValue() {
+               var x = Tuple4.of("foo", 1, 2, 3);
+               var opt = x.optC();
+               assertTrue(opt.isPresent());
+               assertEquals(2, opt.get());
+       }
+
+       @Test void a08_optC_withNull() {
+               var x = Tuple4.of("foo", 1, null, 3);
+               var opt = x.optC();
+               assertFalse(opt.isPresent());
+               assertTrue(opt.isEmpty());
+       }
+
+       @Test void a09_optD_withValue() {
+               var x = Tuple4.of("foo", 1, 2, 3);
+               var opt = x.optD();
+               assertTrue(opt.isPresent());
+               assertEquals(3, opt.get());
+       }
+
+       @Test void a10_optD_withNull() {
+               var x = Tuple4.of("foo", 1, 2, null);
+               var opt = x.optD();
+               assertFalse(opt.isPresent());
+               assertTrue(opt.isEmpty());
+       }
 }
\ No newline at end of file
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/commons/function/Tuple5_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/commons/function/Tuple5_Test.java
index 5ada9a74e2..cd91ac4e95 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/commons/function/Tuple5_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/commons/function/Tuple5_Test.java
@@ -56,4 +56,77 @@ class Tuple5_Test extends TestBase {
                assertNotEquals(x1, x7);
                assertNotEquals(x1.hashCode(), x7.hashCode());
        }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // Optional methods tests.
+       
//------------------------------------------------------------------------------------------------------------------
+       @Test void a03_optA_withValue() {
+               var x = Tuple5.of("foo", 1, 2, 3, 4);
+               var opt = x.optA();
+               assertTrue(opt.isPresent());
+               assertEquals("foo", opt.get());
+       }
+
+       @Test void a04_optA_withNull() {
+               var x = Tuple5.of(null, 1, 2, 3, 4);
+               var opt = x.optA();
+               assertFalse(opt.isPresent());
+               assertTrue(opt.isEmpty());
+       }
+
+       @Test void a05_optB_withValue() {
+               var x = Tuple5.of("foo", 1, 2, 3, 4);
+               var opt = x.optB();
+               assertTrue(opt.isPresent());
+               assertEquals(1, opt.get());
+       }
+
+       @Test void a06_optB_withNull() {
+               var x = Tuple5.of("foo", null, 2, 3, 4);
+               var opt = x.optB();
+               assertFalse(opt.isPresent());
+               assertTrue(opt.isEmpty());
+       }
+
+       @Test void a07_optC_withValue() {
+               var x = Tuple5.of("foo", 1, 2, 3, 4);
+               var opt = x.optC();
+               assertTrue(opt.isPresent());
+               assertEquals(2, opt.get());
+       }
+
+       @Test void a08_optC_withNull() {
+               var x = Tuple5.of("foo", 1, null, 3, 4);
+               var opt = x.optC();
+               assertFalse(opt.isPresent());
+               assertTrue(opt.isEmpty());
+       }
+
+       @Test void a09_optD_withValue() {
+               var x = Tuple5.of("foo", 1, 2, 3, 4);
+               var opt = x.optD();
+               assertTrue(opt.isPresent());
+               assertEquals(3, opt.get());
+       }
+
+       @Test void a10_optD_withNull() {
+               var x = Tuple5.of("foo", 1, 2, null, 4);
+               var opt = x.optD();
+               assertFalse(opt.isPresent());
+               assertTrue(opt.isEmpty());
+       }
+
+       @Test void a11_optE_withValue() {
+               var x = Tuple5.of("foo", 1, 2, 3, 4);
+               var opt = x.optE();
+               assertTrue(opt.isPresent());
+               assertEquals(4, opt.get());
+       }
+
+       @Test void a12_optE_withNull() {
+               var x = Tuple5.of("foo", 1, 2, 3, null);
+               var opt = x.optE();
+               assertFalse(opt.isPresent());
+               assertTrue(opt.isEmpty());
+       }
 }
\ No newline at end of file

Reply via email to