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 set of date ranges. **/
012 public class DateRangeSet
013 {
014 DateRange seedRange;
015 List union;
016 List intersect;
017
018 /**
019 Constructs a new DateRangeSet with the initial set containing
020 only the specified DateRange
021
022 @param cs the initial DateRange
023 **/
024 public DateRangeSet(DateRange cs)
025 {
026 Argcheck.notnull(cs);
027 seedRange = cs;
028 //do _not_ lazy instantiate, otherwise have to put in
029 //null checks in other places
030 union = new ArrayList();
031 intersect = new ArrayList();
032 }
033
034 /**
035 Adds this specified range as a union to the existing set of
036 ranges (for purposes of {@link inRange(char)} method).
037 Overlapping ranges are ok.
038
039 @param cs a DateRange to unite with
040 @throws IllegalArgumentException
041 if the specified range was null
042 **/
043 public void union(DateRange r)
044 {
045 Argcheck.notnull(r);
046 union.add(r);
047 }
048
049 /**
050 Adds the specified range as an intersection to the existing
051 ranges (for purposes of {@link inRange(char)} method).
052 Overlapping ranges are ok.
053
054 @param r the range to add
055 **/
056 public void intersection(DateRange r)
057 {
058 Argcheck.notnull(r);
059 intersect.add(r);
060 }
061
062 /**
063 Consider a set of ranges <tt>A</tt>, <tt>B</tt> added as a union
064 (logical <tt>or</tt>) and ranges <tt>C</tt> and <tt>D</tt> added as an
065 intersection (logical <tt>and</tt>). A character <tt>c</tt> is in range if
066 it exists in:
067
068 <blockquote> <tt>
069
070 (A.inRange(c) || B.inRange(c) || ...) && C.inRange(c) && D.inRange(c)
071 && ...
072
073 </tt></blockquote>
074
075 This can be generalized to an arbitrary number of sub ranges. If
076 intersection or union ranges don't exist, then they are not
077 considered in the above expression. Note, the interaction may be
078 subtle if any of the ranges (<tt>A, B, C...</tt>etc) are
079 individually negated because in that case the inRange method for
080 that negated range would return true if the specified character
081 was <b>not</b> in that range.
082
083 @return <tt>true</tt> if the passed in character is allowed by this
084 set of ranges.
085
086 **/
087 public boolean inRange(Date val)
088 {
089 boolean result = seedRange.inRange(val);
090 for (int i = 0, n = union.size(); i < n; i++) {
091 DateRange item = (DateRange) union.get(i);
092 result = result || item.inRange(val);
093 }
094 for (int i = 0, n = intersect.size(); i < n; i++) {
095 DateRange item = (DateRange) intersect.get(i);
096 result = result && item.inRange(val);
097 }
098 return result;
099 }
100
101 public String toString() {
102 StringBuffer buf = new StringBuffer(128);
103 buf.append("DateRangeSet:[");
104
105 if (intersect.size() > 0)
106 buf.append("(");
107
108 buf.append(seedRange);
109
110 int len = union.size();
111 if (len > 0)
112 {
113 buf.append(" || " );
114 for (int i = 0; i < len; i++) {
115 buf.append(union.get(i).toString());
116 if (i < (len-1))
117 buf.append(" || ");
118 }
119 }
120
121 len = intersect.size();
122 if (len > 0)
123 {
124 buf.append(") && " );
125 for (int i = 0; i < len; i++) {
126 buf.append(intersect.get(i).toString());
127 if (i < (len-1))
128 buf.append(" && ");
129 }
130 }
131
132 buf.append("]");
133 return buf.toString();
134 }
135
136
137 public static void main(String[] args)
138 {
139 Date now = new Date();
140
141 Calendar cal = Calendar.getInstance();
142 Date d1 = cal.getTime();
143 //back 1 month
144 cal.add(Calendar.MONTH, -1);
145 Date d2 = cal.getTime();
146
147 DateRange r = new DateRange(d2, d1);
148
149 cal.setTime(now);
150 cal.add(Calendar.MONTH, -3);
151 Date d3 = cal.getTime();
152 cal.setTime(now);
153 cal.add(Calendar.MONTH, -6);
154 Date d4 = cal.getTime();
155
156 DateRange r2 = new DateRange(d4, d3);
157
158 DateRangeSet crs = new DateRangeSet(r);
159 crs.union(r2);
160 System.out.println("constructed: " + crs);
161 test(crs);
162
163 cal.setTime(now);
164 cal.add(Calendar.MONTH, -4);
165 d3 = cal.getTime();
166 cal.setTime(now);
167 cal.add(Calendar.MONTH, -5);
168 d4 = cal.getTime();
169 r2 = new DateRange(d4, d3);
170 crs.intersection(r2);
171 System.out.println("constructed: " + crs);
172 test(crs);
173 }
174
175 private static void test(DateRangeSet crs)
176 {
177 Calendar cal = Calendar.getInstance();
178 cal.add(Calendar.MONTH, -5);
179 Date d = cal.getTime();
180 System.out.println("in range: " + d + "=" + crs.inRange(d));
181 cal.setTime(new Date());
182 cal.add(Calendar.MONTH, 3);
183 d = cal.getTime();
184 System.out.println("in range: " + d + "=" + crs.inRange(d));
185 }
186 }