com.vaadin.data.converter.DefaultConverterFactory Maven / Gradle / Ivy
/*
* Copyright (C) 2000-2024 Vaadin Ltd
*
* This program is available under Vaadin Commercial License and Service Terms.
*
* See for the full
* license.
*/
package com.vaadin.data.converter;
import java.io.Serializable;
import java.time.ZoneId;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Supplier;
import com.vaadin.data.Converter;
import com.vaadin.data.ErrorMessageProvider;
import com.vaadin.server.SerializableSupplier;
import com.vaadin.util.ReflectTools;
/**
* Default implementation of {@link ConverterFactory}, handling all standard
* converters defined in {@code com.vaadin.flow.data.converters} package.
*
* @author Vaadin Ltd
* @since 8.16
*/
public enum DefaultConverterFactory implements ConverterFactory {
INSTANCE;
@SuppressWarnings({ "rawtypes", "ImmutableEnumChecker" })
private final Map> converterMap = new HashMap<>();
DefaultConverterFactory() {
registerConverter(DateToLongConverter.class, DateToLongConverter::new);
registerConverter(DateToSqlDateConverter.class,
DateToSqlDateConverter::new);
registerConverter(LocalDateTimeToDateConverter.class,
() -> new LocalDateTimeToDateConverter(ZoneId.systemDefault()));
registerConverter(LocalDateToDateConverter.class,
LocalDateToDateConverter::new);
registerConverterWithMessageProvider(StringToBigDecimalConverter.class,
StringToBigDecimalConverter::new);
registerConverterWithMessageProvider(StringToBigIntegerConverter.class,
StringToBigIntegerConverter::new);
registerConverterWithMessageProvider(StringToBooleanConverter.class,
StringToBooleanConverter::new);
registerConverter(StringToDateConverter.class,
StringToDateConverter::new);
registerConverterWithMessageProvider(StringToDoubleConverter.class,
StringToDoubleConverter::new);
registerConverterWithMessageProvider(StringToFloatConverter.class,
StringToFloatConverter::new);
registerConverterWithMessageProvider(StringToIntegerConverter.class,
StringToIntegerConverter::new);
registerConverterWithMessageProvider(StringToLongConverter.class,
StringToLongConverter::new);
registerConverterWithMessageProvider(StringToUuidConverter.class,
StringToUuidConverter::new);
}
private > void registerConverter(
Class converterType, SerializableSupplier factory) {
List> types = ReflectTools
.getGenericInterfaceTypes(converterType, Converter.class);
assert !types.isEmpty() && types.stream().allMatch(Objects::nonNull);
Key key = new Key(types.get(0), types.get(1));
converterMap.put(key, factory);
}
private > void registerConverterWithMessageProvider(
Class converterType, Function factory) {
registerConverter(converterType, () -> factory.apply(context -> ""));
}
@SuppressWarnings("unchecked")
@Override
public Optional> newInstance(
Class presentationType, Class modelType) {
if (presentationType == null) {
throw new IllegalArgumentException(
"The presentation type cannot be null");
}
if (modelType == null) {
throw new IllegalArgumentException(
"The model type must cannot be null");
}
return Optional
.ofNullable(
converterMap.get(new Key(presentationType, modelType)))
.map(Supplier::get);
}
private static final class Key implements Serializable {
private final Class> presentationType;
private final Class> modelType;
private Key(Class> presentationType, Class> modelType) {
assert presentationType != null && modelType != null;
this.presentationType = presentationType;
this.modelType = ReflectTools.convertPrimitiveType(modelType);
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
Key key = (Key) o;
return presentationType.equals(key.presentationType)
&& modelType.equals(key.modelType);
}
@Override
public int hashCode() {
return Objects.hash(presentationType, modelType);
}
}
}