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.DecimalFormat;
024    import java.text.NumberFormat;
025    import java.text.ParseException;
026    import java.util.Locale;
027    import java.util.TimeZone;
028    
029    /** Number Converter classes. */
030    public class NumberConverters implements ConverterLoader {
031    
032        protected static final Class<?>[] classArray = {BigDecimal.class, BigInteger.class, Byte.class, Double.class, Integer.class, Float.class, Long.class, Short.class};
033    
034        protected static Number fromString(String str, NumberFormat nf) throws ConversionException {
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        /**
066         * An abstract <code>Number</code> to <code>String</code> converter class
067         * that implements some of the <code>LocalizedConverter</code> methods. 
068         */
069        public static abstract class AbstractNumberToStringConverter<N extends Number> extends AbstractLocalizedConverter<N, String> {
070            public AbstractNumberToStringConverter(Class<N> sourceClass) {
071                super(sourceClass, String.class);
072            }
073    
074            public String convert(N obj) throws ConversionException {
075                return obj.toString();
076            }
077    
078            public String convert(N obj, Locale locale, TimeZone timeZone, String formatString) throws ConversionException {
079                if (formatString == null) {
080                    return format(obj, NumberFormat.getNumberInstance(locale));
081                } else {
082                    return format(obj, new DecimalFormat(formatString));
083                }
084            }
085    
086            protected abstract String format(N obj, NumberFormat nf) throws ConversionException;
087        }
088    
089        /**
090         * An abstract <code>String</code> to <code>Number</code> converter class
091         * that implements some of the <code>LocalizedConverter</code> methods. 
092         */
093        public static abstract class AbstractStringToNumberConverter<N extends Number> extends AbstractLocalizedConverter<String, N> {
094            public AbstractStringToNumberConverter(Class<N> targetClass) {
095                super(String.class, targetClass);
096            }
097    
098            protected abstract N convert(Number number) throws ConversionException;
099    
100            public N convert(String obj, Locale locale, TimeZone timeZone, String formatString) throws ConversionException {
101                if (formatString == null) {
102                    return convert(fromString(obj, NumberFormat.getNumberInstance(locale)));
103                } else {
104                    return convert(fromString(obj, new DecimalFormat(formatString)));
105                }
106            }
107        }
108    
109        /**
110         * An object that converts a <code>BigDecimal</code> to a
111         * <code>String</code>.
112         */
113        public static class BigDecimalToString extends AbstractNumberToStringConverter<BigDecimal> {
114            public BigDecimalToString() {
115                super(BigDecimal.class);
116            }
117    
118            protected String format(BigDecimal obj, NumberFormat nf) throws ConversionException {
119                return nf.format(obj.doubleValue());
120            }
121        }
122    
123        /**
124         * An object that converts a <code>BigInteger</code> to a
125         * <code>String</code>.
126         */
127        public static class BigIntegerToString extends AbstractNumberToStringConverter<BigInteger> {
128            public BigIntegerToString() {
129                super(BigInteger.class);
130            }
131    
132            protected String format(BigInteger obj, NumberFormat nf) throws ConversionException {
133                return nf.format(obj.doubleValue());
134            }
135        }
136    
137        /**
138         * An object that converts a <code>Byte</code> to a
139         * <code>String</code>.
140         */
141        public static class ByteToString extends AbstractNumberToStringConverter<Byte> {
142            public ByteToString() {
143                super(Byte.class);
144            }
145    
146            protected String format(Byte obj, NumberFormat nf) throws ConversionException {
147                return nf.format(obj.floatValue());
148            }
149        }
150    
151        /**
152         * An object that converts a <code>Double</code> to a
153         * <code>String</code>.
154         */
155        public static class DoubleToString extends AbstractNumberToStringConverter<Double> {
156            public DoubleToString() {
157                super(Double.class);
158            }
159    
160            protected String format(Double obj, NumberFormat nf) throws ConversionException {
161                return nf.format(obj.doubleValue());
162            }
163        }
164    
165        /**
166         * An object that converts a <code>Float</code> to a
167         * <code>String</code>.
168         */
169        public static class FloatToString extends AbstractNumberToStringConverter<Float> {
170            public FloatToString() {
171                super(Float.class);
172            }
173    
174            protected String format(Float obj, NumberFormat nf) throws ConversionException {
175                return nf.format(obj.floatValue());
176            }
177        }
178    
179        /**
180         * An object that converts a <code>Number</code> to a
181         * <code>BigDecimal</code>.
182         */
183        public static class GenericNumberToBigDecimal<N extends Number> extends AbstractConverter<N, BigDecimal> {
184            public GenericNumberToBigDecimal(Class<N> sourceClass) {
185                super(sourceClass, BigDecimal.class);
186            }
187    
188            public BigDecimal convert(N obj) throws ConversionException {
189                return new BigDecimal(obj.doubleValue());
190            }
191        }
192    
193        /**
194         * An object that converts a <code>Number</code> to a
195         * <code>BigInteger</code>.
196         */
197        public static class GenericNumberToBigInteger<N extends Number> extends AbstractConverter<N, BigInteger> {
198            public GenericNumberToBigInteger(Class<N> sourceClass) {
199                super(sourceClass, BigInteger.class);
200            }
201    
202            public BigInteger convert(N obj) throws ConversionException {
203                return BigInteger.valueOf(obj.longValue());
204            }
205        }
206    
207        /**
208         * An object that converts a <code>Number</code> to a
209         * <code>Byte</code>.
210         */
211        public static class GenericNumberToByte<N extends Number> extends AbstractConverter<N, Byte> {
212            public GenericNumberToByte(Class<N> sourceClass) {
213                super(sourceClass, Byte.class);
214            }
215    
216            public Byte convert(N obj) throws ConversionException {
217                return Byte.valueOf(obj.byteValue());
218            }
219        }
220    
221        /**
222         * An object that converts a <code>Number</code> to a
223         * <code>Double</code>.
224         */
225        public static class GenericNumberToDouble<N extends Number> extends AbstractConverter<N, Double> {
226            public GenericNumberToDouble(Class<N> sourceClass) {
227                super(sourceClass, Double.class);
228            }
229    
230            public Double convert(N obj) throws ConversionException {
231                return obj.doubleValue();
232            }
233        }
234    
235        /**
236         * An object that converts a <code>Number</code> to a
237         * <code>Float</code>.
238         */
239        public static class GenericNumberToFloat<N extends Number> extends AbstractConverter<N, Float> {
240            public GenericNumberToFloat(Class<N> sourceClass) {
241                super(sourceClass, Float.class);
242            }
243    
244            public Float convert(N obj) throws ConversionException {
245                return obj.floatValue();
246            }
247        }
248    
249        /**
250         * An object that converts a <code>Number</code> to an
251         * <code>Integer</code>.
252         */
253        public static class GenericNumberToInteger<N extends Number> extends AbstractConverter<N, Integer> {
254            public GenericNumberToInteger(Class<N> sourceClass) {
255                super(sourceClass, Integer.class);
256            }
257    
258            public Integer convert(N obj) throws ConversionException {
259                return obj.intValue();
260            }
261        }
262    
263        /**
264         * An object that converts a <code>Number</code> to a
265         * <code>Long</code>.
266         */
267        public static class GenericNumberToLong<N extends Number> extends AbstractConverter<N, Long> {
268            public GenericNumberToLong(Class<N> sourceClass) {
269                super(sourceClass, Long.class);
270            }
271    
272            public Long convert(N obj) throws ConversionException {
273                return obj.longValue();
274            }
275        }
276    
277        /**
278         * An object that converts a <code>Number</code> to a
279         * <code>Short</code>.
280         */
281        public static class GenericNumberToShort<N extends Number> extends AbstractConverter<N, Short> {
282            public GenericNumberToShort(Class<N> sourceClass) {
283                super(sourceClass, Short.class);
284            }
285    
286            public Short convert(N obj) throws ConversionException {
287                return obj.shortValue();
288            }
289        }
290    
291        /**
292         * An object that converts an <code>Integer</code> to a
293         * <code>String</code>.
294         */
295        public static class IntegerToString extends AbstractNumberToStringConverter<Integer> {
296            public IntegerToString() {
297                super(Integer.class);
298            }
299    
300            protected String format(Integer obj, NumberFormat nf) throws ConversionException {
301                return nf.format(obj.intValue());
302            }
303        }
304    
305        /**
306         * An object that converts a <code>Long</code> to a
307         * <code>BigDecimal</code>.
308         */
309        public static class LongToBigDecimal extends AbstractConverter<Long, BigDecimal> {
310            public LongToBigDecimal() {
311                super(Long.class, BigDecimal.class);
312            }
313    
314            public BigDecimal convert(Long obj) throws ConversionException {
315                return BigDecimal.valueOf(obj.longValue());
316            }
317        }
318    
319        /**
320         * An object that converts a <code>Long</code> to a
321         * <code>String</code>.
322         */
323        public static class LongToString extends AbstractNumberToStringConverter<Long> {
324            public LongToString() {
325                super(Long.class);
326            }
327    
328            protected String format(Long obj, NumberFormat nf) throws ConversionException {
329                return nf.format(obj.longValue());
330            }
331        }
332    
333        /**
334         * An object that converts a <code>Short</code> to a
335         * <code>String</code>.
336         */
337        public static class ShortToString extends AbstractNumberToStringConverter<Short> {
338            public ShortToString() {
339                super(Short.class);
340            }
341    
342            protected String format(Short obj, NumberFormat nf) throws ConversionException {
343                return nf.format(obj.floatValue());
344            }
345        }
346    
347        /**
348         * An object that converts a <code>String</code> to a
349         * <code>BigDecimal</code>.
350         */
351        public static class StringToBigDecimal extends AbstractStringToNumberConverter<BigDecimal> {
352            public StringToBigDecimal() {
353                super(BigDecimal.class);
354            }
355    
356            protected BigDecimal convert(Number number) throws ConversionException {
357                return BigDecimal.valueOf(number.doubleValue());
358            }
359    
360            public BigDecimal convert(String obj) throws ConversionException {
361                return BigDecimal.valueOf(Double.valueOf(obj));
362            }
363        }
364    
365        /**
366         * An object that converts a <code>String</code> to a
367         * <code>BigInteger</code>.
368         */
369        public static class StringToBigInteger extends AbstractStringToNumberConverter<BigInteger> {
370            public StringToBigInteger() {
371                super(BigInteger.class);
372            }
373    
374            protected BigInteger convert(Number number) throws ConversionException {
375                return BigInteger.valueOf(number.longValue());
376            }
377    
378            public BigInteger convert(String obj) throws ConversionException {
379                return new BigInteger(obj);
380            }
381        }
382    
383        /**
384         * An object that converts a <code>String</code> to a
385         * <code>Byte</code>.
386         */
387        public static class StringToByte extends AbstractConverter<String, Byte> {
388            public StringToByte() {
389                super(String.class, Byte.class);
390            }
391    
392            public Byte convert(String obj) throws ConversionException {
393                return Byte.valueOf(obj);
394            }
395        }
396    
397        /**
398         * An object that converts a <code>String</code> to a
399         * <code>Double</code>.
400         */
401        public static class StringToDouble extends AbstractStringToNumberConverter<Double> {
402            public StringToDouble() {
403                super(Double.class);
404            }
405    
406            protected Double convert(Number number) throws ConversionException {
407                return number.doubleValue();
408            }
409    
410            public Double convert(String obj) throws ConversionException {
411                return Double.valueOf(obj);
412            }
413        }
414    
415        /**
416         * An object that converts a <code>String</code> to a
417         * <code>Float</code>.
418         */
419        public static class StringToFloat extends AbstractStringToNumberConverter<Float> {
420            public StringToFloat() {
421                super(Float.class);
422            }
423    
424            protected Float convert(Number number) throws ConversionException {
425                return number.floatValue();
426            }
427    
428            public Float convert(String obj) throws ConversionException {
429                return Float.valueOf(obj);
430            }
431        }
432    
433        /**
434         * An object that converts a <code>String</code> to an
435         * <code>Integer</code>.
436         */
437        public static class StringToInteger extends AbstractStringToNumberConverter<Integer> {
438            public StringToInteger() {
439                super(Integer.class);
440            }
441    
442            protected Integer convert(Number number) throws ConversionException {
443                return number.intValue();
444            }
445    
446            public Integer convert(String obj) throws ConversionException {
447                return Integer.valueOf(obj);
448            }
449        }
450    
451        /**
452         * An object that converts a <code>String</code> to a
453         * <code>Long</code>.
454         */
455        public static class StringToLong extends AbstractStringToNumberConverter<Long> {
456            public StringToLong() {
457                super(Long.class);
458            }
459    
460            protected Long convert(Number number) throws ConversionException {
461                return number.longValue();
462            }
463    
464            public Long convert(String obj) throws ConversionException {
465                return Long.valueOf(obj);
466            }
467        }
468    
469        /**
470         * An object that converts a <code>String</code> to a
471         * <code>Short</code>.
472         */
473        public static class StringToShort extends AbstractConverter<String, Short> {
474            public StringToShort() {
475                super(String.class, Short.class);
476            }
477    
478            public Short convert(String obj) throws ConversionException {
479                return Short.valueOf(obj);
480            }
481        }
482    }