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<Optional<Integer>></c> →
<c>[Integer]</c>
+ * <li><c>ClassMeta<List<Integer>></c> →
<c>[Integer]</c>
+ * <li><c>ClassMeta<Map<String,Integer>></c> →
<c>[String, Integer]</c>
+ *
<li><c>ClassMeta<List<Map<String,Integer>>></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.
*