org.bbottema.javareflection.valueconverter.converters.NumberConverters Maven / Gradle / Ivy
/* * Copyright (C) 2011 Benny Bottema ([email protected]) * * 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 * * http://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.bbottema.javareflection.valueconverter.converters; import lombok.experimental.UtilityClass; import org.bbottema.javareflection.util.Function; import org.bbottema.javareflection.util.Function.Functions; import org.bbottema.javareflection.valueconverter.ValueFunction; import org.bbottema.javareflection.valueconverter.ValueFunction.ValueFunctionImpl; import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import static org.bbottema.javareflection.util.MiscUtil.newArrayList; /** * Generates converters for all numbers to all other numbers, by virtue of Number's own interface that forces all subclasses to implement basic * conversions to common other Number classes. *
* */ @UtilityClass public class NumberConverters { private static final List* Attempts to convert a {@link Number} to the target datatype. *
* NOTE: precision may be lost when converting from a wide number to a narrower number (say float to integer). These * conversions are done by simply calling {@link Number#intValue()} and {@link Number#floatValue()} etc. *
* Conversions are as follows: *
*
- String:
*value.toString()
- Integer:
*value.intValue()
- Boolean:
*value.intValue() > 0
- Float:
*value.floatValue()
- Double:
*value.doubleValue()
- Long:
*value.longValue()
- Byte:
*value.byteValue()
- Short:
*value.shortValue()
- Character:
Character.forDigit(value, 10)
({@link Character#forDigit(int, int)})> CONVERTABLE_NUMBER_FROM_CLASSES_JDK7 = newArrayList(Number.class, AtomicInteger.class, AtomicLong.class, BigDecimal.class, BigInteger.class, byte.class, Byte.class, double.class, Double.class, float.class, Float.class, int.class, Integer.class, long.class, Long.class, short.class, Short.class); private static final Map , Function > CONVERTERS_BY_TARGET_TYPE = new HashMap , Function >() {{ put(Number.class, new NumberDoubleFunction()); put(Integer.class, new NumberIntegerFunction()); put(int.class, new NumberIntegerFunction()); put(Boolean.class, new NumberBooleanFunction()); put(boolean.class, new NumberBooleanFunction()); put(Float.class, new NumberFloatFunction()); put(float.class, new NumberFloatFunction()); put(Double.class, new NumberDoubleFunction()); put(double.class, new NumberDoubleFunction()); put(Long.class, new NumberLongFunction()); put(long.class, new NumberLongFunction()); put(Byte.class, new NumberByteFunction()); put(byte.class, new NumberByteFunction()); put(Short.class, new NumberShortFunction()); put(short.class, new NumberShortFunction()); put(Character.class, new NumberCharacterFunction()); put(char.class, new NumberCharacterFunction()); put(String.class, Functions. simpleToString()); }}; public static final Collection > NUMBER_CONVERTERS = produceNumberConverters(); @SuppressWarnings("unchecked") private static Collection > produceNumberConverters() { ArrayList > valueFunctions = new ArrayList<>(); for (Class extends Number> numberFromClass : CONVERTABLE_NUMBER_FROM_CLASSES_JDK7) { for (Map.Entry , Function > targetClassConverter : CONVERTERS_BY_TARGET_TYPE.entrySet()) { Class> targetClass = targetClassConverter.getKey(); Function, ?> converter = (numberFromClass == targetClass || targetClass.isAssignableFrom(numberFromClass)) ? Functions.identity() : targetClassConverter.getValue(); valueFunctions.add(new ValueFunctionImpl(numberFromClass, targetClass, converter)); } } return valueFunctions; } public static class NumberIntegerFunction implements Function { public Integer apply(Number value) { return value.intValue(); } } public static class NumberBooleanFunction implements Function { public Boolean apply(Number value) { return value.intValue() > 0; } } public static class NumberFloatFunction implements Function { public Float apply(Number value) { return value.floatValue(); } } public static class NumberDoubleFunction implements Function { public Double apply(Number value) { return value.doubleValue(); } } public static class NumberLongFunction implements Function { public Long apply(Number value) { return value.longValue(); } } public static class NumberByteFunction implements Function { public Byte apply(Number value) { return value.byteValue(); } } public static class NumberShortFunction implements Function { public Short apply(Number value) { return value.shortValue(); } } public static class NumberCharacterFunction implements Function { public Character apply(Number value) { return Character.forDigit(value.intValue(), 10); } } }