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