1. /* ====================================================================
  2. * The Apache Software License, Version 1.1
  3. *
  4. * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
  5. * reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. *
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in
  16. * the documentation and/or other materials provided with the
  17. * distribution.
  18. *
  19. * 3. The end-user documentation included with the redistribution, if
  20. * any, must include the following acknowledgement:
  21. * "This product includes software developed by the
  22. * Apache Software Foundation (http://www.apache.org/)."
  23. * Alternately, this acknowledgement may appear in the software itself,
  24. * if and wherever such third-party acknowledgements normally appear.
  25. *
  26. * 4. The names "The Jakarta Project", "Commons", and "Apache Software
  27. * Foundation" must not be used to endorse or promote products derived
  28. * from this software without prior written permission. For written
  29. * permission, please contact apache@apache.org.
  30. *
  31. * 5. Products derived from this software may not be called "Apache"
  32. * nor may "Apache" appear in their names without prior written
  33. * permission of the Apache Software Foundation.
  34. *
  35. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46. * SUCH DAMAGE.
  47. * ====================================================================
  48. *
  49. * This software consists of voluntary contributions made by many
  50. * individuals on behalf of the Apache Software Foundation. For more
  51. * information on the Apache Software Foundation, please see
  52. * <http://www.apache.org/>.
  53. */
  54. package org.apache.commons.lang.math;
  55. import java.io.Serializable;
  56. /**
  57. * <p><code>IntRange</code> represents an inclusive range of <code>int</code>s.</p>
  58. *
  59. * @author Stephen Colebourne
  60. * @since 2.0
  61. * @version $Id: IntRange.java,v 1.6 2003/08/18 02:22:24 bayard Exp $
  62. */
  63. public final class IntRange extends Range implements Serializable {
  64. private static final long serialVersionUID = 71849363892730L;
  65. /**
  66. * The minimum number in this range (inclusive).
  67. */
  68. private final int min;
  69. /**
  70. * The maximum number in this range (inclusive).
  71. */
  72. private final int max;
  73. /**
  74. * Cached output minObject (class is immutable).
  75. */
  76. private transient Integer minObject = null;
  77. /**
  78. * Cached output maxObject (class is immutable).
  79. */
  80. private transient Integer maxObject = null;
  81. /**
  82. * Cached output hashCode (class is immutable).
  83. */
  84. private transient int hashCode = 0;
  85. /**
  86. * Cached output toString (class is immutable).
  87. */
  88. private transient String toString = null;
  89. /**
  90. * <p>Constructs a new <code>IntRange</code> using the specified
  91. * number as both the minimum and maximum in this range.</p>
  92. *
  93. * @param number the number to use for this range
  94. */
  95. public IntRange(int number) {
  96. super();
  97. this.min = number;
  98. this.max = number;
  99. }
  100. /**
  101. * <p>Constructs a new <code>IntRange</code> using the specified
  102. * number as both the minimum and maximum in this range.</p>
  103. *
  104. * @param number the number to use for this range, must not be <code>null</code>
  105. * @throws IllegalArgumentException if the number is <code>null</code>
  106. */
  107. public IntRange(Number number) {
  108. super();
  109. if (number == null) {
  110. throw new IllegalArgumentException("The number must not be null");
  111. }
  112. this.min = number.intValue();
  113. this.max = number.intValue();
  114. if (number instanceof Integer) {
  115. this.minObject = (Integer) number;
  116. this.maxObject = (Integer) number;
  117. }
  118. }
  119. /**
  120. * <p>Constructs a new <code>IntRange</code> with the specified
  121. * minimum and maximum numbers (both inclusive).</p>
  122. *
  123. * <p>The arguments may be passed in the order (min,max) or (max,min). The
  124. * getMinimum and getMaximum methods will return the correct values.</p>
  125. *
  126. * @param number1 first number that defines the edge of the range, inclusive
  127. * @param number2 second number that defines the edge of the range, inclusive
  128. */
  129. public IntRange(int number1, int number2) {
  130. super();
  131. if (number2 < number1) {
  132. this.min = number2;
  133. this.max = number1;
  134. } else {
  135. this.min = number1;
  136. this.max = number2;
  137. }
  138. }
  139. /**
  140. * <p>Constructs a new <code>IntRange</code> with the specified
  141. * minimum and maximum numbers (both inclusive).</p>
  142. *
  143. * <p>The arguments may be passed in the order (min,max) or (max,min). The
  144. * getMinimum and getMaximum methods will return the correct values.</p>
  145. *
  146. * @param number1 first number that defines the edge of the range, inclusive
  147. * @param number2 second number that defines the edge of the range, inclusive
  148. * @throws IllegalArgumentException if either number is <code>null</code>
  149. */
  150. public IntRange(Number number1, Number number2) {
  151. super();
  152. if (number1 == null || number2 == null) {
  153. throw new IllegalArgumentException("The numbers must not be null");
  154. }
  155. int number1val = number1.intValue();
  156. int number2val = number2.intValue();
  157. if (number2val < number1val) {
  158. this.min = number2val;
  159. this.max = number1val;
  160. if (number2 instanceof Integer) {
  161. this.minObject = (Integer) number2;
  162. }
  163. if (number1 instanceof Integer) {
  164. this.maxObject = (Integer) number1;
  165. }
  166. } else {
  167. this.min = number1val;
  168. this.max = number2val;
  169. if (number1 instanceof Integer) {
  170. this.minObject = (Integer) number1;
  171. }
  172. if (number2 instanceof Integer) {
  173. this.maxObject = (Integer) number2;
  174. }
  175. }
  176. }
  177. // Accessors
  178. //--------------------------------------------------------------------
  179. /**
  180. * <p>Returns the minimum number in this range.</p>
  181. *
  182. * @return the minimum number in this range
  183. */
  184. public Number getMinimumNumber() {
  185. if (minObject == null) {
  186. minObject = new Integer(min);
  187. }
  188. return minObject;
  189. }
  190. /**
  191. * <p>Gets the minimum number in this range as a <code>long</code>.</p>
  192. *
  193. * @return the minimum number in this range
  194. */
  195. public long getMinimumLong() {
  196. return min;
  197. }
  198. /**
  199. * <p>Gets the minimum number in this range as a <code>int</code>.</p>
  200. *
  201. * @return the minimum number in this range
  202. */
  203. public int getMinimumInteger() {
  204. return min;
  205. }
  206. /**
  207. * <p>Gets the minimum number in this range as a <code>double</code>.</p>
  208. *
  209. * @return the minimum number in this range
  210. */
  211. public double getMinimumDouble() {
  212. return min;
  213. }
  214. /**
  215. * <p>Gets the minimum number in this range as a <code>float</code>.</p>
  216. *
  217. * @return the minimum number in this range
  218. */
  219. public float getMinimumFloat() {
  220. return min;
  221. }
  222. /**
  223. * <p>Returns the maximum number in this range.</p>
  224. *
  225. * @return the maximum number in this range
  226. */
  227. public Number getMaximumNumber() {
  228. if (maxObject == null) {
  229. maxObject = new Integer(max);
  230. }
  231. return maxObject;
  232. }
  233. /**
  234. * <p>Gets the maximum number in this range as a <code>long</code>.</p>
  235. *
  236. * @return the maximum number in this range
  237. */
  238. public long getMaximumLong() {
  239. return max;
  240. }
  241. /**
  242. * <p>Gets the maximum number in this range as a <code>int</code>.</p>
  243. *
  244. * @return the maximum number in this range
  245. */
  246. public int getMaximumInteger() {
  247. return max;
  248. }
  249. /**
  250. * <p>Gets the maximum number in this range as a <code>double</code>.</p>
  251. *
  252. * @return the maximum number in this range
  253. */
  254. public double getMaximumDouble() {
  255. return max;
  256. }
  257. /**
  258. * <p>Gets the maximum number in this range as a <code>float</code>.</p>
  259. *
  260. * @return the maximum number in this range
  261. */
  262. public float getMaximumFloat() {
  263. return max;
  264. }
  265. // Tests
  266. //--------------------------------------------------------------------
  267. /**
  268. * <p>Tests whether the specified <code>number</code> occurs within
  269. * this range using <code>int</code> comparison.</p>
  270. *
  271. * <p><code>null</code> is handled and returns <code>false</code>.</p>
  272. *
  273. * @param number the number to test, may be <code>null</code>
  274. * @return <code>true</code> if the specified number occurs within this range
  275. */
  276. public boolean containsNumber(Number number) {
  277. if (number == null) {
  278. return false;
  279. }
  280. return containsInteger(number.intValue());
  281. }
  282. /**
  283. * <p>Tests whether the specified <code>int</code> occurs within
  284. * this range using <code>int</code> comparison.</p>
  285. *
  286. * <p>This implementation overrides the superclass for performance as it is
  287. * the most common case.</p>
  288. *
  289. * @param value the int to test
  290. * @return <code>true</code> if the specified number occurs within this
  291. * range by <code>int</code> comparison
  292. */
  293. public boolean containsInteger(int value) {
  294. return (value >= min && value <= max);
  295. }
  296. // Range tests
  297. //--------------------------------------------------------------------
  298. /**
  299. * <p>Tests whether the specified range occurs entirely within this range
  300. * using <code>int</code> comparison.</p>
  301. *
  302. * <p><code>null</code> is handled and returns <code>false</code>.</p>
  303. *
  304. * @param range the range to test, may be <code>null</code>
  305. * @return <code>true</code> if the specified range occurs entirely within this range
  306. * @throws IllegalArgumentException if the range is not of this type
  307. */
  308. public boolean containsRange(Range range) {
  309. if (range == null) {
  310. return false;
  311. }
  312. return containsInteger(range.getMinimumInteger()) &&
  313. containsInteger(range.getMaximumInteger());
  314. }
  315. /**
  316. * <p>Tests whether the specified range overlaps with this range
  317. * using <code>int</code> comparison.</p>
  318. *
  319. * <p><code>null</code> is handled and returns <code>false</code>.</p>
  320. *
  321. * @param range the range to test, may be <code>null</code>
  322. * @return <code>true</code> if the specified range overlaps with this range
  323. */
  324. public boolean overlapsRange(Range range) {
  325. if (range == null) {
  326. return false;
  327. }
  328. return range.containsInteger(min) ||
  329. range.containsInteger(max) ||
  330. containsInteger(range.getMinimumInteger());
  331. }
  332. // Basics
  333. //--------------------------------------------------------------------
  334. /**
  335. * <p>Compares this range to another object to test if they are equal.</p>.
  336. *
  337. * <p>To be equal, the class, minimum and maximum must be equal.</p>
  338. *
  339. * @param obj the reference object with which to compare
  340. * @return <code>true</code> if this object is equal
  341. */
  342. public boolean equals(Object obj) {
  343. if (obj == this) {
  344. return true;
  345. }
  346. if (obj instanceof IntRange == false) {
  347. return false;
  348. }
  349. IntRange range = (IntRange) obj;
  350. return (min == range.min && max == range.max);
  351. }
  352. /**
  353. * <p>Gets a hashCode for the range.</p>
  354. *
  355. * @return a hash code value for this object
  356. */
  357. public int hashCode() {
  358. if (hashCode == 0) {
  359. hashCode = 17;
  360. hashCode = 37 * hashCode + getClass().hashCode();
  361. hashCode = 37 * hashCode + min;
  362. hashCode = 37 * hashCode + max;
  363. }
  364. return hashCode;
  365. }
  366. /**
  367. * <p>Gets the range as a <code>String</code>.</p>
  368. *
  369. * <p>The format of the String is 'Range[<i>min</i>,<i>max</i>]'.</p>
  370. *
  371. * @return the <code>String</code> representation of this range
  372. */
  373. public String toString() {
  374. if (toString == null) {
  375. StringBuffer buf = new StringBuffer(32);
  376. buf.append("Range[");
  377. buf.append(min);
  378. buf.append(',');
  379. buf.append(max);
  380. buf.append(']');
  381. toString = buf.toString();
  382. }
  383. return toString;
  384. }
  385. }