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 2282faed06 Replace Mutaters with BasicConverter
2282faed06 is described below

commit 2282faed06624e19589cb72cced3f71ee0afae69
Author: James Bognar <[email protected]>
AuthorDate: Thu Apr 2 16:54:51 2026 -0700

    Replace Mutaters with BasicConverter
---
 .../commons/conversion/CachingConverter.java       | 33 +++++++++++++++++++---
 .../main/java/org/apache/juneau/BeanSession.java   | 12 ++------
 2 files changed, 32 insertions(+), 13 deletions(-)

diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/conversion/CachingConverter.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/conversion/CachingConverter.java
index 06b94947a3..bd1ef729b6 100644
--- 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/conversion/CachingConverter.java
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/conversion/CachingConverter.java
@@ -57,6 +57,31 @@ public abstract class CachingConverter implements Converter {
        // Using this sentinel avoids re-invoking findConversion() for 
unconvertable type pairs.
        private static final Conversion<?,?> NO_CONVERSION = (in, memberOf, 
session, args) -> null; // HTT: sentinel body is never invoked; 
ConcurrentHashMap prohibits null values so we use this placeholder
 
+       /**
+        * Returns the appropriate default value for a null input to the given 
target type.
+        *
+        * <ul>
+        *      <li>For {@link Optional}: returns {@link Optional#empty()}, or 
{@code Optional.of(Optional.empty())} for
+        *              nested optional types such as {@code 
Optional<Optional<Integer>>}.
+        *      <li>For primitives: returns the JVM zero/false default (e.g. 
{@code 0} for {@code int}).
+        *      <li>For all other types: returns {@code null}.
+        * </ul>
+        *
+        * @param type The target type.
+        * @param args The generic type arguments (e.g. element type for {@link 
Optional}).
+        * @param <T> The target type.
+        * @return The appropriate null default.
+        */
+       @SuppressWarnings("unchecked")
+       static <T> T nullDefault(Class<T> type, Class<?>... args) {
+               if (type == Optional.class) {
+                       if (args.length > 0)
+                               return (T) 
Optional.ofNullable(nullDefault(args[0], Arrays.copyOfRange(args, 1, 
args.length)));
+                       return (T) Optional.empty();
+               }
+               return type.isPrimitive() ? primitiveDefault(type) : null;
+       }
+
        /**
         * Returns the JVM default value for a primitive type, or <jk>null</jk> 
if the type is not primitive.
         *
@@ -176,11 +201,11 @@ public abstract class CachingConverter implements 
Converter {
        @SuppressWarnings("unchecked")
        public <T> T to(Object o, Type mainType, Type... args) {
                var rawType = (Class<T>) (mainType instanceof ParameterizedType 
pt ? pt.getRawType() : (Class<?>) mainType);
-               if (o == null)
-                       return rawType.isPrimitive() ? 
primitiveDefault(rawType) : null;
                var argClasses = Stream.of(args)
                        .map(t -> (Class<?>) (t instanceof ParameterizedType 
pt2 ? pt2.getRawType() : t))
                        .toArray(Class[]::new);
+               if (o == null)
+                       return nullDefault(rawType, argClasses);
                var inType = o.getClass();
                var fn = (Conversion<Object, T>) lookupConversion(inType, 
rawType);
                if (fn == null)
@@ -238,11 +263,11 @@ public abstract class CachingConverter implements 
Converter {
        @SuppressWarnings("unchecked")
        public <T> T to(Object o, Object memberOf, ConverterSession session, 
Type mainType, Type... args) {
                var rawType = (Class<T>) (mainType instanceof ParameterizedType 
pt ? pt.getRawType() : (Class<?>) mainType);
-               if (o == null)
-                       return rawType.isPrimitive() ? 
primitiveDefault(rawType) : null;
                var argClasses = Stream.of(args)
                        .map(t -> (Class<?>) (t instanceof ParameterizedType 
pt2 ? pt2.getRawType() : t))
                        .toArray(Class[]::new);
+               if (o == null)
+                       return nullDefault(rawType, argClasses);
                var inType = o.getClass();
                var fn = (Conversion<Object, T>) lookupConversion(inType, 
rawType);
                if (fn == null)
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanSession.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanSession.java
index 6d4f046eea..cf2eec9673 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanSession.java
@@ -1185,15 +1185,11 @@ public class BeanSession extends ContextSession 
implements ConverterSession {
                        to = (ClassMeta<T>)object();
 
                try {
+                       var ctxConverter = ctx.getConverter();
+
                        // Handle the case of a null value.
                        if (value == null) {
-
-                               // If it's a primitive, then use the converters 
to get the default value for the primitive type.
-                               if (to.isPrimitive())
-                                       return to.getPrimitiveDefault();
-
-                               // Otherwise, just return null.
-                               return to.isOptional() ? 
(T)to.getOptionalDefault() : null;
+                               return ctxConverter.to(value, outer, this, 
to.innerType(), to.getParameters());
                        }
 
                        if (to.isOptional() && (! (value instanceof Optional)))
@@ -1232,8 +1228,6 @@ public class BeanSession extends ContextSession 
implements ConverterSession {
                                        return (T)swap.swap(this, value);
                        }
 
-                       var ctxConverter = ctx.getConverter();
-
                        if (to.isCharSequence() && 
(from.isDateOrCalendarOrTemporal() || from.isDuration()))
                                return (T) Iso8601Utils.format(value, from, 
getTimeZone());
 

Reply via email to