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

commit e913429d019fd3b58f15aa6d1d0d93c5d919327c
Author: James Bognar <[email protected]>
AuthorDate: Thu Apr 2 16:02:50 2026 -0700

    Replace Mutaters with BasicConverter
---
 .../juneau/commons/conversion/BasicConverter.java  | 20 +++++++++
 .../src/main/java/org/apache/juneau/ClassMeta.java | 50 ++++++++++++++++++++++
 2 files changed, 70 insertions(+)

diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/conversion/BasicConverter.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/conversion/BasicConverter.java
index fd6d50284f..be3ef9bc9c 100644
--- 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/conversion/BasicConverter.java
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/conversion/BasicConverter.java
@@ -194,6 +194,8 @@ public class BasicConverter extends CachingConverter {
 
                if (out.isEnum() && (c = findEnumConversion(inType, out)) != 
null) return c;
 
+               if (out == Optional.class && (c = 
findOptionalConversion(inType)) != null) return c;
+
                if (Collection.class.isAssignableFrom(out) && (c = 
findCollectionConversion(inType, out)) != null) return c;
 
                if (Map.class.isAssignableFrom(out) && (c = 
findMapConversion(inType, out)) != null) return c;
@@ -305,6 +307,24 @@ public class BasicConverter extends CachingConverter {
                return null;
        }
 
+       
//-----------------------------------------------------------------------------------------------------------------
+       // Optional conversions
+       
//-----------------------------------------------------------------------------------------------------------------
+
+       @SuppressWarnings("unchecked")
+       private <I, O> Conversion<I, O> findOptionalConversion(Class<I> inType) 
{
+               return (Conversion<I, O>) (Conversion<I, Optional<?>>) (in, 
memberOf, session, args) -> {
+                       if (in instanceof Optional<?> opt) {
+                               if (args.length == 0)
+                                       return opt;
+                               return opt.map(x -> to(x, args[0]));
+                       }
+                       if (args.length == 0)
+                               return Optional.of(in);
+                       return Optional.of(to(in, args[0]));
+               };
+       }
+
        
//-----------------------------------------------------------------------------------------------------------------
        // Collection conversions
        
//-----------------------------------------------------------------------------------------------------------------
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 d9c0c408a6..a9320ed103 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
@@ -158,6 +158,7 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
        private final NullableSupplier<MethodInfo> fromStringMethod;            
   // Static fromString(String) or equivalent method
        private final NullableSupplier<ClassInfoTyped<? extends T>> implClass;  
   // The implementation class to use if this is an interface.
        private final Supplier<KeyValueTypes> keyValueTypes;                    
    // Key and value types for MAP types.
+       private final Supplier<Type[]> parameters;                              
    // Type parameters for converter dispatch.
        private final NullableSupplier<MarshalledFilter> marshalledFilter;
        private final Supplier<Property<T,Object>> nameProperty;                
   // The method to set the name on an object (if it has one).
        private final NullableSupplier<ConstructorInfo> noArgConstructor;       
   // The no-arg constructor for this class (if it has one).
@@ -264,6 +265,7 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
                fromStringMethod = memoize(this::findFromStringMethod);
                implClass = memoize(this::findImplClass);
                keyValueTypes = memoize(this::findKeyValueTypes);
+               parameters = memoize(this::findParameters);
                marshalledFilter = memoize(this::findMarshalledFilter);
                nameProperty = memoize(this::findNameProperty);
                noArgConstructor = memoize(this::findNoArgConstructor);
@@ -316,6 +318,7 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
                this.implClass = memoize(this::findImplClass);
                this.enumValues = memoize(this::findEnumValues);
                this.beanDictionaryName = memoize(this::findBeanDictionaryName);
+               this.parameters = memoize(this::findParameters);
        }
 
        /**
@@ -350,6 +353,7 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
                this.implClass = mainType.implClass;
                this.enumValues = mainType.enumValues;
                this.beanDictionaryName = mainType.beanDictionaryName;
+               this.parameters = memoize(this::findParameters);
        }
 
        /**
@@ -779,6 +783,52 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
                return keyValueTypes.get().valueType();
        }
 
+       /**
+        * Returns the type parameters for this class as a {@link Type} array 
suitable for passing to
+        * {@link org.apache.juneau.commons.conversion.Converter#to(Object, 
Type, Type...)}.
+        *
+        * <p>
+        * The returned array depends on the kind of type:
+        * <ul>
+        *      <li>{@link java.util.Map} types: {@code [keyType, valueType]}
+        *      <li>{@link java.util.Collection} and {@link java.util.Optional} 
types: {@code [elementType, elementType.getParameters()...]}
+        *              — the element raw class followed by the element's own 
parameters, recursively flattened by one level.
+        *      <li>All other types: empty array.
+        * </ul>
+        *
+        * <h5 class='section'>Examples:</h5>
+        * <ul>
+        *      <li><c>ClassMeta&lt;Optional&lt;Integer&gt;&gt;</c> → 
<c>[Integer]</c>
+        *      <li><c>ClassMeta&lt;List&lt;Integer&gt;&gt;</c> → 
<c>[Integer]</c>
+        *      <li><c>ClassMeta&lt;Map&lt;String,Integer&gt;&gt;</c> → 
<c>[String, Integer]</c>
+        *      
<li><c>ClassMeta&lt;List&lt;Map&lt;String,Integer&gt;&gt;&gt;</c> → <c>[Map, 
String, Integer]</c>
+        * </ul>
+        *
+        * @return The type parameters as a {@link Type} array, never 
<jk>null</jk>.
+        */
+       public Type[] getParameters() { return parameters.get(); }
+
+       private Type[] findParameters() {
+               if (isMap()) {
+                       var kt = getKeyType();
+                       var vt = getValueType();
+                       if (kt == null || vt == null)
+                               return new Type[0];
+                       return new Type[]{kt.inner(), vt.inner()};
+               }
+               if (isCollection() || isOptional()) {
+                       var et = getElementType();
+                       if (et == null)
+                               return new Type[0];
+                       var etParams = et.getParameters();
+                       var result = new Type[1 + etParams.length];
+                       result[0] = et.inner();
+                       System.arraycopy(etParams, 0, result, 1, 
etParams.length);
+                       return result;
+               }
+               return new Type[0];
+       }
+
        /**
         * Returns <jk>true</jk> if this class has a transform associated with 
it that allows it to be created from an InputStream.
         *

Reply via email to