View Javadoc

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 }