001 /*
002 * Copyleft notice: This is public-domain software and documentation
003 * with no restrictions of any kind.
004 * Please feel free to use any of it in any way you want.
005 * This work is distributed in the hope that it will be useful,
006 * but WITHOUT ANY WARRANTY; without even the implied warranty of
007 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
008 */
009
010
011 package time;
012
013 import java.util.*;
014
015 /**
016 * A TimeMask is a sorted set of <tt>TimeField</tt> which is used to defined <tt>Time</tt>.
017 * It defines a format which will be used to manipulate <tt>Time</tt>.
018 *
019 *
020 *
021 * @author Arnaud Roques
022 *
023 *
024 * @has - "has" n time.TimeField<V>
025 * @stereotype "SortedSet"
026 *
027 */
028 public final class TimeMask implements SortedSet<TimeField>
029 {
030 private final SortedSet<TimeField> fields;
031
032 /**
033 * Create a new TimeMask from several TimeField.
034 *
035 * The <tt>TimeFields</tt> will be sorted. It is recommanded that
036 * all <tt>TimeField</tt> belongs to the same chronology, although this
037 * is not mandatory.
038 *
039 * A <tt>TimeMask</tt> that mixes several <tt>TimeField</tt> from different
040 * chronologies is likely to be useless.
041 *
042 * @param f all TimeField used by the TimeMask.
043 *
044 * @throws NullPointerException if one or more of the TimeField is <tt>null</tt>.
045 */
046 public TimeMask(TimeField... f)
047 {
048 this(Arrays.asList(f));
049 }
050
051 /**
052 * Create a new TimeMask from several TimeField.
053 *
054 * The <tt>TimeFields</tt> will be sorted. It is recommanded that
055 * all <tt>TimeField</tt> belongs to the same chronology, although this
056 * is not mandatory.
057 *
058 * A <tt>TimeMask</tt> that mixes several <tt>TimeField</tt> from different
059 * chronologies is likely to be useless.
060 *
061 * @param s all TimeField used by the TimeMask.
062 *
063 * @throws NullPointerException if one or more of the TimeField is <tt>null</tt>.
064 */
065 public TimeMask(Collection<TimeField> s)
066 {
067 for (TimeField f : s)
068 if (f==null) throw new NullPointerException();
069
070 fields = Collections.unmodifiableSortedSet(new TreeSet<TimeField>(s));
071 }
072
073
074
075 /**
076 * Create a new TimeMask from several other TimeMask.
077 *
078 * All <tt>TimeField</tt> from every <tt>TimeMask</tt> are collected in
079 * the new <tt>TimeMask</tt>.
080 *
081 * @param masks all TimeMask that will be merged in the new TimeMask.
082 *
083 * @throws NullPointerException if one or more of the TimeMask is <tt>null</tt>.
084 */
085 public TimeMask(TimeMask... masks)
086 {
087 SortedSet<TimeField> s = new TreeSet<TimeField>();
088 for (TimeMask m : masks)
089 s.addAll(m.fields);
090 fields = Collections.unmodifiableSortedSet(s);
091 }
092
093 /**
094 * Create a new TimeMask by adding TimeField to an existing TimeMask.
095 *
096 * @param mask the original TimeMask
097 * @param f all TimeField to add in the new TimeMask
098 *
099 * @throws NullPointerException if <tt>mask</tt> is <tt>null</tt>.
100 * @throws NullPointerException if one or more of the TimeField is <tt>null</tt>.
101 */
102 public TimeMask(TimeMask mask, TimeField... f)
103 {
104 this(mask, new TimeMask(f));
105 }
106
107
108 /**
109 * Return all TimeField contained in this TimeMask.
110 *
111 * @return all TimeField contained in this TimeMask.
112 */
113 public SortedSet<TimeField> getFields()
114 {
115 return fields;
116 }
117
118
119 /**
120 * Return the number of TimeFields in the TimeMask.
121 *
122 * @return number of TimeFields in the TimeMask.
123 */
124 public int size()
125 {
126 return fields.size();
127 }
128
129
130 /**
131 * Compares this TimeMask to the specified object.
132 * The result is <tt>true</tt> if and only if the argument is not <tt>null</tt>
133 * and is a TimeMask that have the same sequence of TimeField as this object.
134 *
135 * @param anObject - the object to compare this TimeMask against.
136 * @hidden
137 */
138 @Override
139 public boolean equals(Object anObject)
140 {
141 if (!(anObject instanceof TimeMask)) return false;
142 TimeMask other = (TimeMask) anObject;
143 return fields.equals(other.fields);
144 }
145
146 /**
147 * Returns a hash code value for this object.
148 * @hidden
149 */
150 @Override
151 public int hashCode()
152 {
153 return fields.hashCode();
154 }
155
156 /**
157 * Convert this TimeMask to a String.
158 *
159 * @return a String describing this TimeMask
160 * @hidden
161 */
162 @Override
163 public String toString()
164 {
165 return super.toString()+" "+fields;
166 }
167
168
169
170 /**
171 * Return the <i>less significant</i> TimeField of this TimeMask.
172 *
173 * @return the <i>less significant</i> TimeField of this TimeMask.
174 * @hidden
175 */
176 public TimeField last()
177 {
178 return fields.last();
179 }
180
181 /**
182 * Return the <i>most significant</i> TimeField of this TimeMask.
183 *
184 * @return the <i>most significant</i> TimeField of this TimeMask.
185 * @hidden
186 */
187 public TimeField first()
188 {
189 return fields.first();
190 }
191
192 /**
193 * Build a new TimeMask with TimeField of this TimeMask which are <i>less
194 * significant</i> (inclusive) than a TimeField.
195 *
196 * @param fromField TimeField to compare with.
197 *
198 * @return new TimeMask with some of the <i>less significant</i> TimeField of this TimeMask.
199 *
200 * @throws NullPointerException if <tt>fromField</tt> is <tt>null</tt>.
201 * @throws IllegalArgumentException if <tt>fromField</tt> is not in the range of this TimeMask.
202 * @hidden
203 */
204 public TimeMask tailSet(TimeField fromField)
205 {
206 return new TimeMask(fields.tailSet(fromField));
207 }
208
209
210 /**
211 * Build a new TimeMask with TimeField of this TimeMask which are <i>more
212 * significant</i> (exclusive) than a TimeField.
213 *
214 * @param toField TimeField to compare with.
215 *
216 * @return new TimeMask with some of the <i>more significant</i> TimeField of this TimeMask.
217 *
218 * @throws NullPointerException if <tt>toField</tt> is <tt>null</tt>.
219 * @throws IllegalArgumentException if <tt>toField</tt> is not in the range of this TimeMask.
220 * @hidden
221 */
222 public TimeMask headSet(TimeField toField)
223 {
224 return new TimeMask(fields.headSet(toField));
225 }
226
227
228 /**
229 * Build a new TimeMask with some TimeField of this TimeMask.
230 *
231 * Only TimeField that are:
232 * <ul>
233 * <li><i>less significant</i> than <tt>fromField</tt> (inclusive)
234 * <li><i>more significant</i> than <tt>toField</tt> (exclusive)
235 * </ul>
236 *
237 * will be in the returned TimeMask.
238 *
239 *
240 * @param fromField lower limit of the TimeField.
241 * @param toField uppder limit TimeField.
242 *
243 * @return new TimeMask with some of the TimeField of this TimeMask.
244 *
245 * @throws NullPointerException if <tt>fromField</tt> or <tt>toField</tt> is <tt>null</tt>.
246 * @throws IllegalArgumentException if <tt>fromField</tt> or <tt>toField</tt> is not in the range of this TimeMask.
247 * @throws IllegalArgumentException if <tt>fromField</tt> is greater than <tt>toField</tt>.
248 * @hidden
249 */
250 public TimeMask subSet(TimeField fromField, TimeField toField)
251 {
252 return new TimeMask(fields.subSet(fromField, toField));
253 }
254
255
256 /**
257 * Return <tt>null</tt>, as natural order of TimeField are used in TimeMask.
258 *
259 * @return <tt>null</tt>
260 * @hidden
261 */
262 public Comparator<? super TimeField> comparator()
263 {
264 return null;
265 }
266
267 /**
268 * As <tt>TimeMask</tt> are immutable, throws a <tt>UnsupportedOperationException</tt>.
269 * @hidden
270 */
271 public void clear()
272 {
273 throw new UnsupportedOperationException();
274 }
275
276 /**
277 * As <tt>TimeMask</tt> are immutable, throws a <tt>UnsupportedOperationException</tt>.
278 * @hidden
279 */
280 public boolean removeAll(Collection<?> c)
281 {
282 throw new UnsupportedOperationException();
283 }
284
285 /**
286 * As <tt>TimeMask</tt> are immutable, throws a <tt>UnsupportedOperationException</tt>.
287 * @hidden
288 */
289 public boolean retainAll(Collection<?> c)
290 {
291 throw new UnsupportedOperationException();
292 }
293
294 /**
295 * As <tt>TimeMask</tt> are immutable, throws a <tt>UnsupportedOperationException</tt>.
296 * @hidden
297 */
298 public boolean addAll(Collection<? extends TimeField> c)
299 {
300 throw new UnsupportedOperationException();
301 }
302
303
304 /**
305 * As <tt>TimeMask</tt> are immutable, throws a <tt>UnsupportedOperationException</tt>.
306 *
307 * @see #remove(TimeField... f)
308 * @hidden
309 */
310 public boolean remove(Object o)
311 {
312 throw new UnsupportedOperationException();
313 }
314
315 /**
316 * Build a new TimeMask by removing some TimeField of this TimeMask.
317 *
318 * @param f all TimeField to remove from this TimeField.
319 *
320 * @return a new TimeMask that contains less TimeField than this TimeMask.
321 *
322 * @throws IllegalArgumentException if one or more of the TimeField are not contained
323 * in the TimeMask.
324 */
325 public TimeMask remove(TimeField... f)
326 {
327 TreeSet<TimeField> ts = new TreeSet<TimeField>(fields);
328 Collection<TimeField> toRemove = Arrays.asList(f);
329
330 if (getFields().containsAll(toRemove)==false)
331 throw new IllegalArgumentException();
332
333 ts.removeAll(toRemove);
334 return new TimeMask(ts);
335 }
336
337
338
339 /**
340 * As <tt>TimeMask</tt> are immutable, throws a <tt>UnsupportedOperationException</tt>.
341 *
342 * @see #TimeMask(TimeMask mask, TimeField... f)
343 * @hidden
344 */
345 public boolean add(TimeField o)
346 {
347 throw new UnsupportedOperationException();
348 }
349
350 /**
351 * Returns <tt>true</tt> if this TimeMask contains all of the elements
352 * in the specified collection.
353 *
354 * @param c collection to be checked for containment in this TimeMask.
355 *
356 * @return <tt>true</tt> if this TimeMask contains all of the elements
357 * in the specified collection.
358 * @hidden
359 */
360 public boolean containsAll(Collection<?> c)
361 {
362 return fields.containsAll(c);
363 }
364
365 /**
366 * Returns <tt>true</tt> if this TimeMask contains the specified element.
367 *
368 * @param obj object to be checked for containment in this TimeMask.
369 * @hidden
370 */
371 public boolean contains(Object obj)
372 {
373 return fields.contains(obj);
374 }
375
376 /**
377 *
378 * @hidden
379 */
380 public <T> T[] toArray(T[] a)
381 {
382 return fields.toArray(a);
383 }
384
385 /**
386 *
387 * @hidden
388 */
389 public Object[] toArray()
390 {
391 return fields.toArray();
392 }
393
394
395 /**
396 * Return an iterator over TimeField contained in this TimeMask.
397 * @hidden
398 */
399 public Iterator<TimeField> iterator()
400 {
401 return fields.iterator();
402 }
403
404 /**
405 * Return <tt>true</tt> is this TimeMask contains no TimeField.
406 *
407 * @return <tt>true</tt> is this TimeMask contains no TimeField.
408 * @hidden
409 */
410 public boolean isEmpty()
411 {
412 return fields.isEmpty();
413 }
414
415
416
417
418 }
419