1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package net.sf.morph.transform.converters;
17
18 import java.text.NumberFormat;
19 import java.util.Locale;
20
21 import net.sf.morph.Defaults;
22 import net.sf.morph.transform.Converter;
23 import net.sf.morph.transform.DecoratedConverter;
24 import net.sf.morph.transform.ImpreciseTransformer;
25 import net.sf.morph.transform.transformers.BaseTransformer;
26 import net.sf.morph.util.TransformerUtils;
27
28 /**
29 * Converts {@link java.lang.Number}s into basic text types ({@link java.lang.String},
30 * {@link java.lang.StringBuffer} or {@link java.lang.Character}).
31 *
32 * @author Matt Sgarlata
33 * @since Jan 26, 2006
34 */
35 public class NumberToTextConverter extends BaseTransformer implements DecoratedConverter,
36 ImpreciseTransformer {
37
38 private Converter textConverter;
39 private Converter numberConverter;
40
41 /**
42 * {@inheritDoc}
43 */
44 protected Object convertImpl(Class destinationClass, Object source, Locale locale) throws Exception {
45 String formatted = getNumberFormat(locale).format(source);
46 return getTextConverter().convert(destinationClass, formatted, locale);
47 }
48
49 /**
50 * {@inheritDoc}
51 */
52 protected Class[] getSourceClassesImpl() throws Exception {
53 return getNumberConverter().getDestinationClasses();
54 }
55
56 /**
57 * {@inheritDoc}
58 */
59 protected Class[] getDestinationClassesImpl() throws Exception {
60 return getTextConverter().getSourceClasses();
61 }
62
63 /**
64 * {@inheritDoc}
65 */
66 protected boolean isImpreciseTransformationImpl(Class destinationClass, Class sourceClass) {
67 return TransformerUtils.isImpreciseTransformation(getTextConverter(), destinationClass, String.class);
68 }
69
70 /**
71 * Get the number converter used by this NumberToTextConverter.
72 * @return Converter
73 */
74 public Converter getNumberConverter() {
75 if (numberConverter == null) {
76 setNumberConverter(Defaults.createNumberConverter());
77 }
78 return numberConverter;
79 }
80
81 /**
82 * Sets the <code>numberConverter</code> to be used. Note that this method
83 * should be called before the transformer is used. Otherwise, if another
84 * thread is in the middle of transforming an object graph and this method
85 * is called, the behavior of the transformer can change partway through the
86 * transformation.
87 *
88 * @param numberConverter
89 * the <code>numberConverter</code> to be used
90 */
91 public synchronized void setNumberConverter(Converter numberConverter) {
92 this.numberConverter = numberConverter;
93 }
94
95 /**
96 * Get the text converter used by this NumberToTextConverter.
97 * @return Converter
98 */
99 public Converter getTextConverter() {
100 if (textConverter == null) {
101 setTextConverter(Defaults.createTextConverter());
102 }
103 return textConverter;
104 }
105
106 /**
107 * Sets the <code>textConverter</code> to be used. Note that this method
108 * should be called before the transformer is used. Otherwise, if another
109 * thread is in the middle of transforming an object graph and this method
110 * is called, the behavior of the transformer can change partway through the
111 * transformation.
112 *
113 * @param textConverter
114 * the <code>textConverter</code> to be used
115 */
116 public synchronized void setTextConverter(Converter textConverter) {
117 this.textConverter = textConverter;
118 }
119
120 /**
121 * Retrieves the {@link NumberFormat} instance to be used to in the given
122 * locale to format numbers as text. Subclasses can override this method to
123 * customize the behavior of this converter.
124 *
125 * @param locale
126 * the locale
127 * @return the {@link NumberFormat} instance to be used to in the given
128 * locale to format numbers as text
129 */
130 protected NumberFormat getNumberFormat(Locale locale) {
131 NumberFormat numberFormat = NumberFormat.getInstance(locale);
132 numberFormat.setGroupingUsed(false);
133 numberFormat.setMaximumFractionDigits(Integer.MAX_VALUE);
134 return numberFormat;
135 }
136
137 /**
138 * {@inheritDoc}
139 */
140 protected boolean isWrappingRuntimeExceptions() {
141 return true;
142 }
143
144 }