001    /*******************************************************************************
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements.  See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership.  The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the
007     * "License"); you may not use this file except in compliance
008     * with the License.  You may obtain a copy of the License at
009     *
010     * http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing,
013     * software distributed under the License is distributed on an
014     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     * KIND, either express or implied.  See the License for the
016     * specific language governing permissions and limitations
017     * under the License.
018     *******************************************************************************/
019    package org.apache.commons.convert;
020    
021    import java.math.BigDecimal;
022    import java.math.BigInteger;
023    import java.text.NumberFormat;
024    import java.text.ParseException;
025    import java.util.Locale;
026    import java.util.TimeZone;
027    
028    /** Number Converter classes. */
029    public class NumberConverters implements ConverterLoader {
030    
031        protected static final Class<?>[] classArray = {BigDecimal.class, BigInteger.class, Byte.class, Double.class, Integer.class, Float.class, Long.class, Short.class};
032    
033        protected static Number fromString(String str, Locale locale) throws ConversionException {
034            NumberFormat nf = NumberFormat.getNumberInstance(locale);
035            try {
036                return nf.parse(str);
037            } catch (ParseException e) {
038                throw new ConversionException(e);
039            }
040        }
041    
042        protected static <S, T> void registerConverter(Converter<S, T> converter) {
043            if (converter.getSourceClass() != converter.getTargetClass()) {
044                Converters.registerConverter(converter);
045            }
046        }
047    
048        @SuppressWarnings("unchecked")
049        public void loadConverters() {
050            Converters.loadContainedConverters(NumberConverters.class);
051            for (Class<?> sourceClass : classArray) {
052                registerConverter(new GenericNumberToBigDecimal(sourceClass));
053                registerConverter(new GenericNumberToBigInteger(sourceClass));
054                registerConverter(new GenericNumberToByte(sourceClass));
055                registerConverter(new GenericNumberToDouble(sourceClass));
056                registerConverter(new GenericNumberToInteger(sourceClass));
057                registerConverter(new GenericNumberToFloat(sourceClass));
058                registerConverter(new GenericNumberToLong(sourceClass));
059                registerConverter(new GenericNumberToShort(sourceClass));
060                registerConverter(new GenericSingletonToList(sourceClass));
061                registerConverter(new GenericSingletonToSet(sourceClass));
062            }
063        }
064    
065        public static abstract class AbstractNumberConverter<S, T> extends AbstractLocalizedConverter<S, T> {
066            protected AbstractNumberConverter(Class<S> sourceClass, Class<T> targetClass) {
067                super(sourceClass, targetClass);
068            }
069    
070            public T convert(S obj, Locale locale, TimeZone timeZone, String formatString) throws ConversionException {
071                return convert(obj, locale, null);
072            }
073        }
074    
075        /**
076         * An abstract <code>Number</code> to <code>String</code> converter class
077         * that implements some of the <code>LocalizedConverter</code> methods. 
078         */
079        public static abstract class AbstractNumberToStringConverter<N extends Number> extends AbstractNumberConverter<N, String> {
080            public AbstractNumberToStringConverter(Class<N> sourceClass) {
081                super(sourceClass, String.class);
082            }
083    
084            public String convert(N obj) throws ConversionException {
085                return obj.toString();
086            }
087    
088            public String convert(N obj, Locale locale, TimeZone timeZone) throws ConversionException {
089                return format(obj, NumberFormat.getNumberInstance(locale));
090            }
091    
092            protected abstract String format(N obj, NumberFormat nf) throws ConversionException;
093        }
094    
095        /**
096         * An abstract <code>String</code> to <code>Number</code> converter class
097         * that implements some of the <code>LocalizedConverter</code> methods. 
098         */
099        public static abstract class AbstractStringToNumberConverter<N extends Number> extends AbstractNumberConverter<String, N> {
100            public AbstractStringToNumberConverter(Class<N> targetClass) {
101                super(String.class, targetClass);
102            }
103    
104            protected abstract N convert(Number number) throws ConversionException;
105    
106            public N convert(String obj, Locale locale, TimeZone timeZone) throws ConversionException {
107                return convert(fromString(obj, locale));
108            }
109        }
110    
111        /**
112         * An object that converts a <code>BigDecimal</code> to a
113         * <code>String</code>.
114         */
115        public static class BigDecimalToString extends AbstractNumberToStringConverter<BigDecimal> {
116            public BigDecimalToString() {
117                super(BigDecimal.class);
118            }
119    
120            protected String format(BigDecimal obj, NumberFormat nf) throws ConversionException {
121                return nf.format(obj.doubleValue());
122            }
123        }
124    
125        /**
126         * An object that converts a <code>BigInteger</code> to a
127         * <code>String</code>.
128         */
129        public static class BigIntegerToString extends AbstractNumberToStringConverter<BigInteger> {
130            public BigIntegerToString() {
131                super(BigInteger.class);
132            }
133    
134            protected String format(BigInteger obj, NumberFormat nf) throws ConversionException {
135                return nf.format(obj.doubleValue());
136            }
137        }
138    
139        /**
140         * An object that converts a <code>Byte</code> to a
141         * <code>String</code>.
142         */
143        public static class ByteToString extends AbstractNumberToStringConverter<Byte> {
144            public ByteToString() {
145                super(Byte.class);
146            }
147    
148            protected String format(Byte obj, NumberFormat nf) throws ConversionException {
149                return nf.format(obj.floatValue());
150            }
151        }
152    
153        /**
154         * An object that converts a <code>Double</code> to a
155         * <code>String</code>.
156         */
157        public static class DoubleToString extends AbstractNumberToStringConverter<Double> {
158            public DoubleToString() {
159                super(Double.class);
160            }
161    
162            protected String format(Double obj, NumberFormat nf) throws ConversionException {
163                return nf.format(obj.doubleValue());
164            }
165        }
166    
167        /**
168         * An object that converts a <code>Float</code> to a
169         * <code>String</code>.
170         */
171        public static class FloatToString extends AbstractNumberToStringConverter<Float> {
172            public FloatToString() {
173                super(Float.class);
174            }
175    
176            protected String format(Float obj, NumberFormat nf) throws ConversionException {
177                return nf.format(obj.floatValue());
178            }
179        }
180    
181        /**
182         * An object that converts a <code>Number</code> to a
183         * <code>BigDecimal</code>.
184         */
185        public static class GenericNumberToBigDecimal<N extends Number> extends AbstractConverter<N, BigDecimal> {
186            public GenericNumberToBigDecimal(Class<N> sourceClass) {
187                super(sourceClass, BigDecimal.class);
188            }
189    
190            public BigDecimal convert(N obj) throws ConversionException {
191                return new BigDecimal(obj.doubleValue());
192            }
193        }
194    
195        /**
196         * An object that converts a <code>Number</code> to a
197         * <code>BigInteger</code>.
198         */
199        public static class GenericNumberToBigInteger<N extends Number> extends AbstractConverter<N, BigInteger> {
200            public GenericNumberToBigInteger(Class<N> sourceClass) {
201                super(sourceClass, BigInteger.class);
202            }
203    
204            public BigInteger convert(N obj) throws ConversionException {
205                return BigInteger.valueOf(obj.longValue());
206            }
207        }
208    
209        /**
210         * An object that converts a <code>Number</code> to a
211         * <code>Byte</code>.
212         */
213        public static class GenericNumberToByte<N extends Number> extends AbstractConverter<N, Byte> {
214            public GenericNumberToByte(Class<N> sourceClass) {
215                super(sourceClass, Byte.class);
216            }
217    
218            public Byte convert(N obj) throws ConversionException {
219                return Byte.valueOf(obj.byteValue());
220            }
221        }
222    
223        /**
224         * An object that converts a <code>Number</code> to a
225         * <code>Double</code>.
226         */
227        public static class GenericNumberToDouble<N extends Number> extends AbstractConverter<N, Double> {
228            public GenericNumberToDouble(Class<N> sourceClass) {
229                super(sourceClass, Double.class);
230            }
231    
232            public Double convert(N obj) throws ConversionException {
233                return obj.doubleValue();
234            }
235        }
236    
237        /**
238         * An object that converts a <code>Number</code> to a
239         * <code>Float</code>.
240         */
241        public static class GenericNumberToFloat<N extends Number> extends AbstractConverter<N, Float> {
242            public GenericNumberToFloat(Class<N> sourceClass) {
243                super(sourceClass, Float.class);
244            }
245    
246            public Float convert(N obj) throws ConversionException {
247                return obj.floatValue();
248            }
249        }
250    
251        /**
252         * An object that converts a <code>Number</code> to an
253         * <code>Integer</code>.
254         */
255        public static class GenericNumberToInteger<N extends Number> extends AbstractConverter<N, Integer> {
256            public GenericNumberToInteger(Class<N> sourceClass) {
257                super(sourceClass, Integer.class);
258            }
259    
260            public Integer convert(N obj) throws ConversionException {
261                return obj.intValue();
262            }
263        }
264    
265        /**
266         * An object that converts a <code>Number</code> to a
267         * <code>Long</code>.
268         */
269        public static class GenericNumberToLong<N extends Number> extends AbstractConverter<N, Long> {
270            public GenericNumberToLong(Class<N> sourceClass) {
271                super(sourceClass, Long.class);
272            }
273    
274            public Long convert(N obj) throws ConversionException {
275                return obj.longValue();
276            }
277        }
278    
279        /**
280         * An object that converts a <code>Number</code> to a
281         * <code>Short</code>.
282         */
283        public static class GenericNumberToShort<N extends Number> extends AbstractConverter<N, Short> {
284            public GenericNumberToShort(Class<N> sourceClass) {
285                super(sourceClass, Short.class);
286            }
287    
288            public Short convert(N obj) throws ConversionException {
289                return obj.shortValue();
290            }
291        }
292    
293        /**
294         * An object that converts an <code>Integer</code> to a
295         * <code>String</code>.
296         */
297        public static class IntegerToString extends AbstractNumberToStringConverter<Integer> {
298            public IntegerToString() {
299                super(Integer.class);
300            }
301    
302            protected String format(Integer obj, NumberFormat nf) throws ConversionException {
303                return nf.format(obj.intValue());
304            }
305        }
306    
307        /**
308         * An object that converts a <code>Long</code> to a
309         * <code>BigDecimal</code>.
310         */
311        public static class LongToBigDecimal extends AbstractConverter<Long, BigDecimal> {
312            public LongToBigDecimal() {
313                super(Long.class, BigDecimal.class);
314            }
315    
316            public BigDecimal convert(Long obj) throws ConversionException {
317                return BigDecimal.valueOf(obj.longValue());
318            }
319        }
320    
321        /**
322         * An object that converts a <code>Long</code> to a
323         * <code>String</code>.
324         */
325        public static class LongToString extends AbstractNumberToStringConverter<Long> {
326            public LongToString() {
327                super(Long.class);
328            }
329    
330            protected String format(Long obj, NumberFormat nf) throws ConversionException {
331                return nf.format(obj.longValue());
332            }
333        }
334    
335        /**
336         * An object that converts a <code>Short</code> to a
337         * <code>String</code>.
338         */
339        public static class ShortToString extends AbstractNumberToStringConverter<Short> {
340            public ShortToString() {
341                super(Short.class);
342            }
343    
344            protected String format(Short obj, NumberFormat nf) throws ConversionException {
345                return nf.format(obj.floatValue());
346            }
347        }
348    
349        /**
350         * An object that converts a <code>String</code> to a
351         * <code>BigDecimal</code>.
352         */
353        public static class StringToBigDecimal extends AbstractStringToNumberConverter<BigDecimal> {
354            public StringToBigDecimal() {
355                super(BigDecimal.class);
356            }
357    
358            protected BigDecimal convert(Number number) throws ConversionException {
359                return BigDecimal.valueOf(number.doubleValue());
360            }
361    
362            public BigDecimal convert(String obj) throws ConversionException {
363                return BigDecimal.valueOf(Double.valueOf(obj));
364            }
365        }
366    
367        /**
368         * An object that converts a <code>String</code> to a
369         * <code>BigInteger</code>.
370         */
371        public static class StringToBigInteger extends AbstractStringToNumberConverter<BigInteger> {
372            public StringToBigInteger() {
373                super(BigInteger.class);
374            }
375    
376            protected BigInteger convert(Number number) throws ConversionException {
377                return BigInteger.valueOf(number.longValue());
378            }
379    
380            public BigInteger convert(String obj) throws ConversionException {
381                return new BigInteger(obj);
382            }
383        }
384    
385        /**
386         * An object that converts a <code>String</code> to a
387         * <code>Byte</code>.
388         */
389        public static class StringToByte extends AbstractConverter<String, Byte> {
390            public StringToByte() {
391                super(String.class, Byte.class);
392            }
393    
394            public Byte convert(String obj) throws ConversionException {
395                return Byte.valueOf(obj);
396            }
397        }
398    
399        /**
400         * An object that converts a <code>String</code> to a
401         * <code>Double</code>.
402         */
403        public static class StringToDouble extends AbstractStringToNumberConverter<Double> {
404            public StringToDouble() {
405                super(Double.class);
406            }
407    
408            protected Double convert(Number number) throws ConversionException {
409                return number.doubleValue();
410            }
411    
412            public Double convert(String obj) throws ConversionException {
413                return Double.valueOf(obj);
414            }
415        }
416    
417        /**
418         * An object that converts a <code>String</code> to a
419         * <code>Float</code>.
420         */
421        public static class StringToFloat extends AbstractStringToNumberConverter<Float> {
422            public StringToFloat() {
423                super(Float.class);
424            }
425    
426            protected Float convert(Number number) throws ConversionException {
427                return number.floatValue();
428            }
429    
430            public Float convert(String obj) throws ConversionException {
431                return Float.valueOf(obj);
432            }
433        }
434    
435        /**
436         * An object that converts a <code>String</code> to an
437         * <code>Integer</code>.
438         */
439        public static class StringToInteger extends AbstractStringToNumberConverter<Integer> {
440            public StringToInteger() {
441                super(Integer.class);
442            }
443    
444            protected Integer convert(Number number) throws ConversionException {
445                return number.intValue();
446            }
447    
448            public Integer convert(String obj) throws ConversionException {
449                return Integer.valueOf(obj);
450            }
451        }
452    
453        /**
454         * An object that converts a <code>String</code> to a
455         * <code>Long</code>.
456         */
457        public static class StringToLong extends AbstractStringToNumberConverter<Long> {
458            public StringToLong() {
459                super(Long.class);
460            }
461    
462            protected Long convert(Number number) throws ConversionException {
463                return number.longValue();
464            }
465    
466            public Long convert(String obj) throws ConversionException {
467                return Long.valueOf(obj);
468            }
469        }
470    
471        /**
472         * An object that converts a <code>String</code> to a
473         * <code>Short</code>.
474         */
475        public static class StringToShort extends AbstractConverter<String, Short> {
476            public StringToShort() {
477                super(String.class, Short.class);
478            }
479    
480            public Short convert(String obj) throws ConversionException {
481                return Short.valueOf(obj);
482            }
483        }
484    }