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;
018    
019    /**
020     * <p>Represents a range of {@link Number} objects.</p>
021     * 
022     * <p>This class uses <code>double</code> comparisons. This means that it
023     * is unsuitable for dealing with large <code>Long</code>, <code>BigDecimal</code>
024     * or <code>BigInteger</code> numbers.</p>
025     *
026     * @author Apache Software Foundation
027     * @author <a href="mailto:chrise@esha.com">Christopher Elkins</a>
028     * @since 1.0
029     * @version $Revision: 905636 $ $Date: 2010-02-02 14:03:32 +0000 (Tue, 02 Feb 2010) $
030     * 
031     * @deprecated Use one of the Range classes in org.apache.commons.lang.math.
032     *             Class will be removed in Commons Lang 3.0.
033     * 
034     */
035    public final class NumberRange {
036    
037        /* The minimum number in this range. */
038        private final Number min;
039    
040        /* The maximum number in this range. */
041        private final Number max;
042    
043    
044        /**
045         * <p>Constructs a new <code>NumberRange</code> using
046         * <code>number</code> as both the minimum and maximum in
047         * this range.</p>
048         *
049         * @param num the number to use for this range
050         * @throws NullPointerException if the number is <code>null</code>
051         */
052        public NumberRange(Number num) {
053            if (num == null) {
054                throw new NullPointerException("The number must not be null");
055            }
056    
057            this.min = num;
058            this.max = num;
059        }
060    
061        /**
062         * <p>Constructs a new <code>NumberRange</code> with the specified
063         * minimum and maximum numbers.</p>
064         * 
065         * <p><em>If the maximum is less than the minimum, the range will be constructed
066         * from the minimum value to the minimum value, not what you would expect!.</em></p>
067         *
068         * @param min the minimum number in this range
069         * @param max the maximum number in this range
070         * @throws NullPointerException if either the minimum or maximum number is
071         *  <code>null</code>
072         */
073        public NumberRange(Number min, Number max) {
074            if (min == null) {
075                throw new NullPointerException("The minimum value must not be null");
076            } else if (max == null) {
077                throw new NullPointerException("The maximum value must not be null");
078            }
079    
080            if (max.doubleValue() < min.doubleValue()) {
081                this.min = this.max = min;
082            } else {
083                this.min = min;
084                this.max = max;
085            }
086        }
087    
088        /**
089         * <p>Returns the minimum number in this range.</p>
090         *
091         * @return the minimum number in this range
092         */
093        public Number getMinimum() {
094            return min;
095        }
096    
097        /**
098         * <p>Returns the maximum number in this range.</p>
099         *
100         * @return the maximum number in this range
101         */
102        public Number getMaximum() {
103            return max;
104        }
105    
106        /**
107         * <p>Tests whether the specified <code>number</code> occurs within
108         * this range using <code>double</code> comparison.</p>
109         *
110         * @param number the number to test
111         * @return <code>true</code> if the specified number occurs within this
112         *  range; otherwise, <code>false</code>
113         */
114        public boolean includesNumber(Number number) {
115            if (number == null) {
116                return false;
117            } else {
118                return !(min.doubleValue() > number.doubleValue()) &&
119                    !(max.doubleValue() < number.doubleValue());
120            }
121        }
122    
123        /**
124         * <p>Tests whether the specified range occurs entirely within this
125         * range using <code>double</code> comparison.</p>
126         *
127         * @param range the range to test
128         * @return <code>true</code> if the specified range occurs entirely within
129         *  this range; otherwise, <code>false</code>
130         */
131        public boolean includesRange(NumberRange range) {
132            if (range == null) {
133                return false;
134            } else {
135                return includesNumber(range.min) && includesNumber(range.max);
136            }
137        }
138    
139        /**
140         * <p>Tests whether the specified range overlaps with this range
141         * using <code>double</code> comparison.</p>
142         *
143         * @param range the range to test
144         * @return <code>true</code> if the specified range overlaps with this
145         *  range; otherwise, <code>false</code>
146         */
147        public boolean overlaps(NumberRange range) {
148            if (range == null) {
149                return false;
150            } else {
151                return range.includesNumber(min) || range.includesNumber(max) || 
152                    includesRange(range);
153            }
154        }
155    
156        /**
157         * <p>Indicates whether some other <code>Object</code> is
158         * &quot;equal&quot; to this one.</p>
159         *
160         * @param obj the reference object with which to compare
161         * @return <code>true</code> if this object is the same as the obj
162         *  argument; <code>false</code> otherwise
163         */
164        public boolean equals(Object obj) {
165            if (obj == this) {
166                return true;
167            } else if (!(obj instanceof NumberRange)) {
168                return false;
169            } else {
170                NumberRange range = (NumberRange)obj;
171                return min.equals(range.min) && max.equals(range.max);
172            }
173        }
174    
175        /**
176         * <p>Returns a hash code value for this object.</p>
177         *
178         * @return a hash code value for this object
179         */
180        public int hashCode() {
181            int result = 17;
182            result = 37 * result + min.hashCode();
183            result = 37 * result + max.hashCode();
184            return result;
185        }
186    
187        /**
188         * <p>Returns the string representation of this range.</p>
189         *
190         * <p>This string is the string representation of the minimum and
191         * maximum numbers in the range, separated by a hyphen. If a number
192         * is negative, then it is enclosed in parentheses.</p>
193         *
194         * @return the string representation of this range
195         */
196        public String toString() {
197            StringBuffer sb = new StringBuffer();
198    
199            if (min.doubleValue() < 0) {
200                sb.append('(')
201                    .append(min)
202                    .append(')');
203            } else {
204                sb.append(min);
205            }
206    
207            sb.append('-');
208    
209            if (max.doubleValue() < 0) {
210                sb.append('(')
211                    .append(max)
212                    .append(')');
213            } else {
214                sb.append(max);
215            }
216    
217            return sb.toString();
218        }
219    
220    }