001 // Copyright (c) 2001 Hursh Jain (http://www.mollypages.org)
002 // The Molly framework is freely distributable under the terms of an
003 // MIT-style license. For details, see the molly pages web site at:
004 // http://www.mollypages.org/. Use, modify, have fun !
005
006 package fc.util;
007
008 import java.util.*;
009
010 /**
011 A range of integral values.
012 <p>
013 Note, many methods in this particular class have the same
014 signatures as in the apache <tt>commons.lang</tt> package but the
015 <tt>implementation</tt> was strictly clean-room.
016 <p>
017 Thread Safety: This class is not thread safe in the face of any
018 concurrent modification (via changing the start/end numbers or
019 union/intersection operations).
020
021 @author hursh jain
022 **/
023 public class NumberRange extends Range
024 {
025 long start;
026 long end;
027
028 /**
029 Constructs a number range between the specified
030 start and end numbers (both inclusive).
031
032 @throws IllegalArgumentException
033 if the end number is lesser (via a <tt><</tt> comparison)
034 than the start number (equal to the start number is ok)
035 **/
036 public NumberRange(long start, long end)
037 {
038 Argcheck.istrue(start <= end, "end number lesser than start number in the specified range, start=["+start+"], end=["+end+"]");
039 this.start = start;
040 this.end = end;
041 }
042
043 /** Get the start number for this number range **/
044 public long getStart()
045 {
046 return start;
047 }
048
049 /**
050 Get the end number for this number range.
051 **/
052 public long getEnd()
053 {
054 return end;
055 }
056
057
058 /** Is the passed in number inside this range **/
059 public boolean inRange(long c)
060 {
061 boolean result = (c >= start) && (c <= end);
062
063 if (negated)
064 return !result;
065 else
066 return result;
067 }
068
069 /**
070 Sets the end number for this number range
071
072 @param c the end number
073 @throws IllegalArgumentException
074 if the end number is lesser (via a <tt><</tt> comparison)
075 than the current start number (equal to the start number is
076 ok)
077 **/
078 public void setEnd(long c)
079 {
080 Argcheck.istrue(start <= c, "end number lesser than start number in the specified range, start=["+start+"], specified end=["+c+"]");
081 end = c;
082 }
083
084 /** Set the start number for this number range
085
086 @throws IllegalArgumentException
087 if the start number is greater (via a <tt>></tt> comparison)
088 than the current end number (equal to the end number is
089 ok)
090 **/
091 public void setStart(long c)
092 {
093 Argcheck.istrue(c <= end, "start number greater than end number in the specified range, end=["+end+"], specified start=["+c+"]");
094 start = c;
095 }
096
097 /** Returns the size of this range which is calculated as the
098 <tt>(endnumber - startnumber) + 1</tt> - i.e., the number of
099 slots in this range, start and end inclusive.
100 **/
101 public long getSize() {
102 return (end - start) + 1;
103 }
104
105
106 /** Output a string representation of the number range **/
107 public java.lang.String toString()
108 {
109 String str = "NumberRange:[";
110 if (isNegated())
111 str += "^";
112
113 if (start >= 0)
114 str += start;
115 else
116 str += "(" + start + ")";
117
118 str += "<->";
119
120 if (end >= 0)
121 str += end ;
122 else
123 str += "(" + end + ")";
124
125 str += "]";
126 return str;
127 }
128
129 public boolean equals(Object obj)
130 {
131 if (! (obj instanceof NumberRange))
132 return false;
133 NumberRange other = (NumberRange) obj;
134 return (this.start == other.start &&
135 this.end == other.end);
136 }
137
138 public int hashCode() {
139 return (int) getSize();
140 }
141
142
143 public static void main(String[] args)
144 {
145 NumberRange r = new NumberRange(-10, 10);
146
147 System.out.println("constructed range:" + r);
148 System.out.println("Range size=" + r.getSize());
149
150 NumberRange r2 = new NumberRange(-10, 10);
151 System.out.println("Constructed range2=" + r2);
152 NumberRange r3 = new NumberRange(-10, 9);
153 System.out.println("Constructed range3=" + r3);
154
155 System.out.println("");
156 System.out.println("r.equals(r2)="+r.equals(r2));
157 System.out.println("r.equals(r3)="+r.equals(r3));
158
159 System.out.println("r.hashCode="+r.hashCode());
160 System.out.println("r2.hashCode="+r2.hashCode());
161 System.out.println("r3.hashCode="+r3.hashCode());
162
163
164 //normal
165 test(r);
166
167 //negate
168 r.setNegated(true);
169 System.out.println("setting the range to be negated:" + r);
170 test(r);
171
172 System.out.println("the following should throw an exception");
173 r = new NumberRange(5, 0);
174 }
175
176 private static void test(NumberRange r)
177 {
178 System.out.println("0 in range:" + r.inRange(0));
179 System.out.println("1 in range:" + r.inRange(1));
180 System.out.println("10 in range:" + r.inRange(10));
181 System.out.println("11 in range:" + r.inRange(11));
182 System.out.println("-1 in range:" + r.inRange(-1));
183 System.out.println("-10 in range:" + r.inRange(-10));
184 System.out.println("-11 in range:" + r.inRange(-11));
185 }
186
187 } //~class NumberRange