1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package net.sf.morph.transform.support;
17
18 import java.math.BigDecimal;
19
20 import net.sf.morph.util.NumberUtils;
21
22 /**
23 * @author Matt Sgarlata
24 * @since Dec 15, 2004
25 */
26 public abstract class NumberRounder {
27
28 /**
29 * Rounding mode specified in {@link BigDecimal}.
30 *
31 * @see BigDecimal#ROUND_CEILING
32 */
33 public static final String ROUND_CEILING = "ROUND_CEILING";
34 /**
35 * Rounding mode specified in {@link BigDecimal}.
36 *
37 * @see BigDecimal#ROUND_DOWN
38 */
39 public static final String ROUND_DOWN = "ROUND_DOWN";
40 /**
41 * Rounding mode specified in {@link BigDecimal}.
42 *
43 * @see BigDecimal#ROUND_FLOOR
44 */
45 public static final String ROUND_FLOOR = "ROUND_FLOOR";
46 /**
47 * Rounding mode specified in {@link BigDecimal}.
48 *
49 * @see BigDecimal#ROUND_HALF_DOWN
50 */
51 public static final String ROUND_HALF_DOWN = "ROUND_HALF_DOWN";
52 /**
53 * Rounding mode specified in {@link BigDecimal}.
54 *
55 * @see BigDecimal#ROUND_HALF_EVEN
56 */
57 public static final String ROUND_HALF_EVEN = "ROUND_HALF_EVEN";
58 /**
59 * Rounding mode specified in {@link BigDecimal}.
60 *
61 * @see BigDecimal#ROUND_HALF_UP
62 */
63 public static final String ROUND_HALF_UP = "ROUND_HALF_UP";
64 /**
65 * Rounding mode specified in {@link BigDecimal}.
66 *
67 * @see BigDecimal#ROUND_UP
68 */
69 public static final String ROUND_UP = "ROUND_UP";
70
71 /**
72 * Converts a rounding mode defined in this class to one of the rounding
73 * mode <code>int</code>s specified in the {@link BigDecimal} class.
74 *
75 * @param mode
76 * the String representation of the mode, as defined in one of
77 * the constants of this class
78 * @return the int representation of the mode, as defined in the
79 * {@link BigDecimal} class.
80 * @throws IllegalArgumentException
81 * if an invalid rounding mode was specified
82 */
83 public static int getBigDecimalRoundMode(String mode)
84 throws IllegalArgumentException {
85 if (ROUND_CEILING.equals(mode)) {
86 return BigDecimal.ROUND_CEILING;
87 }
88 if (ROUND_DOWN.equals(mode)) {
89 return BigDecimal.ROUND_DOWN;
90 }
91 if (ROUND_FLOOR.equals(mode)) {
92 return BigDecimal.ROUND_FLOOR;
93 }
94 if (ROUND_HALF_DOWN.equals(mode)) {
95 return BigDecimal.ROUND_HALF_DOWN;
96 }
97 if (ROUND_HALF_EVEN.equals(mode)) {
98 return BigDecimal.ROUND_HALF_EVEN;
99 }
100 if (ROUND_HALF_UP.equals(mode)) {
101 return BigDecimal.ROUND_HALF_UP;
102 }
103 if (ROUND_UP.equals(mode)) {
104 return BigDecimal.ROUND_UP;
105 }
106 throw new IllegalArgumentException("'" + mode + "' is not a valid rounding mode. Please specify one of the constants defined in " + NumberRounder.class.getName());
107 }
108
109 /**
110 * Rounds the given number using the given rounding mode. The type of the
111 * number is maintained (e.g. - if the number was a Float, it will remain
112 * so).
113 *
114 * @param number
115 * the number to round
116 * @param mode
117 * the rounding mode, as specified by one of the constants in
118 * this class
119 * @return <code>null</code>, if <code>number</code> is
120 * <code>null</code> or <br>
121 * <code>number</code> rounded as requested, otherwise
122 * @throws IllegalArgumentException
123 * if an invalid rounding mode is specified
124 */
125 public static Number round(Number number, String mode)
126 throws IllegalArgumentException {
127 if (NumberUtils.isDecimal(number)) {
128 BigDecimal bigDecimal = NumberUtils.numberToBigDecimal(number);
129 BigDecimal rounded = bigDecimal.setScale(0, getBigDecimalRoundMode(mode));
130 if (number instanceof BigDecimal) {
131 return rounded;
132 }
133 if (number instanceof Double) {
134 return new Double(rounded.doubleValue());
135 }
136 if (number instanceof Float) {
137 return new Float(rounded.floatValue());
138 }
139 }
140 return number;
141 }
142
143 }