6 changed files with 214 additions and 56 deletions
@ -0,0 +1,89 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2012-2019 the original author or authors. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.springframework.boot.convert; |
||||||
|
|
||||||
|
import java.util.Collections; |
||||||
|
import java.util.EnumSet; |
||||||
|
import java.util.LinkedHashMap; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Set; |
||||||
|
|
||||||
|
import org.springframework.core.convert.converter.Converter; |
||||||
|
import org.springframework.core.convert.converter.ConverterFactory; |
||||||
|
import org.springframework.util.Assert; |
||||||
|
import org.springframework.util.LinkedMultiValueMap; |
||||||
|
import org.springframework.util.MultiValueMap; |
||||||
|
|
||||||
|
/** |
||||||
|
* Abstract base class for converting from a type to a {@link java.lang.Enum}. |
||||||
|
* |
||||||
|
* @param <T> the source type |
||||||
|
* @author Phillip Webb |
||||||
|
* @author Madhura Bhave |
||||||
|
*/ |
||||||
|
abstract class AbstractTypeToEnumConverterFactory<T> implements ConverterFactory<T, Enum> { |
||||||
|
|
||||||
|
private static Map<String, List<String>> ALIASES; |
||||||
|
|
||||||
|
static { |
||||||
|
MultiValueMap<String, String> aliases = new LinkedMultiValueMap<>(); |
||||||
|
aliases.add("true", "on"); |
||||||
|
aliases.add("false", "off"); |
||||||
|
ALIASES = Collections.unmodifiableMap(aliases); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public <E extends Enum> Converter<T, E> getConverter(Class<E> targetType) { |
||||||
|
Class<?> enumType = targetType; |
||||||
|
while (enumType != null && !enumType.isEnum()) { |
||||||
|
enumType = enumType.getSuperclass(); |
||||||
|
} |
||||||
|
Assert.notNull(enumType, () -> "The target type " + targetType.getName() + " does not refer to an enum"); |
||||||
|
return getTypeToEnumConverter(targetType); |
||||||
|
} |
||||||
|
|
||||||
|
abstract <E extends Enum> Converter<T, E> getTypeToEnumConverter(Class<E> targetType); |
||||||
|
|
||||||
|
<E extends Enum> E findEnum(String source, Class<E> enumType) { |
||||||
|
Map<String, E> candidates = new LinkedHashMap<>(); |
||||||
|
for (E candidate : (Set<E>) EnumSet.allOf(enumType)) { |
||||||
|
candidates.put(getCanonicalName(candidate.name()), candidate); |
||||||
|
} |
||||||
|
String name = getCanonicalName(source); |
||||||
|
E result = candidates.get(name); |
||||||
|
if (result != null) { |
||||||
|
return result; |
||||||
|
} |
||||||
|
for (String alias : ALIASES.getOrDefault(name, Collections.emptyList())) { |
||||||
|
result = candidates.get(alias); |
||||||
|
if (result != null) { |
||||||
|
return result; |
||||||
|
} |
||||||
|
} |
||||||
|
throw new IllegalArgumentException("No enum constant " + enumType.getCanonicalName() + "." + source); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
private String getCanonicalName(String name) { |
||||||
|
StringBuilder canonicalName = new StringBuilder(name.length()); |
||||||
|
name.chars().filter(Character::isLetterOrDigit).map(Character::toLowerCase) |
||||||
|
.forEach((c) -> canonicalName.append((char) c)); |
||||||
|
return canonicalName.toString(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,50 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2012-2019 the original author or authors. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.springframework.boot.convert; |
||||||
|
|
||||||
|
import org.springframework.core.convert.converter.Converter; |
||||||
|
|
||||||
|
/** |
||||||
|
* Converter to support mapping of YAML style {@code "false"} and {@code "true"} to enums |
||||||
|
* {@code ON} and {@code OFF}. |
||||||
|
* |
||||||
|
* @author Madhura Bhave |
||||||
|
*/ |
||||||
|
@SuppressWarnings({ "unchecked", "rawtypes" }) |
||||||
|
final class BooleanToEnumConverterFactory extends AbstractTypeToEnumConverterFactory<Boolean> { |
||||||
|
|
||||||
|
@Override |
||||||
|
<E extends Enum> Converter<Boolean, E> getTypeToEnumConverter(Class<E> targetType) { |
||||||
|
return new BooleanToEnum<>(targetType); |
||||||
|
} |
||||||
|
|
||||||
|
private class BooleanToEnum<T extends Enum> implements Converter<Boolean, T> { |
||||||
|
|
||||||
|
private final Class<T> enumType; |
||||||
|
|
||||||
|
BooleanToEnum(Class<T> enumType) { |
||||||
|
this.enumType = enumType; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public T convert(Boolean source) { |
||||||
|
return findEnum(Boolean.toString(source), this.enumType); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,59 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2012-2019 the original author or authors. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.springframework.boot.convert; |
||||||
|
|
||||||
|
import java.util.stream.Stream; |
||||||
|
|
||||||
|
import org.junit.jupiter.params.provider.Arguments; |
||||||
|
|
||||||
|
import org.springframework.core.convert.ConversionService; |
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat; |
||||||
|
|
||||||
|
/** |
||||||
|
* Tests for {@link BooleanToEnumConverterFactory}. |
||||||
|
* |
||||||
|
* @author Madhura Bhave |
||||||
|
*/ |
||||||
|
class BooleanToEnumConverterFactoryTests { |
||||||
|
|
||||||
|
@ConversionServiceTest |
||||||
|
void convertFromBooleanToEnumWhenShouldConvertValue(ConversionService conversionService) { |
||||||
|
assertThat(conversionService.convert(true, TestOnOffEnum.class)).isEqualTo(TestOnOffEnum.ON); |
||||||
|
assertThat(conversionService.convert(false, TestOnOffEnum.class)).isEqualTo(TestOnOffEnum.OFF); |
||||||
|
assertThat(conversionService.convert(true, TestTrueFalseEnum.class)).isEqualTo(TestTrueFalseEnum.TRUE); |
||||||
|
assertThat(conversionService.convert(false, TestTrueFalseEnum.class)).isEqualTo(TestTrueFalseEnum.FALSE); |
||||||
|
} |
||||||
|
|
||||||
|
static Stream<? extends Arguments> conversionServices() { |
||||||
|
return ConversionServiceArguments |
||||||
|
.with((service) -> service.addConverterFactory(new BooleanToEnumConverterFactory())); |
||||||
|
} |
||||||
|
|
||||||
|
enum TestOnOffEnum { |
||||||
|
|
||||||
|
ON, OFF |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
enum TestTrueFalseEnum { |
||||||
|
|
||||||
|
ONE, TWO, TRUE, FALSE, ON, OFF |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
Loading…
Reference in new issue