-
Notifications
You must be signed in to change notification settings - Fork 7
Description
The DefaultValues-class is rather rigid, and extensions of the class are inherently invasive.
I propose to replace the DefaultValues-class with a Provider-interface, and an implementation DefaultValuesProvider. Please find the example implementation below.
@FunctionalInterface
public interface Provider<S, T> {
T get(S source);
}An implementation for the Provider-interface, that would offer roughly the same functionality as the DefaultValues-class, could look like this:
public class DefaultValueProvider<S, T extends S> implements Provider<Class<S>, T> {
private static final Map<Class<?>, ?> DEFAULT_VALUES = Map.ofEntries(
Map.entry(boolean.class, false),
Map.entry(byte.class, (byte) 0),
Map.entry(short.class, (short) 0),
Map.entry(int.class, 0),
Map.entry(long.class, 0L),
Map.entry(float.class, 0.0F),
Map.entry(double.class, 0.0),
Map.entry(List.class, Collections.emptyList()),
Map.entry(Set.class, Collections.emptySet()),
Map.entry(Map.class, Collections.emptyMap()),
Map.entry(Optional.class, Optional.empty())
);
@Override
public T get(Class<S> source) {
if (source == null)
return null;
return (T) DEFAULT_VALUES.get(source);
}
}It could also be implemented as a record:
public record DefaultValuesProviderRecord<S, T extends S>(Map<Object, Object> defaultValues) implements Provider<S, T> {
private static final Map<Object, Object> DEFAULT_VALUES = Map.ofEntries(
Map.entry(boolean.class, false),
Map.entry(byte.class, (byte) 0),
Map.entry(short.class, (short) 0),
Map.entry(int.class, 0),
Map.entry(long.class, 0L),
Map.entry(float.class, 0.0F),
Map.entry(double.class, 0.0),
Map.entry(List.class, Collections.emptyList()),
Map.entry(Set.class, Collections.emptySet()),
Map.entry(Map.class, Collections.emptyMap()),
Map.entry(Optional.class, Optional.empty())
);
public DefaultValuesProviderRecord() {
this(DEFAULT_VALUES);
}
@Override
public Map<Object, Object> defaultValues() {
return Collections.unmodifiableMap(this.defaultValues);
}
@Override
public T get(S source) {
return (T) this.defaultValues().get(source);
}
}Aside from the benefits for extensibility of the Provider itself, this will also positively impact testing, and the composition of Form - and Result-classes.
I also propose to allow, not one, but any number of providers for any given mapping, by modifying the Configuration to include a Collection of Provider-objects. This would allow users a greater degree of control over the mapping of their objects, and would be especially easy to use, due to the Provider-interface being a functional interface.