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
006package fc.util;
007
008import java.util.*;
009
010/** 
011A range of integral values.
012<p>
013Note, many methods in this particular class have the same
014signatures as in the apache <tt>commons.lang</tt> package but the
015<tt>implementation</tt> was strictly clean-room.
016<p>
017Thread Safety: This class is not thread safe in the face of any
018concurrent modification (via changing the start/end numbers or
019union/intersection operations).
020
021@author hursh jain
022**/
023public class NumberRange extends Range
024{
025long start;
026long end;
027
028/** 
029Constructs a number range between the specified
030start and end numbers (both inclusive). 
031
032@throws IllegalArgumentException 
033      if the end number is lesser (via a <tt>&lt;</tt> comparison) 
034      than the start number (equal to the start number is ok)
035**/
036public 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 **/
044public long getStart() 
045  {
046  return start;
047  }
048
049/** 
050Get the end number for this number range. 
051**/
052public long getEnd() 
053  {
054  return end;
055  }
056
057
058/** Is the passed in number inside this range **/
059public 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/** 
070Sets 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>&lt;</tt> comparison) 
075      than the current start number (equal to the start number is 
076      ok)
077**/
078public 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>&gt;</tt> comparison) 
088      than the current end number (equal to the end number is 
089      ok)
090**/
091public 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
099slots in this range, start and end inclusive.
100**/
101public long getSize() {
102  return (end - start) + 1;
103  }
104  
105  
106/** Output a string representation of the number range **/
107public 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  
129public 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
138public int hashCode() {
139  return (int) getSize();
140  }
141
142
143public 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
176private 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