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>&lt;</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>&lt;</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>&gt;</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