package solution.common.di;
import solution.common.converter.BasicConverter;
import solution.common.converter.BasicConverterService;
import solution.common.converter.Converter;
import solution.common.converter.ConverterService;
import solution.common.date.DateUtils;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import java.util.Optional;
public class Converters {
public static ConverterService converterService() {
BasicConverterService converterService = new BasicConverterService();
converterService.addConverter(Date.class, toDateConverter());
converterService.addConverter(Byte.class, toByteConverter());
converterService.addConverter(Short.class, toShortConverter());
converterService.addConverter(Integer.class, toIntegerConverter());
converterService.addConverter(BigInteger.class, toBigIntegerConverter());
converterService.addConverter(Long.class, toLongConverter());
converterService.addConverter(Float.class, toFloatConverter());
converterService.addConverter(Double.class, toDoubleConverter());
converterService.addConverter(BigDecimal.class, toBigDecimalConverter());
converterService.addConverter(String.class, toStringConverter());
return converterService;
}
private static Converter<Date> toDateConverter() {
BasicConverter<Date> converter = new BasicConverter<>();
converter.addMapping(Object.class, DateUtils::asDate);
return converter;
}
private static Converter<Byte> toByteConverter() {
BasicConverter<Byte> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Byte::parseByte));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::byteValue));
return converter;
}
private static Converter<Short> toShortConverter() {
BasicConverter<Short> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Short::parseShort));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::shortValue));
return converter;
}
private static Converter<Integer> toIntegerConverter() {
BasicConverter<Integer> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Integer::parseInt));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::intValue));
return converter;
}
private static Converter<Long> toLongConverter() {
BasicConverter<Long> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Long::parseLong));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::longValue));
return converter;
}
private static Converter<BigInteger> toBigIntegerConverter() {
BasicConverter<BigInteger> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(BigInteger::new));
converter.addMapping(Number.class, input -> Optional.of(input)
.map(Number::longValue)
.map(BigInteger::valueOf));
return converter;
}
private static Converter<Float> toFloatConverter() {
BasicConverter<Float> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Float::parseFloat));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::floatValue));
return converter;
}
private static Converter<Double> toDoubleConverter() {
BasicConverter<Double> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Double::parseDouble));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::doubleValue));
return converter;
}
private static Converter<BigDecimal> toBigDecimalConverter() {
BasicConverter<BigDecimal> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(BigDecimal::new));
converter.addMapping(Number.class, input -> Optional.of(input)
.map(Number::doubleValue)
.map(BigDecimal::new));
return converter;
}
private static Converter<String> toStringConverter() {
BasicConverter<String> converter = new BasicConverter<>();
converter.addMapping(Object.class, input -> Optional.of(input).map(Object::toString));
return converter;
}
}
```
package solution.common.di;
import solution.common.converter.BasicConverter;
import solution.common.converter.BasicConverterService;
import solution.common.converter.Converter;
import solution.common.converter.ConverterService;
import solution.common.date.DateUtils;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import java.util.Optional;
public class Converters {
public static ConverterService converterService() {
BasicConverterService converterService = new BasicConverterService();
converterService.addConverter(Date.class, toDateConverter());
converterService.addConverter(Byte.class, toByteConverter());
converterService.addConverter(Short.class, toShortConverter());
converterService.addConverter(Integer.class, toIntegerConverter());
converterService.addConverter(BigInteger.class, toBigIntegerConverter());
converterService.addConverter(Long.class, toLongConverter());
converterService.addConverter(Float.class, toFloatConverter());
converterService.addConverter(Double.class, toDoubleConverter());
converterService.addConverter(BigDecimal.class, toBigDecimalConverter());
converterService.addConverter(String.class, toStringConverter());
return converterService;
}
private static Converter<Date> toDateConverter() {
BasicConverter<Date> converter = new BasicConverter<>();
converter.addMapping(Object.class, DateUtils::asDate);
return converter;
}
private static Converter<Byte> toByteConverter() {
BasicConverter<Byte> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Byte::parseByte));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::byteValue));
return converter;
}
private static Converter<Short> toShortConverter() {
BasicConverter<Short> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Short::parseShort));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::shortValue));
return converter;
}
private static Converter<Integer> toIntegerConverter() {
BasicConverter<Integer> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Integer::parseInt));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::intValue));
return converter;
}
private static Converter<Long> toLongConverter() {
BasicConverter<Long> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Long::parseLong));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::longValue));
return converter;
}
private static Converter<BigInteger> toBigIntegerConverter() {
BasicConverter<BigInteger> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(BigInteger::new));
converter.addMapping(Number.class, input -> Optional.of(input)
.map(Number::longValue)
.map(BigInteger::valueOf));
return converter;
}
private static Converter<Float> toFloatConverter() {
BasicConverter<Float> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Float::parseFloat));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::floatValue));
return converter;
}
private static Converter<Double> toDoubleConverter() {
BasicConverter<Double> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Double::parseDouble));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::doubleValue));
return converter;
}
private static Converter<BigDecimal> toBigDecimalConverter() {
BasicConverter<BigDecimal> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(BigDecimal::new));
converter.addMapping(Number.class, input -> Optional.of(input)
.map(Number::doubleValue)
.map(BigDecimal::new));
return converter;
}
private static Converter<String> toStringConverter() {
BasicConverter<String> converter = new BasicConverter<>();
converter.addMapping(Object.class, input -> Optional.of(input).map(Object::toString));
return converter;
}
}
```
package solution.common.di;
import solution.common.converter.BasicConverter;
import solution.common.converter.BasicConverterService;
import solution.common.converter.Converter;
import solution.common.converter.ConverterService;
import solution.common.date.DateUtils;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import java.util.Optional;
public class Converters {
public static ConverterService converterService() {
BasicConverterService converterService = new BasicConverterService();
converterService.addConverter(Date.class, toDateConverter());
converterService.addConverter(Byte.class, toByteConverter());
converterService.addConverter(Short.class, toShortConverter());
converterService.addConverter(Integer.class, toIntegerConverter());
converterService.addConverter(BigInteger.class, toBigIntegerConverter());
converterService.addConverter(Long.class, toLongConverter());
converterService.addConverter(Float.class, toFloatConverter());
converterService.addConverter(Double.class, toDoubleConverter());
converterService.addConverter(BigDecimal.class, toBigDecimalConverter());
converterService.addConverter(String.class, toStringConverter());
return converterService;
}
private static Converter<Date> toDateConverter() {
BasicConverter<Date> converter = new BasicConverter<>();
converter.addMapping(Object.class, DateUtils::asDate);
return converter;
}
private static Converter<Byte> toByteConverter() {
BasicConverter<Byte> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Byte::parseByte));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::byteValue));
return converter;
}
private static Converter<Short> toShortConverter() {
BasicConverter<Short> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Short::parseShort));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::shortValue));
return converter;
}
private static Converter<Integer> toIntegerConverter() {
BasicConverter<Integer> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Integer::parseInt));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::intValue));
return converter;
}
private static Converter<Long> toLongConverter() {
BasicConverter<Long> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Long::parseLong));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::longValue));
return converter;
}
private static Converter<BigInteger> toBigIntegerConverter() {
BasicConverter<BigInteger> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(BigInteger::new));
converter.addMapping(Number.class, input -> Optional.of(input)
.map(Number::longValue)
.map(BigInteger::valueOf));
return converter;
}
private static Converter<Float> toFloatConverter() {
BasicConverter<Float> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Float::parseFloat));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::floatValue));
return converter;
}
private static Converter<Double> toDoubleConverter() {
BasicConverter<Double> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Double::parseDouble));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::doubleValue));
return converter;
}
private static Converter<BigDecimal> toBigDecimalConverter() {
BasicConverter<BigDecimal> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(BigDecimal::new));
converter.addMapping(Number.class, input -> Optional.of(input)
.map(Number::doubleValue)
.map(BigDecimal::new));
return converter;
}
private static Converter<String> toStringConverter() {
BasicConverter<String> converter = new BasicConverter<>();
converter.addMapping(Object.class, input -> Optional.of(input).map(Object::toString));
return converter;
}
}
Code snippets rearranged (without altering the code) to make it easier to follow the code. Tag "generics" added.
I was hoping to make it cleaner and more robust.
Converter
:
package solution.common.converter;
import java.util.Optional;
public interface ConverterServiceConverter<T> {
<T><S> Optional<T> convert(ObjectS value, Class<T> targetType);
}
Converter
implementation:
package solution.common.converter;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
public interfaceclass BasicConverter<T> implements Converter<T> {
private final Map<Class<?>, Function<?, Optional<T>>> mappings = new HashMap<>();
public <S> void addMapping(Class<S> sourceType, Function<S, Optional<T>> mappingFunction) {
mappings.put(sourceType, mappingFunction);
}
@Override
@SuppressWarnings("unchecked")
public <S> Optional<T> convert(S value) {
Class<?> valueType = value.getClass();
Function<? super S, Optional<T>> mapping = (Function<? super S, Optional<T>>) getMappingForType(valueType);
Optional<T> optionalValue = mapping.apply(value);
return optionalValue;
}
private Function<?, Optional<T>> getMappingForType(Class<?> type) {
Function<?, Optional<T>> mapping = mappings.containsKey(type) ?
mappings.get(type) :
findSuperTypeMapping(type);
return mapping;
}
@SuppressWarnings("unchecked")
private <S> Function<? super S, Optional<T>> findSuperTypeMapping(Class<S> valueType) {
for (Class<?> aClass : mappings.keySet()) {
if (aClass.isAssignableFrom(valueType))
return (Function<? super S, Optional<T>>) mappings.get(aClass);
}
return noopMapping();
}
private <S> Function<S, Optional<T>> noopMapping() {
return input -> Optional.empty();
}
}
ConverterService
:
package solution.common.converter;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
public class BasicConverterService implementsinterface ConverterService {
private final Map<Class<?>, Converter<?>> converterMap = new HashMap<>();
public <T> void addConverter(Class<T> targetType, Converter<T> converter) {
converterMap.put(targetType, converter);
}
@Override
@SuppressWarnings("unchecked")
public <T> Optional<T> convert(Object value, Class<T> targetType) {
if (targetType.isAssignableFrom(value.getClass()))
return (Optional<T>) Optional.of(value);
Converter<?> converter = (converterMap.containsKey(targetType)) ?
converterMap.get(targetType) :
findSubtypeConverter(targetType);
return (Optional<T>) converter.convert(value);
}
private Converter<?> findSubtypeConverter(Class<?> targetType) {
for (Class<?> aClass : converterMap.keySet()) {
if (targetType.isAssignableFrom(aClass))
return converterMap.get(aClass);
}
return noopConverter();
}
private <T> Converter<T> noopConverter() {
return new Converter<T>() {
@Override
public <S> Optional<T> convert(S value) {
return Optional.empty();
}
};
}
}
ConverterService
implementation:
package solution.common.converter;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
public class BasicConverter<T>BasicConverterService implements Converter<T>ConverterService {
private final Map<Class<?>, Function<Converter<?, Optional<T>>>>> mappingsconverterMap = new HashMap<>();
public <S><T> void addMappingaddConverter(Class<S> sourceType,Class<T> Function<StargetType, Optional<T>>Converter<T> mappingFunctionconverter) {
mappingsconverterMap.put(sourceTypetargetType, mappingFunctionconverter);
}
@Override
@SuppressWarnings("unchecked")
public <S><T> Optional<T> convert(SObject value, Class<T> targetType) {
Class<?> valueType =if (targetType.isAssignableFrom(value.getClass();))
Function<? super S, Optional<T>> mappingreturn =(Optional<T>) Optional.of(Function<value);
Converter<?> superconverter S,= Optional<T>>(converterMap.containsKey(targetType)) getMappingForType?
converterMap.get(valueTypetargetType); :
Optional<T> optionalValue = mapping.apply findSubtypeConverter(valuetargetType);
return optionalValue;(Optional<T>) converter.convert(value);
}
private Function<Converter<?, Optional<T>>> getMappingForTypefindSubtypeConverter(Class<?> typetargetType) {
Function<?,for Optional<T>>(Class<?> mappingaClass =: mappingsconverterMap.containsKeykeySet(type)) ?{
if mappings(targetType.getisAssignableFrom(typeaClass) :)
findSuperTypeMappingreturn converterMap.get(typeaClass);
return mapping;}
}
@SuppressWarningsreturn noopConverter("unchecked");
private}
<S> Function<? super S,private Optional<T>><T> findSuperTypeMapping(Class<S>Converter<T> valueTypenoopConverter() {
for (Class<?> aClassreturn :new mappings.keySetConverter<T>()) {
if (aClass.isAssignableFrom(valueType))@Override
public <S> returnOptional<T> convert(Function<? super S, Optional<T>>value) mappings.get(aClass);{
}
return noopMappingOptional.empty();
}
private <S> Function<S, Optional<T>> noopMapping() {}
return input -> Optional.empty()};
}
}
Tests:
package solution.common.di;
import solution.common.converter.BasicConverter;
import solution.common.converter.BasicConverterService;
import solution.common.converter.Converter;
import solution.common.converter.ConverterService;
import solution.common.date.DateUtils;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import java.util.Optional;
public class Converters {
public static ConverterService converterService() {
BasicConverterService converterService = new BasicConverterService();
converterService.addConverter(Date.class, toDateConverter());
converterService.addConverter(Byte.class, toByteConverter());
converterService.addConverter(Short.class, toShortConverter());
converterService.addConverter(Integer.class, toIntegerConverter());
converterService.addConverter(BigInteger.class, toBigIntegerConverter());
converterService.addConverter(Long.class, toLongConverter());
converterService.addConverter(Float.class, toFloatConverter());
converterService.addConverter(Double.class, toDoubleConverter());
converterService.addConverter(BigDecimal.class, toBigDecimalConverter());
converterService.addConverter(String.class, toStringConverter());
return converterService;
}
private static Converter<Date> toDateConverter() {
BasicConverter<Date> converter = new BasicConverter<>();
converter.addMapping(Object.class, DateUtils::asDate);
return converter;
}
private static Converter<Byte> toByteConverter() {
BasicConverter<Byte> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Byte::parseByte));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::byteValue));
return converter;
}
private static Converter<Short> toShortConverter() {
BasicConverter<Short> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Short::parseShort));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::shortValue));
return converter;
}
private static Converter<Integer> toIntegerConverter() {
BasicConverter<Integer> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Integer::parseInt));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::intValue));
return converter;
}
private static Converter<Long> toLongConverter() {
BasicConverter<Long> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Long::parseLong));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::longValue));
return converter;
}
private static Converter<BigInteger> toBigIntegerConverter() {
BasicConverter<BigInteger> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(BigInteger::new));
converter.addMapping(Number.class, input -> Optional.of(input)
.map(Number::longValue)
.map(BigInteger::valueOf));
return converter;
}
private static Converter<Float> toFloatConverter() {
BasicConverter<Float> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Float::parseFloat));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::floatValue));
return converter;
}
private static Converter<Double> toDoubleConverter() {
BasicConverter<Double> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Double::parseDouble));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::doubleValue));
return converter;
}
private static Converter<BigDecimal> toBigDecimalConverter() {
BasicConverter<BigDecimal> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(BigDecimal::new));
converter.addMapping(Number.class, input -> Optional.of(input)
.map(Number::doubleValue)
.map(BigDecimal::new));
return converter;
}
private static Converter<String> toStringConverter() {
BasicConverter<String> converter = new BasicConverter<>();
converter.addMapping(Object.class, input -> Optional.of(input).map(Object::toString));
return converter;
}
}
```
I was hoping to make it cleaner and more robust
package solution.common.converter;
import java.util.Optional;
public interface ConverterService {
<T> Optional<T> convert(Object value, Class<T> targetType);
}
package solution.common.converter;
import java.util.Optional;
public interface Converter<T> {
<S> Optional<T> convert(S value);
}
package solution.common.converter;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
public class BasicConverterService implements ConverterService {
private final Map<Class<?>, Converter<?>> converterMap = new HashMap<>();
public <T> void addConverter(Class<T> targetType, Converter<T> converter) {
converterMap.put(targetType, converter);
}
@Override
@SuppressWarnings("unchecked")
public <T> Optional<T> convert(Object value, Class<T> targetType) {
if (targetType.isAssignableFrom(value.getClass()))
return (Optional<T>) Optional.of(value);
Converter<?> converter = (converterMap.containsKey(targetType)) ?
converterMap.get(targetType) :
findSubtypeConverter(targetType);
return (Optional<T>) converter.convert(value);
}
private Converter<?> findSubtypeConverter(Class<?> targetType) {
for (Class<?> aClass : converterMap.keySet()) {
if (targetType.isAssignableFrom(aClass))
return converterMap.get(aClass);
}
return noopConverter();
}
private <T> Converter<T> noopConverter() {
return new Converter<T>() {
@Override
public <S> Optional<T> convert(S value) {
return Optional.empty();
}
};
}
}
package solution.common.converter;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
public class BasicConverter<T> implements Converter<T> {
private final Map<Class<?>, Function<?, Optional<T>>> mappings = new HashMap<>();
public <S> void addMapping(Class<S> sourceType, Function<S, Optional<T>> mappingFunction) {
mappings.put(sourceType, mappingFunction);
}
@Override
@SuppressWarnings("unchecked")
public <S> Optional<T> convert(S value) {
Class<?> valueType = value.getClass();
Function<? super S, Optional<T>> mapping = (Function<? super S, Optional<T>>) getMappingForType(valueType);
Optional<T> optionalValue = mapping.apply(value);
return optionalValue;
}
private Function<?, Optional<T>> getMappingForType(Class<?> type) {
Function<?, Optional<T>> mapping = mappings.containsKey(type) ?
mappings.get(type) :
findSuperTypeMapping(type);
return mapping;
}
@SuppressWarnings("unchecked")
private <S> Function<? super S, Optional<T>> findSuperTypeMapping(Class<S> valueType) {
for (Class<?> aClass : mappings.keySet()) {
if (aClass.isAssignableFrom(valueType))
return (Function<? super S, Optional<T>>) mappings.get(aClass);
}
return noopMapping();
}
private <S> Function<S, Optional<T>> noopMapping() {
return input -> Optional.empty();
}
}
package solution.common.di;
import solution.common.converter.BasicConverter;
import solution.common.converter.BasicConverterService;
import solution.common.converter.Converter;
import solution.common.converter.ConverterService;
import solution.common.date.DateUtils;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import java.util.Optional;
public class Converters {
public static ConverterService converterService() {
BasicConverterService converterService = new BasicConverterService();
converterService.addConverter(Date.class, toDateConverter());
converterService.addConverter(Byte.class, toByteConverter());
converterService.addConverter(Short.class, toShortConverter());
converterService.addConverter(Integer.class, toIntegerConverter());
converterService.addConverter(BigInteger.class, toBigIntegerConverter());
converterService.addConverter(Long.class, toLongConverter());
converterService.addConverter(Float.class, toFloatConverter());
converterService.addConverter(Double.class, toDoubleConverter());
converterService.addConverter(BigDecimal.class, toBigDecimalConverter());
converterService.addConverter(String.class, toStringConverter());
return converterService;
}
private static Converter<Date> toDateConverter() {
BasicConverter<Date> converter = new BasicConverter<>();
converter.addMapping(Object.class, DateUtils::asDate);
return converter;
}
private static Converter<Byte> toByteConverter() {
BasicConverter<Byte> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Byte::parseByte));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::byteValue));
return converter;
}
private static Converter<Short> toShortConverter() {
BasicConverter<Short> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Short::parseShort));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::shortValue));
return converter;
}
private static Converter<Integer> toIntegerConverter() {
BasicConverter<Integer> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Integer::parseInt));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::intValue));
return converter;
}
private static Converter<Long> toLongConverter() {
BasicConverter<Long> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Long::parseLong));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::longValue));
return converter;
}
private static Converter<BigInteger> toBigIntegerConverter() {
BasicConverter<BigInteger> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(BigInteger::new));
converter.addMapping(Number.class, input -> Optional.of(input)
.map(Number::longValue)
.map(BigInteger::valueOf));
return converter;
}
private static Converter<Float> toFloatConverter() {
BasicConverter<Float> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Float::parseFloat));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::floatValue));
return converter;
}
private static Converter<Double> toDoubleConverter() {
BasicConverter<Double> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Double::parseDouble));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::doubleValue));
return converter;
}
private static Converter<BigDecimal> toBigDecimalConverter() {
BasicConverter<BigDecimal> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(BigDecimal::new));
converter.addMapping(Number.class, input -> Optional.of(input)
.map(Number::doubleValue)
.map(BigDecimal::new));
return converter;
}
private static Converter<String> toStringConverter() {
BasicConverter<String> converter = new BasicConverter<>();
converter.addMapping(Object.class, input -> Optional.of(input).map(Object::toString));
return converter;
}
}
I was hoping to make it cleaner and more robust.
Converter
:
package solution.common.converter;
import java.util.Optional;
public interface Converter<T> {
<S> Optional<T> convert(S value);
}
Converter
implementation:
package solution.common.converter;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
public class BasicConverter<T> implements Converter<T> {
private final Map<Class<?>, Function<?, Optional<T>>> mappings = new HashMap<>();
public <S> void addMapping(Class<S> sourceType, Function<S, Optional<T>> mappingFunction) {
mappings.put(sourceType, mappingFunction);
}
@Override
@SuppressWarnings("unchecked")
public <S> Optional<T> convert(S value) {
Class<?> valueType = value.getClass();
Function<? super S, Optional<T>> mapping = (Function<? super S, Optional<T>>) getMappingForType(valueType);
Optional<T> optionalValue = mapping.apply(value);
return optionalValue;
}
private Function<?, Optional<T>> getMappingForType(Class<?> type) {
Function<?, Optional<T>> mapping = mappings.containsKey(type) ?
mappings.get(type) :
findSuperTypeMapping(type);
return mapping;
}
@SuppressWarnings("unchecked")
private <S> Function<? super S, Optional<T>> findSuperTypeMapping(Class<S> valueType) {
for (Class<?> aClass : mappings.keySet()) {
if (aClass.isAssignableFrom(valueType))
return (Function<? super S, Optional<T>>) mappings.get(aClass);
}
return noopMapping();
}
private <S> Function<S, Optional<T>> noopMapping() {
return input -> Optional.empty();
}
}
ConverterService
:
package solution.common.converter;
import java.util.Optional;
public interface ConverterService {
<T> Optional<T> convert(Object value, Class<T> targetType);
}
ConverterService
implementation:
package solution.common.converter;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
public class BasicConverterService implements ConverterService {
private final Map<Class<?>, Converter<?>> converterMap = new HashMap<>();
public <T> void addConverter(Class<T> targetType, Converter<T> converter) {
converterMap.put(targetType, converter);
}
@Override
@SuppressWarnings("unchecked")
public <T> Optional<T> convert(Object value, Class<T> targetType) {
if (targetType.isAssignableFrom(value.getClass()))
return (Optional<T>) Optional.of(value);
Converter<?> converter = (converterMap.containsKey(targetType)) ?
converterMap.get(targetType) :
findSubtypeConverter(targetType);
return (Optional<T>) converter.convert(value);
}
private Converter<?> findSubtypeConverter(Class<?> targetType) {
for (Class<?> aClass : converterMap.keySet()) {
if (targetType.isAssignableFrom(aClass))
return converterMap.get(aClass);
}
return noopConverter();
}
private <T> Converter<T> noopConverter() {
return new Converter<T>() {
@Override
public <S> Optional<T> convert(S value) {
return Optional.empty();
}
};
}
}
Tests:
package solution.common.di;
import solution.common.converter.BasicConverter;
import solution.common.converter.BasicConverterService;
import solution.common.converter.Converter;
import solution.common.converter.ConverterService;
import solution.common.date.DateUtils;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import java.util.Optional;
public class Converters {
public static ConverterService converterService() {
BasicConverterService converterService = new BasicConverterService();
converterService.addConverter(Date.class, toDateConverter());
converterService.addConverter(Byte.class, toByteConverter());
converterService.addConverter(Short.class, toShortConverter());
converterService.addConverter(Integer.class, toIntegerConverter());
converterService.addConverter(BigInteger.class, toBigIntegerConverter());
converterService.addConverter(Long.class, toLongConverter());
converterService.addConverter(Float.class, toFloatConverter());
converterService.addConverter(Double.class, toDoubleConverter());
converterService.addConverter(BigDecimal.class, toBigDecimalConverter());
converterService.addConverter(String.class, toStringConverter());
return converterService;
}
private static Converter<Date> toDateConverter() {
BasicConverter<Date> converter = new BasicConverter<>();
converter.addMapping(Object.class, DateUtils::asDate);
return converter;
}
private static Converter<Byte> toByteConverter() {
BasicConverter<Byte> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Byte::parseByte));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::byteValue));
return converter;
}
private static Converter<Short> toShortConverter() {
BasicConverter<Short> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Short::parseShort));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::shortValue));
return converter;
}
private static Converter<Integer> toIntegerConverter() {
BasicConverter<Integer> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Integer::parseInt));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::intValue));
return converter;
}
private static Converter<Long> toLongConverter() {
BasicConverter<Long> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Long::parseLong));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::longValue));
return converter;
}
private static Converter<BigInteger> toBigIntegerConverter() {
BasicConverter<BigInteger> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(BigInteger::new));
converter.addMapping(Number.class, input -> Optional.of(input)
.map(Number::longValue)
.map(BigInteger::valueOf));
return converter;
}
private static Converter<Float> toFloatConverter() {
BasicConverter<Float> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Float::parseFloat));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::floatValue));
return converter;
}
private static Converter<Double> toDoubleConverter() {
BasicConverter<Double> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Double::parseDouble));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::doubleValue));
return converter;
}
private static Converter<BigDecimal> toBigDecimalConverter() {
BasicConverter<BigDecimal> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(BigDecimal::new));
converter.addMapping(Number.class, input -> Optional.of(input)
.map(Number::doubleValue)
.map(BigDecimal::new));
return converter;
}
private static Converter<String> toStringConverter() {
BasicConverter<String> converter = new BasicConverter<>();
converter.addMapping(Object.class, input -> Optional.of(input).map(Object::toString));
return converter;
}
}
```
package solution.common.di;
import solution.common.converter.BasicConverter;
import solution.common.converter.BasicConverterService;
import solution.common.converter.Converter;
import solution.common.converter.ConverterService;
import solution.common.date.DateUtils;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import java.util.Optional;
public class Converters {
public static ConverterService converterService() {
BasicConverterService converterService = new BasicConverterService();
converterService.addConverter(Date.class, toDateConverter());
converterService.addConverter(Byte.class, toByteConverter());
converterService.addConverter(Short.class, toShortConverter());
converterService.addConverter(Integer.class, toIntegerConverter());
converterService.addConverter(BigInteger.class, toBigIntegerConverter());
converterService.addConverter(Long.class, toLongConverter());
converterService.addConverter(Float.class, toFloatConverter());
converterService.addConverter(Double.class, toDoubleConverter());
converterService.addConverter(BigDecimal.class, toBigDecimalConverter());
converterService.addConverter(String.class, toStringConverter());
return converterService;
}
private static Converter<Date> toDateConverter() {
BasicConverter<Date> converter = new BasicConverter<>();
converter.addMapping(Object.class, DateUtils::asDate);
return converter;
}
private static Converter<Byte> toByteConverter() {
BasicConverter<Byte> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Byte::parseByte));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::byteValue));
return converter;
}
private static Converter<Short> toShortConverter() {
BasicConverter<Short> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Short::parseShort));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::shortValue));
return converter;
}
private static Converter<Integer> toIntegerConverter() {
BasicConverter<Integer> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Integer::parseInt));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::intValue));
return converter;
}
private static Converter<Long> toLongConverter() {
BasicConverter<Long> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Long::parseLong));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::longValue));
return converter;
}
private static Converter<BigInteger> toBigIntegerConverter() {
BasicConverter<BigInteger> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(BigInteger::new));
converter.addMapping(Number.class, input -> Optional.of(input)
.map(Number::longValue)
.map(BigInteger::valueOf));
return converter;
}
private static Converter<Float> toFloatConverter() {
BasicConverter<Float> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Float::parseFloat));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::floatValue));
return converter;
}
private static Converter<Double> toDoubleConverter() {
BasicConverter<Double> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Double::parseDouble));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::doubleValue));
return converter;
}
private static Converter<BigDecimal> toBigDecimalConverter() {
BasicConverter<BigDecimal> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(BigDecimal::new));
converter.addMapping(Number.class, input -> Optional.of(input)
.map(Number::doubleValue)
.map(BigDecimal::new));
return converter;
}
private static Converter<String> toStringConverter() {
BasicConverter<String> converter = new BasicConverter<>();
converter.addMapping(Object.class, input -> Optional.of(input).map(Object::toString));
return converter;
}
}
```
package solution.common.di;
import solution.common.converter.BasicConverter;
import solution.common.converter.BasicConverterService;
import solution.common.converter.Converter;
import solution.common.converter.ConverterService;
import solution.common.date.DateUtils;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import java.util.Optional;
public class Converters {
public static ConverterService converterService() {
BasicConverterService converterService = new BasicConverterService();
converterService.addConverter(Date.class, toDateConverter());
converterService.addConverter(Byte.class, toByteConverter());
converterService.addConverter(Short.class, toShortConverter());
converterService.addConverter(Integer.class, toIntegerConverter());
converterService.addConverter(BigInteger.class, toBigIntegerConverter());
converterService.addConverter(Long.class, toLongConverter());
converterService.addConverter(Float.class, toFloatConverter());
converterService.addConverter(Double.class, toDoubleConverter());
converterService.addConverter(BigDecimal.class, toBigDecimalConverter());
converterService.addConverter(String.class, toStringConverter());
return converterService;
}
private static Converter<Date> toDateConverter() {
BasicConverter<Date> converter = new BasicConverter<>();
converter.addMapping(Object.class, DateUtils::asDate);
return converter;
}
private static Converter<Byte> toByteConverter() {
BasicConverter<Byte> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Byte::parseByte));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::byteValue));
return converter;
}
private static Converter<Short> toShortConverter() {
BasicConverter<Short> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Short::parseShort));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::shortValue));
return converter;
}
private static Converter<Integer> toIntegerConverter() {
BasicConverter<Integer> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Integer::parseInt));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::intValue));
return converter;
}
private static Converter<Long> toLongConverter() {
BasicConverter<Long> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Long::parseLong));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::longValue));
return converter;
}
private static Converter<BigInteger> toBigIntegerConverter() {
BasicConverter<BigInteger> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(BigInteger::new));
converter.addMapping(Number.class, input -> Optional.of(input)
.map(Number::longValue)
.map(BigInteger::valueOf));
return converter;
}
private static Converter<Float> toFloatConverter() {
BasicConverter<Float> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Float::parseFloat));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::floatValue));
return converter;
}
private static Converter<Double> toDoubleConverter() {
BasicConverter<Double> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Double::parseDouble));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::doubleValue));
return converter;
}
private static Converter<BigDecimal> toBigDecimalConverter() {
BasicConverter<BigDecimal> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(BigDecimal::new));
converter.addMapping(Number.class, input -> Optional.of(input)
.map(Number::doubleValue)
.map(BigDecimal::new));
return converter;
}
private static Converter<String> toStringConverter() {
BasicConverter<String> converter = new BasicConverter<>();
converter.addMapping(Object.class, input -> Optional.of(input).map(Object::toString));
return converter;
}
}
```
package solution.common.di;
import solution.common.converter.BasicConverter;
import solution.common.converter.BasicConverterService;
import solution.common.converter.Converter;
import solution.common.converter.ConverterService;
import solution.common.date.DateUtils;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import java.util.Optional;
public class Converters {
public static ConverterService converterService() {
BasicConverterService converterService = new BasicConverterService();
converterService.addConverter(Date.class, toDateConverter());
converterService.addConverter(Byte.class, toByteConverter());
converterService.addConverter(Short.class, toShortConverter());
converterService.addConverter(Integer.class, toIntegerConverter());
converterService.addConverter(BigInteger.class, toBigIntegerConverter());
converterService.addConverter(Long.class, toLongConverter());
converterService.addConverter(Float.class, toFloatConverter());
converterService.addConverter(Double.class, toDoubleConverter());
converterService.addConverter(BigDecimal.class, toBigDecimalConverter());
converterService.addConverter(String.class, toStringConverter());
return converterService;
}
private static Converter<Date> toDateConverter() {
BasicConverter<Date> converter = new BasicConverter<>();
converter.addMapping(Object.class, DateUtils::asDate);
return converter;
}
private static Converter<Byte> toByteConverter() {
BasicConverter<Byte> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Byte::parseByte));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::byteValue));
return converter;
}
private static Converter<Short> toShortConverter() {
BasicConverter<Short> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Short::parseShort));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::shortValue));
return converter;
}
private static Converter<Integer> toIntegerConverter() {
BasicConverter<Integer> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Integer::parseInt));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::intValue));
return converter;
}
private static Converter<Long> toLongConverter() {
BasicConverter<Long> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Long::parseLong));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::longValue));
return converter;
}
private static Converter<BigInteger> toBigIntegerConverter() {
BasicConverter<BigInteger> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(BigInteger::new));
converter.addMapping(Number.class, input -> Optional.of(input)
.map(Number::longValue)
.map(BigInteger::valueOf));
return converter;
}
private static Converter<Float> toFloatConverter() {
BasicConverter<Float> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Float::parseFloat));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::floatValue));
return converter;
}
private static Converter<Double> toDoubleConverter() {
BasicConverter<Double> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(Double::parseDouble));
converter.addMapping(Number.class, input -> Optional.of(input).map(Number::doubleValue));
return converter;
}
private static Converter<BigDecimal> toBigDecimalConverter() {
BasicConverter<BigDecimal> converter = new BasicConverter<>();
converter.addMapping(String.class, input -> Optional.of(input)
.map(BigDecimal::new));
converter.addMapping(Number.class, input -> Optional.of(input)
.map(Number::doubleValue)
.map(BigDecimal::new));
return converter;
}
private static Converter<String> toStringConverter() {
BasicConverter<String> converter = new BasicConverter<>();
converter.addMapping(Object.class, input -> Optional.of(input).map(Object::toString));
return converter;
}
}
lang-java