1 /*
2 * Copyright 2006-2007 The Kuali Foundation
3 *
4 * Licensed under the Educational Community License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.opensource.org/licenses/ecl2.php
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.kuali.rice.kns.util;
17
18 import java.math.BigDecimal;
19 import java.math.BigInteger;
20 import java.math.MathContext;
21 import java.math.RoundingMode;
22
23 public class KualiInteger extends Number implements Comparable {
24 public static final int ROUND_BEHAVIOR = KualiDecimal.ROUND_BEHAVIOR;
25 public static final int SCALE = 0;
26
27 public static KualiInteger ZERO = new KualiInteger(0);
28
29 private final BigInteger value;
30
31 /**
32 * Constructor - only accepts a string representation of the value.
33 *
34 * This is done to prevent unexpected inaccuracy by conversion to and from floating-point values.
35 *
36 * @param value String containing numeric value
37 * @throws IllegalArgumentException if the given String is null
38 */
39 public KualiInteger(String value) {
40 if (value == null) {
41 throw new IllegalArgumentException("invalid (null) String in KualiInteger constructor");
42 }
43
44 this.value = new BigInteger(value);
45 }
46
47 /**
48 * Initializes this instance to the given integer value with integer arithmetic.
49 */
50 public KualiInteger(long value) {
51 this.value = BigInteger.valueOf(value);
52 }
53
54 /**
55 * Simple constructor, copies in the given BigInteger as the value for the instance.
56 *
57 * @param value BigInteger to be used as basis for value
58 * @throws IllegalArgumentException if the given BigDecimal is null
59 */
60 public KualiInteger(BigInteger value) {
61 if (value == null) {
62 throw new IllegalArgumentException("invalid (null) BigDecimal in KualiDecimal constructor");
63 }
64
65 this.value = value;
66 }
67
68 /**
69 * Simple constructor, copies in the given BigInteger as the value for the instance.
70 *
71 * @param value BigInteger to be used as basis for value
72 * @throws IllegalArgumentException if the given BigDecimal is null
73 */
74 public KualiInteger(BigDecimal value) {
75 if (value == null) {
76 throw new IllegalArgumentException("invalid (null) BigDecimal in KualiDecimal constructor");
77 }
78
79 this.value = value.setScale(SCALE, ROUND_BEHAVIOR).toBigInteger();
80 }
81
82 /**
83 * Simple constructor, rounds the given KualiDecimal according to the RoundingMode
84 *
85 * @param value KualiDecmial to be used as basis for value
86 * @param roundingMode RoundingMode for converting to Integer
87 * @throws IllegalArgumentException if the given KualiDecmial or RoundingMode is null
88 */
89 public KualiInteger(KualiDecimal value, RoundingMode roundingMode) {
90 if (value == null) {
91 throw new IllegalArgumentException("invalid (null) KualiDecimal in KualiInteger constructor");
92 }
93 if (roundingMode == null) {
94 throw new IllegalArgumentException("invalid (null) RoundingMode in KualiInteger constructor");
95 }
96
97 this.value = value.bigDecimalValue().round(new MathContext(0, roundingMode)).toBigInteger();
98 }
99
100 /**
101 * Wraps BigDecimal's add method to accept and return KualiDecimal instances instead of BigDecimals, so that users of the class
102 * don't have to typecast the return value.
103 *
104 * @param addend
105 * @return result of adding the given addend to this value
106 * @throws IllegalArgumentException if the given addend is null
107 */
108 public KualiInteger add(KualiInteger addend) {
109 if (addend == null) {
110 throw new IllegalArgumentException("invalid (null) addend");
111 }
112
113 BigInteger sum = this.value.add(addend.value);
114 return new KualiInteger(sum);
115 }
116
117 /**
118 * Wraps BigDecimal's subtract method to accept and return KualiDecimal instances instead of BigDecimals, so that users of the
119 * class don't have to typecast the return value.
120 *
121 * @param subtrahend
122 * @return result of the subtracting the given subtrahend from this value
123 * @throws IllegalArgumentException if the given subtrahend is null
124 */
125 public KualiInteger subtract(KualiInteger subtrahend) {
126 if (subtrahend == null) {
127 throw new IllegalArgumentException("invalid (null) subtrahend");
128 }
129
130 BigInteger difference = this.value.subtract(subtrahend.value);
131 return new KualiInteger(difference);
132 }
133
134 /**
135 * Wraps BigDecimal's multiply method to accept and return KualiInteger instances instead of BigDecimals, so that users of the
136 * class don't have to typecast the return value.
137 *
138 * @param multiplicand
139 * @return result of multiplying this value by the given multiplier
140 * @throws IllegalArgumentException if the given multiplier is null
141 */
142 public KualiInteger multiply(KualiInteger multiplier) {
143 if (multiplier == null) {
144 throw new IllegalArgumentException("invalid (null) multiplier");
145 }
146
147 BigInteger product = this.value.multiply(multiplier.value);
148 return new KualiInteger(product);
149 }
150
151 public KualiInteger multiply(BigDecimal multiplier) {
152 if (multiplier == null) {
153 throw new IllegalArgumentException("invalid (null) multiplier");
154 }
155
156 BigDecimal product = multiplier.multiply(new BigDecimal(this.value));
157 return new KualiInteger(product);
158 }
159
160 public KualiInteger multiply(KualiDecimal multiplier) {
161 return multiply(multiplier.bigDecimalValue());
162 }
163
164
165 public BigDecimal divide(BigDecimal dividend) {
166 if (dividend == null) {
167 throw new IllegalArgumentException("invalid (null) dividend");
168 }
169
170 return this.bigDecimalValue().divide(dividend, 8, ROUND_BEHAVIOR);
171 }
172
173 public BigDecimal divide(KualiInteger dividend) {
174 if (dividend == null) {
175 throw new IllegalArgumentException("invalid (null) dividend");
176 }
177
178 return divide(dividend.bigDecimalValue());
179 }
180
181 // Number methods
182 /**
183 * @see java.lang.Number#doubleValue()
184 */
185 public double doubleValue() {
186 return this.value.doubleValue();
187 }
188
189 /**
190 * @see java.lang.Number#floatValue()
191 */
192 public float floatValue() {
193 return this.value.floatValue();
194 }
195
196 /**
197 * @see java.lang.Number#intValue()
198 */
199 public int intValue() {
200 return this.value.intValue();
201 }
202
203 /**
204 * @see java.lang.Number#longValue()
205 */
206 public long longValue() {
207 return this.value.longValue();
208 }
209
210 /**
211 * @return the value of this instance as a BigDecimal.
212 */
213 public BigInteger bigIntegerValue() {
214 return this.value;
215 }
216
217 /**
218 * @return the value of this instance as a BigDecimal.
219 */
220 public BigDecimal bigDecimalValue() {
221 return new BigDecimal(this.value);
222 }
223
224 /**
225 * @return the value of this instance as a BigDecimal.
226 */
227 public KualiDecimal kualiDecimalValue() {
228 return new KualiDecimal(this.bigDecimalValue());
229 }
230
231
232 /**
233 * @param operand
234 * @return true if this KualiDecimal is less than the given KualiDecimal
235 */
236 public boolean isLessThan(KualiInteger operand) {
237 if (operand == null) {
238 throw new IllegalArgumentException("invalid (null) operand");
239 }
240
241 return (this.compareTo(operand) == -1);
242 }
243
244 /**
245 * @param operand
246 * @return true if this KualiDecimal is greater than the given KualiDecimal
247 */
248 public boolean isGreaterThan(KualiInteger operand) {
249 if (operand == null) {
250 throw new IllegalArgumentException("invalid (null) operand");
251 }
252
253 return (this.compareTo(operand) == 1);
254 }
255
256 /**
257 * @param operand
258 * @return true if this KualiDecimal is less than or equal to the given KualiDecimal
259 */
260 public boolean isLessEqual(KualiInteger operand) {
261 if (operand == null) {
262 throw new IllegalArgumentException("invalid (null) operand");
263 }
264
265 return !isGreaterThan(operand);
266 }
267
268 /**
269 * @param operand
270 * @return true if this KualiDecimal is greater than or equal to the given KualiDecimal
271 */
272 public boolean isGreaterEqual(KualiInteger operand) {
273 if (operand == null) {
274 throw new IllegalArgumentException("invalid (null) operand");
275 }
276
277 return !isLessThan(operand);
278 }
279
280 /**
281 * @return true if this KualiDecimal is less than zero
282 */
283 public boolean isNegative() {
284 return (this.compareTo(ZERO) == -1);
285 }
286
287 /**
288 * @return true if this KualiDecimal is greater than zero
289 */
290 public boolean isPositive() {
291 return (this.compareTo(ZERO) == 1);
292 }
293
294
295 /**
296 * @return true if this KualiDecimal is equal to zero
297 */
298 public boolean isZero() {
299 return (this.compareTo(ZERO) == 0);
300 }
301
302
303 /**
304 * @return true if this KualiDecimal is not equal to zero
305 */
306 public boolean isNonZero() {
307 return !this.isZero();
308 }
309
310 /**
311 * @return a KualiInteger with the same scale and a negated value (iff the value is non-zero)
312 */
313 public KualiInteger negated() {
314 return multiply(new KualiInteger("-1"));
315 }
316
317
318 // Comparable methods
319 /**
320 * Compares this KualiInteger with the specified Object. If the Object is a KualiInteger, this method behaves like
321 * java.lang.Comparable#compareTo(java.lang.Object).
322 *
323 * Otherwise, it throws a <tt>ClassCastException</tt> (as KualiIntegers are comparable only to other KualiIntegers).
324 *
325 * @see java.lang.Comparable#compareTo(java.lang.Object)
326 */
327 public int compareTo(Object o) {
328 return compareTo((KualiInteger) o);
329 }
330
331 /**
332 * Returns the result of comparing the values of this KualiInteger and the given KualiInteger.
333 *
334 * @see java.lang.Comparable#compareTo(java.lang.Object)
335 */
336 public int compareTo(KualiInteger k) {
337 return this.value.compareTo(k.value);
338 }
339
340
341 // Object methods
342 /**
343 * @see java.lang.Object#equals(java.lang.Object)
344 */
345 public boolean equals(Object obj) {
346 boolean equals = false;
347
348 if (obj instanceof KualiInteger) {
349 KualiInteger k = (KualiInteger) obj;
350
351 // using KualiInteger.compareTo instead of BigDecimal.equals since BigDecimal.equals only returns true if the
352 // scale and precision are equal, rather than comparing the actual (scaled) values
353 equals = (this.compareTo(k) == 0);
354 }
355
356 return equals;
357 }
358
359 /**
360 *
361 * @see java.lang.Object#hashCode()
362 */
363 public int hashCode() {
364 return this.value.hashCode();
365 }
366
367 /**
368 * @see java.lang.Object#toString()
369 */
370 public String toString() {
371 return this.value.toString();
372 }
373
374 }