|
1 /** |
|
2 * Copyright (c) 2012, Ben Fortuna |
|
3 * All rights reserved. |
|
4 * |
|
5 * Redistribution and use in source and binary forms, with or without |
|
6 * modification, are permitted provided that the following conditions |
|
7 * are met: |
|
8 * |
|
9 * o Redistributions of source code must retain the above copyright |
|
10 * notice, this list of conditions and the following disclaimer. |
|
11 * |
|
12 * o Redistributions in binary form must reproduce the above copyright |
|
13 * notice, this list of conditions and the following disclaimer in the |
|
14 * documentation and/or other materials provided with the distribution. |
|
15 * |
|
16 * o Neither the name of Ben Fortuna nor the names of any other contributors |
|
17 * may be used to endorse or promote products derived from this software |
|
18 * without specific prior written permission. |
|
19 * |
|
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
|
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
|
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
|
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
|
27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
|
28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
|
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
|
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
31 */ |
|
32 package net.fortuna.ical4j.model; |
|
33 |
|
34 import java.io.Serializable; |
|
35 import java.text.ParseException; |
|
36 import java.util.ArrayList; |
|
37 import java.util.Collection; |
|
38 import java.util.Collections; |
|
39 import java.util.Iterator; |
|
40 import java.util.List; |
|
41 import java.util.ListIterator; |
|
42 import java.util.StringTokenizer; |
|
43 |
|
44 import net.fortuna.ical4j.model.parameter.Value; |
|
45 |
|
46 import org.apache.commons.lang.builder.EqualsBuilder; |
|
47 import org.apache.commons.lang.builder.HashCodeBuilder; |
|
48 |
|
49 /** |
|
50 * $Id$ [23-Apr-2004] |
|
51 * |
|
52 * Defines a list of iCalendar dates. If no value type is specified a list |
|
53 * defaults to DATE-TIME instances. |
|
54 * @author Ben Fortuna |
|
55 */ |
|
56 public class DateList implements List, Serializable { |
|
57 |
|
58 private static final long serialVersionUID = -3700862452550012357L; |
|
59 |
|
60 private final Value type; |
|
61 |
|
62 private final List dates; |
|
63 |
|
64 private TimeZone timeZone; |
|
65 |
|
66 private boolean utc; |
|
67 |
|
68 /** |
|
69 * Default constructor. |
|
70 */ |
|
71 public DateList() { |
|
72 this(false); |
|
73 } |
|
74 |
|
75 public DateList(final boolean unmodifiable) { |
|
76 |
|
77 this.type = Value.DATE_TIME; |
|
78 if (unmodifiable) { |
|
79 dates = Collections.EMPTY_LIST; |
|
80 } |
|
81 else { |
|
82 dates = new ArrayList(); |
|
83 } |
|
84 } |
|
85 |
|
86 /** |
|
87 * @param aType the type of dates contained by the instance |
|
88 */ |
|
89 public DateList(final Value aType) { |
|
90 this(aType, null); |
|
91 } |
|
92 |
|
93 /** |
|
94 * Default constructor. |
|
95 * |
|
96 * @param aType |
|
97 * specifies the type of dates (either date or date-time) |
|
98 * @param timezone the timezone to apply to dates contained by the instance |
|
99 */ |
|
100 public DateList(final Value aType, final TimeZone timezone) { |
|
101 if (aType == null) { |
|
102 this.type = Value.DATE_TIME; |
|
103 } else { |
|
104 this.type = aType; |
|
105 } |
|
106 this.timeZone = timezone; |
|
107 dates = new ArrayList(); |
|
108 } |
|
109 |
|
110 /** |
|
111 * @param aValue a string representation of a date list |
|
112 * @param aType the date types contained in the instance |
|
113 * @throws ParseException where the specified string is not a valid date list |
|
114 */ |
|
115 public DateList(final String aValue, final Value aType) throws ParseException { |
|
116 this(aValue, aType, null); |
|
117 } |
|
118 |
|
119 /** |
|
120 * Parses the specified string representation to create a list of dates. |
|
121 * |
|
122 * @param aValue |
|
123 * a string representation of a list of dates |
|
124 * @param aType |
|
125 * specifies the type of dates (either date or date-time) |
|
126 * @param timezone the timezone to apply to contained dates |
|
127 * @throws ParseException |
|
128 * if an invalid date representation exists in the date list |
|
129 * string |
|
130 */ |
|
131 public DateList(final String aValue, final Value aType, final TimeZone timezone) |
|
132 throws ParseException { |
|
133 |
|
134 this(aType, timezone); |
|
135 final StringTokenizer t = new StringTokenizer(aValue, ","); |
|
136 while (t.hasMoreTokens()) { |
|
137 if (Value.DATE.equals(type)) { |
|
138 add((Object) new Date(t.nextToken())); |
|
139 } |
|
140 else { |
|
141 add((Object) new DateTime(t.nextToken(), timezone)); |
|
142 } |
|
143 } |
|
144 } |
|
145 |
|
146 /** |
|
147 * Constructs a new date list of the specified type containing |
|
148 * the dates in the specified list. |
|
149 * @param list a list of dates to include in the new list |
|
150 * @param type the type of the new list |
|
151 */ |
|
152 public DateList(final DateList list, final Value type) { |
|
153 if (!Value.DATE.equals(type) && !Value.DATE_TIME.equals(type)) { |
|
154 throw new IllegalArgumentException( |
|
155 "Type must be either DATE or DATE-TIME"); |
|
156 } |
|
157 |
|
158 this.type = type; |
|
159 dates = new ArrayList(); |
|
160 |
|
161 if (Value.DATE.equals(type)) { |
|
162 for (final Iterator i = list.iterator(); i.hasNext();) { |
|
163 add(new Date((Date) i.next())); |
|
164 } |
|
165 } |
|
166 else { |
|
167 for (final Iterator i = list.iterator(); i.hasNext();) { |
|
168 add(new DateTime((Date) i.next())); |
|
169 } |
|
170 } |
|
171 } |
|
172 |
|
173 /** |
|
174 * {@inheritDoc} |
|
175 */ |
|
176 public final String toString() { |
|
177 final StringBuffer b = new StringBuffer(); |
|
178 for (final Iterator i = iterator(); i.hasNext();) { |
|
179 /* |
|
180 * if (type != null && Value.DATE.equals(type)) { |
|
181 * b.append(DateFormat.getInstance().format((Date) i.next())); } |
|
182 * else { b.append(DateTimeFormat.getInstance().format((Date) |
|
183 * i.next(), isUtc())); } |
|
184 */ |
|
185 b.append(i.next()); |
|
186 if (i.hasNext()) { |
|
187 b.append(','); |
|
188 } |
|
189 } |
|
190 return b.toString(); |
|
191 } |
|
192 |
|
193 /** |
|
194 * Add a date to the list. The date will be updated to reflect the |
|
195 * timezone of this list. |
|
196 * @param date the date to add |
|
197 * @return true |
|
198 * @see List#add(java.lang.Object) |
|
199 */ |
|
200 public final boolean add(final Date date) { |
|
201 if (date instanceof DateTime) { |
|
202 if (isUtc()) { |
|
203 ((DateTime) date).setUtc(true); |
|
204 } |
|
205 else { |
|
206 ((DateTime) date).setTimeZone(getTimeZone()); |
|
207 } |
|
208 } |
|
209 else if (!Value.DATE.equals(getType())) { |
|
210 final DateTime dateTime = new DateTime(date); |
|
211 dateTime.setTimeZone(getTimeZone()); |
|
212 return add((Object) dateTime); |
|
213 } |
|
214 return add((Object) date); |
|
215 } |
|
216 |
|
217 /** |
|
218 * Overrides superclass to throw an <code>IllegalArgumentException</code> |
|
219 * Where argument is not a <code>net.fortuna.ical4j.model.Date</code>. |
|
220 * @param date the date to add |
|
221 * @return true if the object was added, otherwise false |
|
222 * @see List#add(E) |
|
223 */ |
|
224 public final boolean add(final Object date) { |
|
225 if (!(date instanceof Date)) { |
|
226 throw new IllegalArgumentException("Argument not a " + Date.class.getName()); |
|
227 } |
|
228 return dates.add(date); |
|
229 } |
|
230 |
|
231 /** |
|
232 * Remove a date from the list. |
|
233 * |
|
234 * @param date |
|
235 * the date to remove |
|
236 * @return true if the list contained the specified date |
|
237 * @see List#remove(java.lang.Object) |
|
238 */ |
|
239 public final boolean remove(final Date date) { |
|
240 return remove((Object) date); |
|
241 } |
|
242 |
|
243 /** |
|
244 * Returns the VALUE parameter specifying the type of dates (ie. date or |
|
245 * date-time) stored in this date list. |
|
246 * |
|
247 * @return Returns a Value parameter. |
|
248 */ |
|
249 public final Value getType() { |
|
250 return type; |
|
251 } |
|
252 |
|
253 /** |
|
254 * Indicates whether this list is in local or UTC format. This property will |
|
255 * have no affect if the type of the list is not DATE-TIME. |
|
256 * |
|
257 * @return Returns true if in UTC format, otherwise false. |
|
258 */ |
|
259 public final boolean isUtc() { |
|
260 return utc; |
|
261 } |
|
262 |
|
263 /** |
|
264 * Sets whether this list is in UTC or local time format. |
|
265 * |
|
266 * @param utc |
|
267 * The utc to set. |
|
268 */ |
|
269 public final void setUtc(final boolean utc) { |
|
270 if (!Value.DATE.equals(type)) { |
|
271 for (final Iterator i = iterator(); i.hasNext();) { |
|
272 ((DateTime) i.next()).setUtc(utc); |
|
273 } |
|
274 } |
|
275 this.timeZone = null; |
|
276 this.utc = utc; |
|
277 } |
|
278 |
|
279 /** |
|
280 * Applies the specified timezone to all dates in the list. |
|
281 * All dates added to this list will also have this timezone |
|
282 * applied. |
|
283 * @param timeZone a timezone to apply to contained dates |
|
284 */ |
|
285 public final void setTimeZone(final TimeZone timeZone) { |
|
286 if (!Value.DATE.equals(type)) { |
|
287 for (final Iterator i = iterator(); i.hasNext();) { |
|
288 ((DateTime) i.next()).setTimeZone(timeZone); |
|
289 } |
|
290 } |
|
291 this.timeZone = timeZone; |
|
292 this.utc = false; |
|
293 } |
|
294 |
|
295 /** |
|
296 * @return Returns the timeZone. |
|
297 */ |
|
298 public final TimeZone getTimeZone() { |
|
299 return timeZone; |
|
300 } |
|
301 |
|
302 public final void add(int arg0, Object arg1) { |
|
303 dates.add(arg0, arg1); |
|
304 } |
|
305 |
|
306 public final boolean addAll(Collection arg0) { |
|
307 return dates.addAll(arg0); |
|
308 } |
|
309 |
|
310 public final boolean addAll(int arg0, Collection arg1) { |
|
311 return dates.addAll(arg0, arg1); |
|
312 } |
|
313 |
|
314 public final void clear() { |
|
315 dates.clear(); |
|
316 } |
|
317 |
|
318 public final boolean contains(Object o) { |
|
319 return dates.contains(o); |
|
320 } |
|
321 |
|
322 public final boolean containsAll(Collection arg0) { |
|
323 return dates.containsAll(arg0); |
|
324 } |
|
325 |
|
326 public final Object get(int index) { |
|
327 return dates.get(index); |
|
328 } |
|
329 |
|
330 public final int indexOf(Object o) { |
|
331 return dates.indexOf(o); |
|
332 } |
|
333 |
|
334 public final boolean isEmpty() { |
|
335 return dates.isEmpty(); |
|
336 } |
|
337 |
|
338 public final Iterator iterator() { |
|
339 return dates.iterator(); |
|
340 } |
|
341 |
|
342 public final int lastIndexOf(Object o) { |
|
343 return dates.lastIndexOf(o); |
|
344 } |
|
345 |
|
346 public final ListIterator listIterator() { |
|
347 return dates.listIterator(); |
|
348 } |
|
349 |
|
350 public final ListIterator listIterator(int index) { |
|
351 return dates.listIterator(index); |
|
352 } |
|
353 |
|
354 public final Object remove(int index) { |
|
355 return dates.remove(index); |
|
356 } |
|
357 |
|
358 public final boolean remove(Object o) { |
|
359 return dates.remove(o); |
|
360 } |
|
361 |
|
362 public final boolean removeAll(Collection arg0) { |
|
363 return dates.removeAll(arg0); |
|
364 } |
|
365 |
|
366 public final boolean retainAll(Collection arg0) { |
|
367 return dates.retainAll(arg0); |
|
368 } |
|
369 |
|
370 public final Object set(int arg0, Object arg1) { |
|
371 return dates.set(arg0, arg1); |
|
372 } |
|
373 |
|
374 public final int size() { |
|
375 return dates.size(); |
|
376 } |
|
377 |
|
378 public final List subList(int fromIndex, int toIndex) { |
|
379 return dates.subList(fromIndex, toIndex); |
|
380 } |
|
381 |
|
382 public final Object[] toArray() { |
|
383 return dates.toArray(); |
|
384 } |
|
385 |
|
386 public final Object[] toArray(Object[] arg0) { |
|
387 return dates.toArray(arg0); |
|
388 } |
|
389 |
|
390 public final boolean equals(Object obj) { |
|
391 if (!getClass().isAssignableFrom(obj.getClass())) { |
|
392 return false; |
|
393 } |
|
394 final DateList rhs = (DateList) obj; |
|
395 return new EqualsBuilder().append(dates, rhs.dates) |
|
396 .append(type, rhs.type) |
|
397 .append(timeZone, rhs.timeZone) |
|
398 .append(utc, utc) |
|
399 .isEquals(); |
|
400 } |
|
401 |
|
402 public final int hashCode() { |
|
403 return new HashCodeBuilder().append(dates) |
|
404 .append(type) |
|
405 .append(timeZone) |
|
406 .append(utc) |
|
407 .toHashCode(); |
|
408 } |
|
409 } |