1 package com.github.mygreen.supercsv.cellprocessor.format;
2
3 import java.math.BigDecimal;
4 import java.math.BigInteger;
5 import java.math.MathContext;
6 import java.util.HashMap;
7 import java.util.Map;
8 import java.util.Objects;
9
10
11
12
13
14
15
16
17 public class SimpleNumberFormatter<T extends Number> extends AbstractTextFormatter<T> {
18
19 private final Class<T> type;
20
21 private final boolean lenient;
22
23 private final MathContext mathContext;
24
25
26
27
28
29
30
31
32 public SimpleNumberFormatter(final Class<T> type, final boolean lenient) {
33 this(type, lenient, null);
34
35 }
36
37
38
39
40
41
42
43
44
45 public SimpleNumberFormatter(final Class<T> type, final boolean lenient, final MathContext mathContext) {
46 Objects.requireNonNull(type);
47
48 this.type = type;
49 this.lenient = lenient;
50 this.mathContext = mathContext;
51
52 }
53
54 @SuppressWarnings("unchecked")
55 @Override
56 public T parse(final String text) {
57
58 try {
59 final BigDecimal number = mathContext == null ? new BigDecimal(text) : new BigDecimal(text, mathContext);
60 return (T) parseFromBigDecimal(type, number);
61
62 } catch(NumberFormatException | ArithmeticException e) {
63 throw new TextParseException(text, type, e);
64 }
65 }
66
67 private Number parseFromBigDecimal(final Class<? extends Number> type, final BigDecimal number) {
68
69 if(Byte.class.isAssignableFrom(type) || byte.class.isAssignableFrom(type)) {
70 return lenient ? number.byteValue() : number.byteValueExact();
71
72 } else if(Short.class.isAssignableFrom(type) || short.class.isAssignableFrom(type)) {
73 return lenient ? number.shortValue() : number.shortValueExact();
74
75 } else if(Integer.class.isAssignableFrom(type) || int.class.isAssignableFrom(type)) {
76 return lenient ? number.intValue() : number.intValueExact();
77
78 } else if(Long.class.isAssignableFrom(type) || long.class.isAssignableFrom(type)) {
79 return lenient ? number.longValue() : number.longValueExact();
80
81 } else if(Float.class.isAssignableFrom(type) || float.class.isAssignableFrom(type)) {
82 return number.floatValue();
83
84 } else if(Double.class.isAssignableFrom(type) || double.class.isAssignableFrom(type)) {
85 return number.doubleValue();
86
87 } else if(type.isAssignableFrom(BigInteger.class)) {
88 return lenient ? number.toBigInteger() : number.toBigIntegerExact();
89
90 } else if(type.isAssignableFrom(BigDecimal.class)) {
91 return number;
92
93 }
94
95 throw new IllegalArgumentException(String.format("Not support class type : %s", type.getCanonicalName()));
96
97 }
98
99 @Override
100 public String print(final T object) {
101
102 if(mathContext != null) {
103 return printNumber(object);
104 }
105
106 return object.toString();
107 }
108
109 private String printNumber(final Object object) {
110
111 if(Byte.class.isAssignableFrom(type) || byte.class.isAssignableFrom(type)) {
112 return new BigDecimal((byte)object, mathContext).toPlainString();
113
114 } else if(Short.class.isAssignableFrom(type) || short.class.isAssignableFrom(type)) {
115 return new BigDecimal((short)object, mathContext).toPlainString();
116
117 } else if(Integer.class.isAssignableFrom(type) || int.class.isAssignableFrom(type)) {
118 return new BigDecimal((int)object, mathContext).toPlainString();
119
120 } else if(Long.class.isAssignableFrom(type) || long.class.isAssignableFrom(type)) {
121 return new BigDecimal((long)object, mathContext).toPlainString();
122
123 } else if(Float.class.isAssignableFrom(type) || float.class.isAssignableFrom(type)) {
124 return new BigDecimal((float)object, mathContext).toPlainString();
125
126 } else if(Double.class.isAssignableFrom(type) || double.class.isAssignableFrom(type)) {
127 return new BigDecimal((double)object, mathContext).toPlainString();
128
129 } else if(BigInteger.class.isAssignableFrom(type)) {
130 return new BigDecimal((BigInteger)object, mathContext).toPlainString();
131
132 } else {
133 return object.toString();
134 }
135 }
136
137
138
139
140
141
142
143
144 public boolean isLenient() {
145 return lenient;
146 }
147
148
149
150
151
152 public MathContext getMathContext() {
153 return mathContext;
154 }
155
156 @Override
157 public Map<String, Object> getMessageVariables() {
158
159 final Map<String, Object> vars = new HashMap<>();
160
161 if(mathContext != null) {
162 vars.put("precision", mathContext.getPrecision());
163 }
164
165 return vars;
166 }
167
168 }