001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.commons.lang.math;
018:
019: import java.io.Serializable;
020:
021: /**
022: * <p><code>IntRange</code> represents an inclusive range of <code>int</code>s.</p>
023: *
024: * @author Stephen Colebourne
025: * @since 2.0
026: * @version $Id: IntRange.java 437554 2006-08-28 06:21:41Z bayard $
027: */
028: public final class IntRange extends Range implements Serializable {
029:
030: /**
031: * Required for serialization support.
032: *
033: * @see java.io.Serializable
034: */
035: private static final long serialVersionUID = 71849363892730L;
036:
037: /**
038: * The minimum number in this range (inclusive).
039: */
040: private final int min;
041: /**
042: * The maximum number in this range (inclusive).
043: */
044: private final int max;
045:
046: /**
047: * Cached output minObject (class is immutable).
048: */
049: private transient Integer minObject = null;
050: /**
051: * Cached output maxObject (class is immutable).
052: */
053: private transient Integer maxObject = null;
054: /**
055: * Cached output hashCode (class is immutable).
056: */
057: private transient int hashCode = 0;
058: /**
059: * Cached output toString (class is immutable).
060: */
061: private transient String toString = null;
062:
063: /**
064: * <p>Constructs a new <code>IntRange</code> using the specified
065: * number as both the minimum and maximum in this range.</p>
066: *
067: * @param number the number to use for this range
068: */
069: public IntRange(int number) {
070: super ();
071: this .min = number;
072: this .max = number;
073: }
074:
075: /**
076: * <p>Constructs a new <code>IntRange</code> using the specified
077: * number as both the minimum and maximum in this range.</p>
078: *
079: * @param number the number to use for this range, must not be <code>null</code>
080: * @throws IllegalArgumentException if the number is <code>null</code>
081: */
082: public IntRange(Number number) {
083: super ();
084: if (number == null) {
085: throw new IllegalArgumentException(
086: "The number must not be null");
087: }
088: this .min = number.intValue();
089: this .max = number.intValue();
090: if (number instanceof Integer) {
091: this .minObject = (Integer) number;
092: this .maxObject = (Integer) number;
093: }
094: }
095:
096: /**
097: * <p>Constructs a new <code>IntRange</code> with the specified
098: * minimum and maximum numbers (both inclusive).</p>
099: *
100: * <p>The arguments may be passed in the order (min,max) or (max,min). The
101: * getMinimum and getMaximum methods will return the correct values.</p>
102: *
103: * @param number1 first number that defines the edge of the range, inclusive
104: * @param number2 second number that defines the edge of the range, inclusive
105: */
106: public IntRange(int number1, int number2) {
107: super ();
108: if (number2 < number1) {
109: this .min = number2;
110: this .max = number1;
111: } else {
112: this .min = number1;
113: this .max = number2;
114: }
115: }
116:
117: /**
118: * <p>Constructs a new <code>IntRange</code> with the specified
119: * minimum and maximum numbers (both inclusive).</p>
120: *
121: * <p>The arguments may be passed in the order (min,max) or (max,min). The
122: * getMinimum and getMaximum methods will return the correct values.</p>
123: *
124: * @param number1 first number that defines the edge of the range, inclusive
125: * @param number2 second number that defines the edge of the range, inclusive
126: * @throws IllegalArgumentException if either number is <code>null</code>
127: */
128: public IntRange(Number number1, Number number2) {
129: super ();
130: if (number1 == null || number2 == null) {
131: throw new IllegalArgumentException(
132: "The numbers must not be null");
133: }
134: int number1val = number1.intValue();
135: int number2val = number2.intValue();
136: if (number2val < number1val) {
137: this .min = number2val;
138: this .max = number1val;
139: if (number2 instanceof Integer) {
140: this .minObject = (Integer) number2;
141: }
142: if (number1 instanceof Integer) {
143: this .maxObject = (Integer) number1;
144: }
145: } else {
146: this .min = number1val;
147: this .max = number2val;
148: if (number1 instanceof Integer) {
149: this .minObject = (Integer) number1;
150: }
151: if (number2 instanceof Integer) {
152: this .maxObject = (Integer) number2;
153: }
154: }
155: }
156:
157: // Accessors
158: //--------------------------------------------------------------------
159:
160: /**
161: * <p>Returns the minimum number in this range.</p>
162: *
163: * @return the minimum number in this range
164: */
165: public Number getMinimumNumber() {
166: if (minObject == null) {
167: minObject = new Integer(min);
168: }
169: return minObject;
170: }
171:
172: /**
173: * <p>Gets the minimum number in this range as a <code>long</code>.</p>
174: *
175: * @return the minimum number in this range
176: */
177: public long getMinimumLong() {
178: return min;
179: }
180:
181: /**
182: * <p>Gets the minimum number in this range as a <code>int</code>.</p>
183: *
184: * @return the minimum number in this range
185: */
186: public int getMinimumInteger() {
187: return min;
188: }
189:
190: /**
191: * <p>Gets the minimum number in this range as a <code>double</code>.</p>
192: *
193: * @return the minimum number in this range
194: */
195: public double getMinimumDouble() {
196: return min;
197: }
198:
199: /**
200: * <p>Gets the minimum number in this range as a <code>float</code>.</p>
201: *
202: * @return the minimum number in this range
203: */
204: public float getMinimumFloat() {
205: return min;
206: }
207:
208: /**
209: * <p>Returns the maximum number in this range.</p>
210: *
211: * @return the maximum number in this range
212: */
213: public Number getMaximumNumber() {
214: if (maxObject == null) {
215: maxObject = new Integer(max);
216: }
217: return maxObject;
218: }
219:
220: /**
221: * <p>Gets the maximum number in this range as a <code>long</code>.</p>
222: *
223: * @return the maximum number in this range
224: */
225: public long getMaximumLong() {
226: return max;
227: }
228:
229: /**
230: * <p>Gets the maximum number in this range as a <code>int</code>.</p>
231: *
232: * @return the maximum number in this range
233: */
234: public int getMaximumInteger() {
235: return max;
236: }
237:
238: /**
239: * <p>Gets the maximum number in this range as a <code>double</code>.</p>
240: *
241: * @return the maximum number in this range
242: */
243: public double getMaximumDouble() {
244: return max;
245: }
246:
247: /**
248: * <p>Gets the maximum number in this range as a <code>float</code>.</p>
249: *
250: * @return the maximum number in this range
251: */
252: public float getMaximumFloat() {
253: return max;
254: }
255:
256: // Tests
257: //--------------------------------------------------------------------
258:
259: /**
260: * <p>Tests whether the specified <code>number</code> occurs within
261: * this range using <code>int</code> comparison.</p>
262: *
263: * <p><code>null</code> is handled and returns <code>false</code>.</p>
264: *
265: * @param number the number to test, may be <code>null</code>
266: * @return <code>true</code> if the specified number occurs within this range
267: */
268: public boolean containsNumber(Number number) {
269: if (number == null) {
270: return false;
271: }
272: return containsInteger(number.intValue());
273: }
274:
275: /**
276: * <p>Tests whether the specified <code>int</code> occurs within
277: * this range using <code>int</code> comparison.</p>
278: *
279: * <p>This implementation overrides the superclass for performance as it is
280: * the most common case.</p>
281: *
282: * @param value the int to test
283: * @return <code>true</code> if the specified number occurs within this
284: * range by <code>int</code> comparison
285: */
286: public boolean containsInteger(int value) {
287: return value >= min && value <= max;
288: }
289:
290: // Range tests
291: //--------------------------------------------------------------------
292:
293: /**
294: * <p>Tests whether the specified range occurs entirely within this range
295: * using <code>int</code> comparison.</p>
296: *
297: * <p><code>null</code> is handled and returns <code>false</code>.</p>
298: *
299: * @param range the range to test, may be <code>null</code>
300: * @return <code>true</code> if the specified range occurs entirely within this range
301: * @throws IllegalArgumentException if the range is not of this type
302: */
303: public boolean containsRange(Range range) {
304: if (range == null) {
305: return false;
306: }
307: return containsInteger(range.getMinimumInteger())
308: && containsInteger(range.getMaximumInteger());
309: }
310:
311: /**
312: * <p>Tests whether the specified range overlaps with this range
313: * using <code>int</code> comparison.</p>
314: *
315: * <p><code>null</code> is handled and returns <code>false</code>.</p>
316: *
317: * @param range the range to test, may be <code>null</code>
318: * @return <code>true</code> if the specified range overlaps with this range
319: */
320: public boolean overlapsRange(Range range) {
321: if (range == null) {
322: return false;
323: }
324: return range.containsInteger(min) || range.containsInteger(max)
325: || containsInteger(range.getMinimumInteger());
326: }
327:
328: // Basics
329: //--------------------------------------------------------------------
330:
331: /**
332: * <p>Compares this range to another object to test if they are equal.</p>.
333: *
334: * <p>To be equal, the class, minimum and maximum must be equal.</p>
335: *
336: * @param obj the reference object with which to compare
337: * @return <code>true</code> if this object is equal
338: */
339: public boolean equals(Object obj) {
340: if (obj == this ) {
341: return true;
342: }
343: if (obj instanceof IntRange == false) {
344: return false;
345: }
346: IntRange range = (IntRange) obj;
347: return min == range.min && max == range.max;
348: }
349:
350: /**
351: * <p>Gets a hashCode for the range.</p>
352: *
353: * @return a hash code value for this object
354: */
355: public int hashCode() {
356: if (hashCode == 0) {
357: hashCode = 17;
358: hashCode = 37 * hashCode + getClass().hashCode();
359: hashCode = 37 * hashCode + min;
360: hashCode = 37 * hashCode + max;
361: }
362: return hashCode;
363: }
364:
365: /**
366: * <p>Gets the range as a <code>String</code>.</p>
367: *
368: * <p>The format of the String is 'Range[<i>min</i>,<i>max</i>]'.</p>
369: *
370: * @return the <code>String</code> representation of this range
371: */
372: public String toString() {
373: if (toString == null) {
374: StringBuffer buf = new StringBuffer(32);
375: buf.append("Range[");
376: buf.append(min);
377: buf.append(',');
378: buf.append(max);
379: buf.append(']');
380: toString = buf.toString();
381: }
382: return toString;
383: }
384:
385: }
|