001package biweekly.component;
002
003import static biweekly.property.ValuedProperty.getValue;
004
005import java.util.Date;
006import java.util.List;
007
008import biweekly.ICalVersion;
009import biweekly.Warning;
010import biweekly.property.Attachment;
011import biweekly.property.Attendee;
012import biweekly.property.Categories;
013import biweekly.property.Classification;
014import biweekly.property.Comment;
015import biweekly.property.Completed;
016import biweekly.property.Contact;
017import biweekly.property.Created;
018import biweekly.property.DateDue;
019import biweekly.property.DateStart;
020import biweekly.property.DateTimeStamp;
021import biweekly.property.Description;
022import biweekly.property.DurationProperty;
023import biweekly.property.ExceptionDates;
024import biweekly.property.ExceptionRule;
025import biweekly.property.Geo;
026import biweekly.property.LastModified;
027import biweekly.property.Location;
028import biweekly.property.Method;
029import biweekly.property.Organizer;
030import biweekly.property.PercentComplete;
031import biweekly.property.Priority;
032import biweekly.property.RecurrenceDates;
033import biweekly.property.RecurrenceId;
034import biweekly.property.RecurrenceRule;
035import biweekly.property.RelatedTo;
036import biweekly.property.RequestStatus;
037import biweekly.property.Resources;
038import biweekly.property.Sequence;
039import biweekly.property.Status;
040import biweekly.property.Summary;
041import biweekly.property.Uid;
042import biweekly.property.Url;
043import biweekly.util.Duration;
044import biweekly.util.ICalDate;
045import biweekly.util.Recurrence;
046
047/*
048 Copyright (c) 2013-2015, Michael Angstadt
049 All rights reserved.
050
051 Redistribution and use in source and binary forms, with or without
052 modification, are permitted provided that the following conditions are met: 
053
054 1. Redistributions of source code must retain the above copyright notice, this
055 list of conditions and the following disclaimer. 
056 2. Redistributions in binary form must reproduce the above copyright notice,
057 this list of conditions and the following disclaimer in the documentation
058 and/or other materials provided with the distribution. 
059
060 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
061 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
062 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
063 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
064 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
065 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
066 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
067 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
068 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
069 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
070 */
071
072/**
073 * <p>
074 * Defines a task or assignment.
075 * </p>
076 * <p>
077 * <b>Examples:</b>
078 * 
079 * <pre class="brush:java">
080 * VTodo todo = new VTodo();
081 * todo.setSummary("Complete report");
082 * Date due = ...
083 * todo.setDateDue(due);
084 * todo.setStatus(Status.confirmed());
085 * </pre>
086 * 
087 * </p>
088 * @author Michael Angstadt
089 * @see <a href="http://tools.ietf.org/html/rfc5545#page-55">RFC 5545 p.55-7</a>
090 * @see <a href="http://tools.ietf.org/html/rfc2445#page-55">RFC 2445 p.55-6</a>
091 * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.14</a>
092 */
093public class VTodo extends ICalComponent {
094        /**
095         * <p>
096         * Creates a new to-do entry.
097         * </p>
098         * <p>
099         * The following properties are auto-generated on object creation. These
100         * properties <b>must</b> be present in order for the to-do to be valid:
101         * <ul>
102         * <li>{@link Uid} - Set to a UUID.</li>
103         * <li>{@link DateTimeStamp} - Set to the current date-time.</li>
104         * </ul>
105         * </p>
106         */
107        public VTodo() {
108                setUid(Uid.random());
109                setDateTimeStamp(new Date());
110        }
111
112        /**
113         * Gets the unique identifier for this to-do. This component object comes
114         * populated with a UID on creation. This is a <b>required</b> property.
115         * @return the UID or null if not set
116         * @see <a href="http://tools.ietf.org/html/rfc5545#page-117">RFC 5545
117         * p.117-8</a>
118         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.37</a>
119         */
120        public Uid getUid() {
121                return getProperty(Uid.class);
122        }
123
124        /**
125         * Sets the unique identifier for this to-do. This component object comes
126         * populated with a UID on creation. This is a <b>required</b> property.
127         * @param uid the UID or null to remove
128         * @see <a href="http://tools.ietf.org/html/rfc5545#page-117">RFC 5545
129         * p.117-8</a>
130         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.37</a>
131         */
132        public void setUid(Uid uid) {
133                setProperty(Uid.class, uid);
134        }
135
136        /**
137         * Sets the unique identifier for this to-do. This component object comes
138         * populated with a UID on creation. This is a <b>required</b> property.
139         * @param uid the UID or null to remove
140         * @return the property that was created
141         * @see <a href="http://tools.ietf.org/html/rfc5545#page-117">RFC 5545
142         * p.117-8</a>
143         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.37</a>
144         */
145        public Uid setUid(String uid) {
146                Uid prop = (uid == null) ? null : new Uid(uid);
147                setUid(prop);
148                return prop;
149        }
150
151        /**
152         * Gets either (a) the creation date of the iCalendar object (if the
153         * {@link Method} property is defined) or (b) the date that the to-do was
154         * last modified (the {@link LastModified} property also holds this
155         * information). This to-do object comes populated with a
156         * {@link DateTimeStamp} property that is set to the current time. This is a
157         * <b>required</b> property.
158         * @return the date time stamp or null if not set
159         * @see <a href="http://tools.ietf.org/html/rfc5545#page-137">RFC 5545
160         * p.137-8</a>
161         */
162        public DateTimeStamp getDateTimeStamp() {
163                return getProperty(DateTimeStamp.class);
164        }
165
166        /**
167         * Sets either (a) the creation date of the iCalendar object (if the
168         * {@link Method} property is defined) or (b) the date that the to-do was
169         * last modified (the {@link LastModified} property also holds this
170         * information). This to-do object comes populated with a
171         * {@link DateTimeStamp} property that is set to the current time. This is a
172         * <b>required</b> property.
173         * @param dateTimeStamp the date time stamp or null to remove
174         * @see <a href="http://tools.ietf.org/html/rfc5545#page-137">RFC 5545
175         * p.137-8</a>
176         */
177        public void setDateTimeStamp(DateTimeStamp dateTimeStamp) {
178                setProperty(DateTimeStamp.class, dateTimeStamp);
179        }
180
181        /**
182         * Sets either (a) the creation date of the iCalendar object (if the
183         * {@link Method} property is defined) or (b) the date that the to-do was
184         * last modified (the {@link LastModified} property also holds this
185         * information). This to-do object comes populated with a
186         * {@link DateTimeStamp} property that is set to the current time. This is a
187         * <b>required</b> property.
188         * @param dateTimeStamp the date time stamp or null to remove
189         * @return the property that was created
190         * @see <a href="http://tools.ietf.org/html/rfc5545#page-137">RFC 5545
191         * p.137-8</a>
192         */
193        public DateTimeStamp setDateTimeStamp(Date dateTimeStamp) {
194                DateTimeStamp prop = (dateTimeStamp == null) ? null : new DateTimeStamp(dateTimeStamp);
195                setDateTimeStamp(prop);
196                return prop;
197        }
198
199        /**
200         * Gets the level of sensitivity of the to-do data. If not specified, the
201         * data within the to-do should be considered "public".
202         * @return the classification level or null if not set
203         * @see <a href="http://tools.ietf.org/html/rfc5545#page-82">RFC 5545
204         * p.82-3</a>
205         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.28-9</a>
206         */
207        public Classification getClassification() {
208                return getProperty(Classification.class);
209        }
210
211        /**
212         * Sets the level of sensitivity of the to-do data. If not specified, the
213         * data within the to-do should be considered "public".
214         * @param classification the classification level or null to remove
215         * @see <a href="http://tools.ietf.org/html/rfc5545#page-82">RFC 5545
216         * p.82-3</a>
217         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.28-9</a>
218         */
219        public void setClassification(Classification classification) {
220                setProperty(Classification.class, classification);
221        }
222
223        /**
224         * Sets the level of sensitivity of the to-do data. If not specified, the
225         * data within the to-do should be considered "public".
226         * @param classification the classification level (e.g. "CONFIDENTIAL") or
227         * null to remove
228         * @return the property that was created
229         * @see <a href="http://tools.ietf.org/html/rfc5545#page-82">RFC 5545
230         * p.82-3</a>
231         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.28-9</a>
232         */
233        public Classification setClassification(String classification) {
234                Classification prop = (classification == null) ? null : new Classification(classification);
235                setClassification(prop);
236                return prop;
237        }
238
239        /**
240         * Gets the date and time that the to-do was completed.
241         * @return the completion date or null if not set
242         * @see <a href="http://tools.ietf.org/html/rfc5545#page-94">RFC 5545
243         * p.94-5</a>
244         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.29</a>
245         */
246        public Completed getCompleted() {
247                return getProperty(Completed.class);
248        }
249
250        /**
251         * Sets the date and time that the to-do was completed.
252         * @param completed the completion date or null to remove
253         * @see <a href="http://tools.ietf.org/html/rfc5545#page-94">RFC 5545
254         * p.94-5</a>
255         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.29</a>
256         */
257        public void setCompleted(Completed completed) {
258                setProperty(Completed.class, completed);
259        }
260
261        /**
262         * Sets the date and time that the to-do was completed.
263         * @param completed the completion date or null to remove
264         * @return the property that was created
265         * @see <a href="http://tools.ietf.org/html/rfc5545#page-94">RFC 5545
266         * p.94-5</a>
267         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.29</a>
268         */
269        public Completed setCompleted(Date completed) {
270                Completed prop = (completed == null) ? null : new Completed(completed);
271                setCompleted(prop);
272                return prop;
273        }
274
275        /**
276         * Gets the date-time that the to-do was initially created.
277         * @return the creation date-time or null if not set
278         * @see <a href="http://tools.ietf.org/html/rfc5545#page-136">RFC 5545
279         * p.136</a>
280         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.29</a>
281         */
282        public Created getCreated() {
283                return getProperty(Created.class);
284        }
285
286        /**
287         * Sets the date-time that the to-do was initially created.
288         * @param created the creation date-time or null to remove
289         * @see <a href="http://tools.ietf.org/html/rfc5545#page-136">RFC 5545
290         * p.136</a>
291         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.29</a>
292         */
293        public void setCreated(Created created) {
294                setProperty(Created.class, created);
295        }
296
297        /**
298         * Sets the date-time that the to-do was initially created.
299         * @param created the creation date-time or null to remove
300         * @return the property that was created
301         * @see <a href="http://tools.ietf.org/html/rfc5545#page-136">RFC 5545
302         * p.136</a>
303         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.29</a>
304         */
305        public Created setCreated(Date created) {
306                Created prop = (created == null) ? null : new Created(created);
307                setCreated(prop);
308                return prop;
309        }
310
311        /**
312         * Gets a detailed description of the to-do. The description should be more
313         * detailed than the one provided by the {@link Summary} property.
314         * @return the description or null if not set
315         * @see <a href="http://tools.ietf.org/html/rfc5545#page-84">RFC 5545
316         * p.84-5</a>
317         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.30</a>
318         */
319        public Description getDescription() {
320                return getProperty(Description.class);
321        }
322
323        /**
324         * Sets a detailed description of the to-do. The description should be more
325         * detailed than the one provided by the {@link Summary} property.
326         * @param description the description or null to remove
327         * @see <a href="http://tools.ietf.org/html/rfc5545#page-84">RFC 5545
328         * p.84-5</a>
329         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.30</a>
330         */
331        public void setDescription(Description description) {
332                setProperty(Description.class, description);
333        }
334
335        /**
336         * Sets a detailed description of the to-do. The description should be more
337         * detailed than the one provided by the {@link Summary} property.
338         * @param description the description or null to remove
339         * @return the property that was created
340         * @see <a href="http://tools.ietf.org/html/rfc5545#page-84">RFC 5545
341         * p.84-5</a>
342         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.30</a>
343         */
344        public Description setDescription(String description) {
345                Description prop = (description == null) ? null : new Description(description);
346                setDescription(prop);
347                return prop;
348        }
349
350        /**
351         * Gets the date that the to-do starts.
352         * @return the start date or null if not set
353         * @see <a href="http://tools.ietf.org/html/rfc5545#page-97">RFC 5545
354         * p.97-8</a>
355         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.35</a>
356         */
357        public DateStart getDateStart() {
358                return getProperty(DateStart.class);
359        }
360
361        /**
362         * Sets the date that the to-do starts.
363         * @param dateStart the start date or null to remove
364         * @see <a href="http://tools.ietf.org/html/rfc5545#page-97">RFC 5545
365         * p.97-8</a>
366         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.35</a>
367         */
368        public void setDateStart(DateStart dateStart) {
369                setProperty(DateStart.class, dateStart);
370        }
371
372        /**
373         * Sets the date that the to-do starts.
374         * @param dateStart the start date or null to remove
375         * @return the property that was created
376         * @see <a href="http://tools.ietf.org/html/rfc5545#page-97">RFC 5545
377         * p.97-8</a>
378         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.35</a>
379         */
380        public DateStart setDateStart(Date dateStart) {
381                DateStart prop = (dateStart == null) ? null : new DateStart(dateStart);
382                setDateStart(prop);
383                return prop;
384        }
385
386        /**
387         * Gets a set of geographical coordinates.
388         * @return the geographical coordinates or null if not set
389         * @see <a href="http://tools.ietf.org/html/rfc5545#page-85">RFC 5545
390         * p.85-7</a>
391         */
392        public Geo getGeo() {
393                return getProperty(Geo.class);
394        }
395
396        /**
397         * Sets a set of geographical coordinates.
398         * @param geo the geographical coordinates or null to remove
399         * @see <a href="http://tools.ietf.org/html/rfc5545#page-85">RFC 5545
400         * p.85-7</a>
401         */
402        public void setGeo(Geo geo) {
403                setProperty(Geo.class, geo);
404        }
405
406        /**
407         * Gets the date-time that the to-do was last changed.
408         * @return the last modified date or null if not set
409         * @see <a href="http://tools.ietf.org/html/rfc5545#page-138">RFC 5545
410         * p.138</a>
411         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.31</a>
412         */
413        public LastModified getLastModified() {
414                return getProperty(LastModified.class);
415        }
416
417        /**
418         * Sets the date-time that the to-do was last changed.
419         * @param lastModified the last modified date or null to remove
420         * @see <a href="http://tools.ietf.org/html/rfc5545#page-138">RFC 5545
421         * p.138</a>
422         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.31</a>
423         */
424        public void setLastModified(LastModified lastModified) {
425                setProperty(LastModified.class, lastModified);
426        }
427
428        /**
429         * Sets the date-time that the to-do was last changed.
430         * @param lastModified the last modified date or null to remove
431         * @return the property that was created
432         * @see <a href="http://tools.ietf.org/html/rfc5545#page-138">RFC 5545
433         * p.138</a>
434         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.31</a>
435         */
436        public LastModified setLastModified(Date lastModified) {
437                LastModified prop = (lastModified == null) ? null : new LastModified(lastModified);
438                setLastModified(prop);
439                return prop;
440        }
441
442        /**
443         * Gets the physical location of the to-do.
444         * @return the location or null if not set
445         * @see <a href="http://tools.ietf.org/html/rfc5545#page-87">RFC 5545
446         * p.87-8</a>
447         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.32</a>
448         */
449        public Location getLocation() {
450                return getProperty(Location.class);
451        }
452
453        /**
454         * Sets the physical location of the to-do.
455         * @param location the location or null to remove
456         * @see <a href="http://tools.ietf.org/html/rfc5545#page-87">RFC 5545
457         * p.87-8</a>
458         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.32</a>
459         */
460        public void setLocation(Location location) {
461                setProperty(Location.class, location);
462        }
463
464        /**
465         * Sets the physical location of the to-do.
466         * @param location the location (e.g. "Room 101") or null to remove
467         * @return the property that was created
468         * @see <a href="http://tools.ietf.org/html/rfc5545#page-87">RFC 5545
469         * p.87-8</a>
470         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.32</a>
471         */
472        public Location setLocation(String location) {
473                Location prop = (location == null) ? null : new Location(location);
474                setLocation(prop);
475                return prop;
476        }
477
478        /**
479         * Gets the organizer of the to-do.
480         * @return the organizer or null if not set
481         * @see <a href="http://tools.ietf.org/html/rfc5545#page-111">RFC 5545
482         * p.111-2</a>
483         */
484        public Organizer getOrganizer() {
485                return getProperty(Organizer.class);
486        }
487
488        /**
489         * Sets the organizer of the to-do.
490         * @param organizer the organizer or null to remove
491         * @see <a href="http://tools.ietf.org/html/rfc5545#page-111">RFC 5545
492         * p.111-2</a>
493         */
494        public void setOrganizer(Organizer organizer) {
495                setProperty(Organizer.class, organizer);
496        }
497
498        /**
499         * Sets the organizer of the to-do.
500         * @param email the organizer's email address (e.g. "johndoe@example.com")
501         * or null to remove
502         * @return the property that was created
503         * @see <a href="http://tools.ietf.org/html/rfc5545#page-111">RFC 5545
504         * p.111-2</a>
505         */
506        public Organizer setOrganizer(String email) {
507                Organizer prop = (email == null) ? null : new Organizer(null, email);
508                setOrganizer(prop);
509                return prop;
510        }
511
512        /**
513         * Gets the amount that the to-do task has been completed.
514         * @return the percent complete or null if not set
515         * @see <a href="http://tools.ietf.org/html/rfc5545#page-88">RFC 5545
516         * p.88-9</a>
517         */
518        public PercentComplete getPercentComplete() {
519                return getProperty(PercentComplete.class);
520        }
521
522        /**
523         * Sets the amount that the to-do task has been completed.
524         * @param percentComplete the percent complete or null to remove
525         * @see <a href="http://tools.ietf.org/html/rfc5545#page-88">RFC 5545
526         * p.88-9</a>
527         */
528        public void setPercentComplete(PercentComplete percentComplete) {
529                setProperty(PercentComplete.class, percentComplete);
530        }
531
532        /**
533         * Sets the amount that the to-do task has been completed.
534         * @param percent the percent complete (e.g. "50" for 50%) or null to remove
535         * @return the property that was created
536         * @see <a href="http://tools.ietf.org/html/rfc5545#page-88">RFC 5545
537         * p.88-9</a>
538         */
539        public PercentComplete setPercentComplete(Integer percent) {
540                PercentComplete prop = (percent == null) ? null : new PercentComplete(percent);
541                setPercentComplete(prop);
542                return prop;
543        }
544
545        /**
546         * Gets the priority of the to-do.
547         * @return the priority or null if not set
548         * @see <a href="http://tools.ietf.org/html/rfc5545#page-89">RFC 5545
549         * p.89-90</a>
550         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.33</a>
551         */
552        public Priority getPriority() {
553                return getProperty(Priority.class);
554        }
555
556        /**
557         * Sets the priority of the to-do.
558         * @param priority the priority or null to remove
559         * @see <a href="http://tools.ietf.org/html/rfc5545#page-89">RFC 5545
560         * p.89-90</a>
561         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.33</a>
562         */
563        public void setPriority(Priority priority) {
564                setProperty(Priority.class, priority);
565        }
566
567        /**
568         * Sets the priority of the to-do.
569         * @param priority the priority ("0" is undefined, "1" is the highest, "9"
570         * is the lowest) or null to remove
571         * @return the property that was created
572         * @see <a href="http://tools.ietf.org/html/rfc5545#page-89">RFC 5545
573         * p.89-90</a>
574         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.33</a>
575         */
576        public Priority setPriority(Integer priority) {
577                Priority prop = (priority == null) ? null : new Priority(priority);
578                setPriority(prop);
579                return prop;
580        }
581
582        /**
583         * Gets the original value of the {@link DateStart} property if the to-do is
584         * recurring and has been modified. Used in conjunction with the {@link Uid}
585         * and {@link Sequence} properties to uniquely identify a recurrence
586         * instance.
587         * @return the recurrence ID or null if not set
588         * @see <a href="http://tools.ietf.org/html/rfc5545#page-112">RFC 5545
589         * p.112-4</a>
590         */
591        public RecurrenceId getRecurrenceId() {
592                return getProperty(RecurrenceId.class);
593        }
594
595        /**
596         * Sets the original value of the {@link DateStart} property if the to-do is
597         * recurring and has been modified. Used in conjunction with the {@link Uid}
598         * and {@link Sequence} properties to uniquely identify a recurrence
599         * instance.
600         * @param recurrenceId the recurrence ID or null to remove
601         * @see <a href="http://tools.ietf.org/html/rfc5545#page-112">RFC 5545
602         * p.112-4</a>
603         */
604        public void setRecurrenceId(RecurrenceId recurrenceId) {
605                setProperty(RecurrenceId.class, recurrenceId);
606        }
607
608        /**
609         * Sets the original value of the {@link DateStart} property if the to-do is
610         * recurring and has been modified. Used in conjunction with the {@link Uid}
611         * and {@link Sequence} properties to uniquely identify a recurrence
612         * instance.
613         * @param originalStartDate the original start date or null to remove
614         * @return the property that was created
615         * @see <a href="http://tools.ietf.org/html/rfc5545#page-112">RFC 5545
616         * p.112-4</a>
617         */
618        public RecurrenceId setRecurrenceId(Date originalStartDate) {
619                RecurrenceId prop = (originalStartDate == null) ? null : new RecurrenceId(originalStartDate);
620                setRecurrenceId(prop);
621                return prop;
622        }
623
624        /**
625         * Gets the revision number of the to-do. The organizer can increment this
626         * number every time he or she makes a significant change.
627         * @return the sequence number
628         * @see <a href="http://tools.ietf.org/html/rfc5545#page-138">RFC 5545
629         * p.138-9</a>
630         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.35</a>
631         */
632        public Sequence getSequence() {
633                return getProperty(Sequence.class);
634        }
635
636        /**
637         * Sets the revision number of the to-do. The organizer can increment this
638         * number every time he or she makes a significant change.
639         * @param sequence the sequence number
640         * @see <a href="http://tools.ietf.org/html/rfc5545#page-138">RFC 5545
641         * p.138-9</a>
642         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.35</a>
643         */
644        public void setSequence(Sequence sequence) {
645                setProperty(Sequence.class, sequence);
646        }
647
648        /**
649         * Sets the revision number of the to-do. The organizer can increment this
650         * number every time he or she makes a significant change.
651         * @param sequence the sequence number
652         * @return the property that was created
653         * @see <a href="http://tools.ietf.org/html/rfc5545#page-138">RFC 5545
654         * p.138-9</a>
655         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.35</a>
656         */
657        public Sequence setSequence(Integer sequence) {
658                Sequence prop = (sequence == null) ? null : new Sequence(sequence);
659                setSequence(prop);
660                return prop;
661        }
662
663        /**
664         * Increments the revision number of the to-do. The organizer can increment
665         * this number every time he or she makes a significant change.
666         * @see <a href="http://tools.ietf.org/html/rfc5545#page-138">RFC 5545
667         * p.138-9</a>
668         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.35</a>
669         */
670        public void incrementSequence() {
671                Sequence sequence = getSequence();
672                if (sequence == null) {
673                        setSequence(1);
674                } else {
675                        sequence.increment();
676                }
677        }
678
679        /**
680         * Gets the status of the to-do.
681         * @return the status or null if not set
682         * @see <a href="http://tools.ietf.org/html/rfc5545#page-92">RFC 5545
683         * p.92-3</a>
684         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.35-6</a>
685         */
686        public Status getStatus() {
687                return getProperty(Status.class);
688        }
689
690        /**
691         * Sets the status of the to-do.
692         * <p>
693         * Valid to-do status codes are:
694         * <ul>
695         * <li>NEEDS-ACTION</li>
696         * <li>COMPLETED</li>
697         * <li>IN-PROGRESS</li>
698         * <li>CANCELLED</li>
699         * </ul>
700         * </p>
701         * @param status the status or null to remove
702         * @see <a href="http://tools.ietf.org/html/rfc5545#page-92">RFC 5545
703         * p.92-3</a>
704         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.35-6</a>
705         */
706        public void setStatus(Status status) {
707                setProperty(Status.class, status);
708        }
709
710        /**
711         * Gets the summary of the to-do.
712         * @return the summary or null if not set
713         * @see <a href="http://tools.ietf.org/html/rfc5545#page-93">RFC 5545
714         * p.93-4</a>
715         */
716        public Summary getSummary() {
717                return getProperty(Summary.class);
718        }
719
720        /**
721         * Sets the summary of the to-do.
722         * @param summary the summary or null to remove
723         * @see <a href="http://tools.ietf.org/html/rfc5545#page-93">RFC 5545
724         * p.93-4</a>
725         */
726        public void setSummary(Summary summary) {
727                setProperty(Summary.class, summary);
728        }
729
730        /**
731         * Sets the summary of the to-do.
732         * @param summary the summary or null to remove
733         * @return the property that was created
734         * @see <a href="http://tools.ietf.org/html/rfc5545#page-93">RFC 5545
735         * p.93-4</a>
736         */
737        public Summary setSummary(String summary) {
738                Summary prop = (summary == null) ? null : new Summary(summary);
739                setSummary(prop);
740                return prop;
741        }
742
743        /**
744         * Gets a URL to a resource that contains additional information about the
745         * to-do.
746         * @return the URL or null if not set
747         * @see <a href="http://tools.ietf.org/html/rfc5545#page-116">RFC 5545
748         * p.116-7</a>
749         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.37</a>
750         */
751        public Url getUrl() {
752                return getProperty(Url.class);
753        }
754
755        /**
756         * Sets a URL to a resource that contains additional information about the
757         * to-do.
758         * @param url the URL or null to remove
759         * @see <a href="http://tools.ietf.org/html/rfc5545#page-116">RFC 5545
760         * p.116-7</a>
761         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.37</a>
762         */
763        public void setUrl(Url url) {
764                setProperty(Url.class, url);
765        }
766
767        /**
768         * Sets a URL to a resource that contains additional information about the
769         * to-do.
770         * @param url the URL (e.g. "http://example.com/resource.ics") or null to
771         * remove
772         * @return the property that was created
773         * @see <a href="http://tools.ietf.org/html/rfc5545#page-116">RFC 5545
774         * p.116-7</a>
775         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.37</a>
776         */
777        public Url setUrl(String url) {
778                Url prop = (url == null) ? null : new Url(url);
779                setUrl(prop);
780                return prop;
781        }
782
783        /**
784         * Gets how often the to-do repeats.
785         * @return the recurrence rule or null if not set
786         * @see <a href="http://tools.ietf.org/html/rfc5545#page-122">RFC 5545
787         * p.122-32</a>
788         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.34</a>
789         */
790        public RecurrenceRule getRecurrenceRule() {
791                return getProperty(RecurrenceRule.class);
792        }
793
794        /**
795         * Sets how often the to-do repeats.
796         * @param recur the recurrence rule or null to remove
797         * @return the property that was created
798         * @see <a href="http://tools.ietf.org/html/rfc5545#page-122">RFC 5545
799         * p.122-32</a>
800         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.34</a>
801         */
802        public RecurrenceRule setRecurrenceRule(Recurrence recur) {
803                RecurrenceRule prop = (recur == null) ? null : new RecurrenceRule(recur);
804                setRecurrenceRule(prop);
805                return prop;
806        }
807
808        /**
809         * Sets how often the to-do repeats.
810         * @param recurrenceRule the recurrence rule or null to remove
811         * @see <a href="http://tools.ietf.org/html/rfc5545#page-122">RFC 5545
812         * p.122-32</a>
813         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.34</a>
814         */
815        public void setRecurrenceRule(RecurrenceRule recurrenceRule) {
816                setProperty(RecurrenceRule.class, recurrenceRule);
817        }
818
819        /**
820         * Gets the date that a to-do is due by.
821         * @return the due date or null if not set
822         * @see <a href="http://tools.ietf.org/html/rfc5545#page-96">RFC 5545
823         * p.96-7</a>
824         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.30</a>
825         */
826        public DateDue getDateDue() {
827                return getProperty(DateDue.class);
828        }
829
830        /**
831         * Sets the date that a to-do is due by. This must NOT be set if a
832         * {@link DurationProperty} is defined.
833         * @param dateDue the due date or null to remove
834         * @see <a href="http://tools.ietf.org/html/rfc5545#page-96">RFC 5545
835         * p.96-7</a>
836         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.30</a>
837         */
838        public void setDateDue(DateDue dateDue) {
839                setProperty(DateDue.class, dateDue);
840        }
841
842        /**
843         * Sets the date that a to-do is due by. This must NOT be set if a
844         * {@link DurationProperty} is defined.
845         * @param dateDue the due date or null to remove
846         * @return the property that was created
847         * @see <a href="http://tools.ietf.org/html/rfc5545#page-96">RFC 5545
848         * p.96-7</a>
849         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.30</a>
850         */
851        public DateDue setDateDue(Date dateDue) {
852                DateDue prop = (dateDue == null) ? null : new DateDue(dateDue);
853                setDateDue(prop);
854                return prop;
855        }
856
857        /**
858         * Gets the duration of the to-do.
859         * @return the duration or null if not set
860         * @see <a href="http://tools.ietf.org/html/rfc5545#page-99">RFC 5545
861         * p.99</a>
862         */
863        public DurationProperty getDuration() {
864                return getProperty(DurationProperty.class);
865        }
866
867        /**
868         * Sets the duration of the to-do. This must NOT be set if a {@link DateDue}
869         * is defined.
870         * @param duration the duration or null to remove
871         * @see <a href="http://tools.ietf.org/html/rfc5545#page-99">RFC 5545
872         * p.99</a>
873         */
874        public void setDuration(DurationProperty duration) {
875                setProperty(DurationProperty.class, duration);
876        }
877
878        /**
879         * Sets the duration of the to-do. This must NOT be set if a {@link DateDue}
880         * is defined.
881         * @param duration the duration or null to remove
882         * @return the property that was created
883         * @see <a href="http://tools.ietf.org/html/rfc5545#page-99">RFC 5545
884         * p.99</a>
885         */
886        public DurationProperty setDuration(Duration duration) {
887                DurationProperty prop = (duration == null) ? null : new DurationProperty(duration);
888                setDuration(prop);
889                return prop;
890        }
891
892        /**
893         * Gets any attachments that are associated with the to-do.
894         * @return the attachments
895         * @see <a href="http://tools.ietf.org/html/rfc5545#page-80">RFC 5545
896         * p.80-1</a>
897         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.25</a>
898         */
899        public List<Attachment> getAttachments() {
900                return getProperties(Attachment.class);
901        }
902
903        /**
904         * Adds an attachment to the to-do.
905         * @param attachment the attachment to add
906         * @see <a href="http://tools.ietf.org/html/rfc5545#page-80">RFC 5545
907         * p.80-1</a>
908         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.25</a>
909         */
910        public void addAttachment(Attachment attachment) {
911                addProperty(attachment);
912        }
913
914        /**
915         * Gets the people who are involved in the to-do.
916         * @return the attendees
917         * @see <a href="http://tools.ietf.org/html/rfc5545#page-107">RFC 5545
918         * p.107-9</a>
919         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.25-7</a>
920         */
921        public List<Attendee> getAttendees() {
922                return getProperties(Attendee.class);
923        }
924
925        /**
926         * Adds a person who is involved in the to-do.
927         * @param attendee the attendee
928         * @see <a href="http://tools.ietf.org/html/rfc5545#page-107">RFC 5545
929         * p.107-9</a>
930         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.25-7</a>
931         */
932        public void addAttendee(Attendee attendee) {
933                addProperty(attendee);
934        }
935
936        /**
937         * Adds a person who is involved in the to-do.
938         * @param email the attendee's email address
939         * @return the property that was created
940         * @see <a href="http://tools.ietf.org/html/rfc5545#page-107">RFC 5545
941         * p.107-9</a>
942         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.25-7</a>
943         */
944        public Attendee addAttendee(String email) {
945                Attendee prop = new Attendee(null, email);
946                addAttendee(prop);
947                return prop;
948        }
949
950        /**
951         * Gets a list of "tags" or "keywords" that describe the to-do.
952         * @return the categories
953         * @see <a href="http://tools.ietf.org/html/rfc5545#page-81">RFC 5545
954         * p.81-2</a>
955         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.28</a>
956         */
957        public List<Categories> getCategories() {
958                return getProperties(Categories.class);
959        }
960
961        /**
962         * Adds a list of "tags" or "keywords" that describe the to-do. Note that a
963         * single property can hold multiple keywords.
964         * @param categories the categories to add
965         * @see <a href="http://tools.ietf.org/html/rfc5545#page-81">RFC 5545
966         * p.81-2</a>
967         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.28</a>
968         */
969        public void addCategories(Categories categories) {
970                addProperty(categories);
971        }
972
973        /**
974         * Adds a list of "tags" or "keywords" that describe the to-do.
975         * @param categories the categories to add
976         * @return the property that was created
977         * @see <a href="http://tools.ietf.org/html/rfc5545#page-81">RFC 5545
978         * p.81-2</a>
979         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.28</a>
980         */
981        public Categories addCategories(String... categories) {
982                Categories prop = new Categories(categories);
983                addCategories(prop);
984                return prop;
985        }
986
987        /**
988         * Adds a list of "tags" or "keywords" that describe the to-do.
989         * @param categories the categories to add
990         * @return the property that was created
991         * @see <a href="http://tools.ietf.org/html/rfc5545#page-81">RFC 5545
992         * p.81-2</a>
993         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.28</a>
994         */
995        public Categories addCategories(List<String> categories) {
996                Categories prop = new Categories(categories);
997                addCategories(prop);
998                return prop;
999        }
1000
1001        /**
1002         * Gets the comments attached to the to-do.
1003         * @return the comments
1004         * @see <a href="http://tools.ietf.org/html/rfc5545#page-83">RFC 5545
1005         * p.83-4</a>
1006         */
1007        public List<Comment> getComments() {
1008                return getProperties(Comment.class);
1009        }
1010
1011        /**
1012         * Adds a comment to the to-do.
1013         * @param comment the comment to add
1014         * @see <a href="http://tools.ietf.org/html/rfc5545#page-83">RFC 5545
1015         * p.83-4</a>
1016         */
1017        public void addComment(Comment comment) {
1018                addProperty(comment);
1019        }
1020
1021        /**
1022         * Adds a comment to the to-do.
1023         * @param comment the comment to add
1024         * @return the property that was created
1025         * @see <a href="http://tools.ietf.org/html/rfc5545#page-83">RFC 5545
1026         * p.83-4</a>
1027         */
1028        public Comment addComment(String comment) {
1029                Comment prop = new Comment(comment);
1030                addComment(prop);
1031                return prop;
1032        }
1033
1034        /**
1035         * Gets the contacts associated with the to-do.
1036         * @return the contacts
1037         * @see <a href="http://tools.ietf.org/html/rfc5545#page-109">RFC 5545
1038         * p.109-11</a>
1039         */
1040        public List<Contact> getContacts() {
1041                return getProperties(Contact.class);
1042        }
1043
1044        /**
1045         * Adds a contact to the to-do.
1046         * @param contact the contact
1047         * @see <a href="http://tools.ietf.org/html/rfc5545#page-109">RFC 5545
1048         * p.109-11</a>
1049         */
1050        public void addContact(Contact contact) {
1051                addProperty(contact);
1052        }
1053
1054        /**
1055         * Adds a contact to the to-do.
1056         * @param contact the contact (e.g. "ACME Co - (123) 555-1234")
1057         * @return the property that was created
1058         * @see <a href="http://tools.ietf.org/html/rfc5545#page-109">RFC 5545
1059         * p.109-11</a>
1060         */
1061        public Contact addContact(String contact) {
1062                Contact prop = new Contact(contact);
1063                addContact(prop);
1064                return prop;
1065        }
1066
1067        /**
1068         * Gets the list of exceptions to the recurrence rule defined in the to-do
1069         * (if one is defined).
1070         * @return the list of exceptions
1071         * @see <a href="http://tools.ietf.org/html/rfc5545#page-118">RFC 5545
1072         * p.118-20</a>
1073         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.31</a>
1074         */
1075        public List<ExceptionDates> getExceptionDates() {
1076                return getProperties(ExceptionDates.class);
1077        }
1078
1079        /**
1080         * Adds a list of exceptions to the recurrence rule defined in the to-do (if
1081         * one is defined). Note that this property can contain multiple dates.
1082         * @param exceptionDates the list of exceptions
1083         * @see <a href="http://tools.ietf.org/html/rfc5545#page-118">RFC 5545
1084         * p.118-20</a>
1085         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.31</a>
1086         */
1087        public void addExceptionDates(ExceptionDates exceptionDates) {
1088                addProperty(exceptionDates);
1089        }
1090
1091        /**
1092         * Gets the response to a scheduling request.
1093         * @return the response
1094         * @see <a href="http://tools.ietf.org/html/rfc5545#page-141">RFC 5545
1095         * p.141-3</a>
1096         */
1097        public RequestStatus getRequestStatus() {
1098                return getProperty(RequestStatus.class);
1099        }
1100
1101        /**
1102         * Sets the response to a scheduling request.
1103         * @param requestStatus the response
1104         * @see <a href="http://tools.ietf.org/html/rfc5545#page-141">RFC 5545
1105         * p.141-3</a>
1106         */
1107        public void setRequestStatus(RequestStatus requestStatus) {
1108                setProperty(RequestStatus.class, requestStatus);
1109        }
1110
1111        /**
1112         * Gets the components that the to-do is related to.
1113         * @return the relationships
1114         * @see <a href="http://tools.ietf.org/html/rfc5545#page-115">RFC 5545
1115         * p.115-6</a>
1116         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.33-4</a>
1117         */
1118        public List<RelatedTo> getRelatedTo() {
1119                return getProperties(RelatedTo.class);
1120        }
1121
1122        /**
1123         * Adds a component that the to-do is related to.
1124         * @param relatedTo the relationship
1125         * @see <a href="http://tools.ietf.org/html/rfc5545#page-115">RFC 5545
1126         * p.115-6</a>
1127         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.33-4</a>
1128         */
1129        public void addRelatedTo(RelatedTo relatedTo) {
1130                //TODO create a method that accepts a component and make the RelatedTo property invisible to the user
1131                //@formatter:off
1132                /*
1133                 * addRelation(RelationshipType relType, ICalComponent component){
1134                 *   RelatedTo prop = new RelatedTo(component.getUid().getValue());
1135                 *   prop.setRelationshipType(relType);
1136                 *   addProperty(prop);
1137                 * }
1138                 */
1139                //@formatter:on
1140                addProperty(relatedTo);
1141        }
1142
1143        /**
1144         * Adds a component that the to-do is related to.
1145         * @param uid the UID of the other component
1146         * @return the property that was created
1147         * @see <a href="http://tools.ietf.org/html/rfc5545#page-115">RFC 5545
1148         * p.115-6</a>
1149         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.33-4</a>
1150         */
1151        public RelatedTo addRelatedTo(String uid) {
1152                RelatedTo prop = new RelatedTo(uid);
1153                addRelatedTo(prop);
1154                return prop;
1155        }
1156
1157        /**
1158         * Gets the resources that are needed for the to-do.
1159         * @return the resources
1160         * @see <a href="http://tools.ietf.org/html/rfc5545#page-91">RFC 5545
1161         * p.91</a>
1162         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.34-5</a>
1163         */
1164        public List<Resources> getResources() {
1165                return getProperties(Resources.class);
1166        }
1167
1168        /**
1169         * Adds a list of resources that are needed for the to-do. Note that a
1170         * single property can hold multiple resources.
1171         * @param resources the resources to add
1172         * @see <a href="http://tools.ietf.org/html/rfc5545#page-91">RFC 5545
1173         * p.91</a>
1174         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.34-5</a>
1175         */
1176        public void addResources(Resources resources) {
1177                addProperty(resources);
1178        }
1179
1180        /**
1181         * Adds a list of resources that are needed for the to-do.
1182         * @param resources the resources to add (e.g. "easel", "projector")
1183         * @return the property that was created
1184         * @see <a href="http://tools.ietf.org/html/rfc5545#page-91">RFC 5545
1185         * p.91</a>
1186         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.34-5</a>
1187         */
1188        public Resources addResources(String... resources) {
1189                Resources prop = new Resources(resources);
1190                addResources(prop);
1191                return prop;
1192        }
1193
1194        /**
1195         * Adds a list of resources that are needed for the to-do.
1196         * @param resources the resources to add (e.g. "easel", "projector")
1197         * @return the property that was created
1198         * @see <a href="http://tools.ietf.org/html/rfc5545#page-91">RFC 5545
1199         * p.91</a>
1200         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.34-5</a>
1201         */
1202        public Resources addResources(List<String> resources) {
1203                Resources prop = new Resources(resources);
1204                addResources(prop);
1205                return prop;
1206        }
1207
1208        /**
1209         * Gets the list of dates/periods that help define the recurrence rule of
1210         * this to-do (if one is defined).
1211         * @return the recurrence dates
1212         * @see <a href="http://tools.ietf.org/html/rfc5545#page-120">RFC 5545
1213         * p.120-2</a>
1214         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.34</a>
1215         */
1216        public List<RecurrenceDates> getRecurrenceDates() {
1217                return getProperties(RecurrenceDates.class);
1218        }
1219
1220        /**
1221         * Adds a list of dates/periods that help define the recurrence rule of this
1222         * to-do (if one is defined).
1223         * @param recurrenceDates the recurrence dates
1224         * @see <a href="http://tools.ietf.org/html/rfc5545#page-120">RFC 5545
1225         * p.120-2</a>
1226         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.34</a>
1227         */
1228        public void addRecurrenceDates(RecurrenceDates recurrenceDates) {
1229                addProperty(recurrenceDates);
1230        }
1231
1232        /**
1233         * Gets the alarms that are assigned to this to-do.
1234         * @return the alarms
1235         * @see <a href="http://tools.ietf.org/html/rfc5545#page-71">RFC 5545
1236         * p.71-6</a>
1237         */
1238        public List<VAlarm> getAlarms() {
1239                return getComponents(VAlarm.class);
1240        }
1241
1242        /**
1243         * Adds an alarm to this to-do.
1244         * @param alarm the alarm
1245         * @see <a href="http://tools.ietf.org/html/rfc5545#page-71">RFC 5545
1246         * p.71-6</a>
1247         */
1248        public void addAlarm(VAlarm alarm) {
1249                addComponent(alarm);
1250        }
1251
1252        /**
1253         * <p>
1254         * Gets the exceptions for the {@link RecurrenceRule} property.
1255         * </p>
1256         * <p>
1257         * Note that this property has been removed from the latest version of the
1258         * iCal specification. Its use should be avoided.
1259         * </p>
1260         * @return the exception rules
1261         * @see <a href="http://tools.ietf.org/html/rfc2445#page-114">RFC 2445
1262         * p.114-15</a>
1263         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.31</a>
1264         */
1265        public List<ExceptionRule> getExceptionRules() {
1266                return getProperties(ExceptionRule.class);
1267        }
1268
1269        /**
1270         * <p>
1271         * Adds an exception for the {@link RecurrenceRule} property.
1272         * </p>
1273         * <p>
1274         * Note that this property has been removed from the latest version of the
1275         * iCal specification. Its use should be avoided.
1276         * </p>
1277         * @param recur the exception rule to add
1278         * @return the property that was created
1279         * @see <a href="http://tools.ietf.org/html/rfc2445#page-114">RFC 2445
1280         * p.114-15</a>
1281         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.31</a>
1282         */
1283        public ExceptionRule addExceptionRule(Recurrence recur) {
1284                ExceptionRule prop = new ExceptionRule(recur);
1285                addExceptionRule(prop);
1286                return prop;
1287        }
1288
1289        /**
1290         * <p>
1291         * Adds an exception for the {@link RecurrenceRule} property.
1292         * </p>
1293         * <p>
1294         * Note that this property has been removed from the latest version of the
1295         * iCal specification. Its use should be avoided.
1296         * </p>
1297         * @param exceptionRule the exception rule to add
1298         * @see <a href="http://tools.ietf.org/html/rfc2445#page-114">RFC 2445
1299         * p.114-15</a>
1300         * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.31</a>
1301         */
1302        public void addExceptionRule(ExceptionRule exceptionRule) {
1303                addProperty(exceptionRule);
1304        }
1305
1306        @SuppressWarnings("unchecked")
1307        @Override
1308        protected void validate(List<ICalComponent> components, ICalVersion version, List<Warning> warnings) {
1309                if (version != ICalVersion.V1_0) {
1310                        checkRequiredCardinality(warnings, Uid.class, DateTimeStamp.class);
1311                        checkOptionalCardinality(warnings, Classification.class, Completed.class, Created.class, Description.class, DateStart.class, Geo.class, LastModified.class, Location.class, Organizer.class, PercentComplete.class, Priority.class, RecurrenceId.class, Sequence.class, Status.class, Summary.class, Url.class);
1312                }
1313
1314                Status validStatuses[];
1315                switch (version) {
1316                case V1_0:
1317                        validStatuses = new Status[] { Status.needsAction(), Status.completed(), Status.accepted(), Status.declined(), Status.delegated(), Status.sent() };
1318                        break;
1319                default:
1320                        validStatuses = new Status[] { Status.needsAction(), Status.completed(), Status.inProgress(), Status.cancelled() };
1321                        break;
1322                }
1323                checkStatus(warnings, validStatuses);
1324
1325                ICalDate dateStart = getValue(getDateStart());
1326                ICalDate dateDue = getValue(getDateDue());
1327                if (dateStart != null && dateDue != null) {
1328                        //DTSTART must come before DUE
1329                        if (dateStart.compareTo(dateDue) > 0) {
1330                                warnings.add(Warning.validate(22));
1331                        }
1332
1333                        //DTSTART and DUE must have the same data type
1334                        if (dateStart.hasTime() != dateDue.hasTime()) {
1335                                warnings.add(Warning.validate(23));
1336                        }
1337                }
1338
1339                //DUE and DURATION cannot both exist
1340                DurationProperty duration = getDuration();
1341                if (dateDue != null && duration != null) {
1342                        warnings.add(Warning.validate(24));
1343                }
1344
1345                //DTSTART is required if DURATION exists
1346                if (dateStart == null && duration != null) {
1347                        warnings.add(Warning.validate(25));
1348                }
1349
1350                //DTSTART and RECURRENCE-ID must have the same data type
1351                ICalDate recurrenceId = getValue(getRecurrenceId());
1352                if (recurrenceId != null && dateStart != null && dateStart.hasTime() != recurrenceId.hasTime()) {
1353                        warnings.add(Warning.validate(19));
1354                }
1355
1356                //BYHOUR, BYMINUTE, and BYSECOND cannot be specified in RRULE if DTSTART's data type is "date"
1357                //RFC 5545 p. 167
1358                Recurrence rrule = getValue(getRecurrenceRule());
1359                if (dateStart != null && rrule != null) {
1360                        if (!dateStart.hasTime() && (!rrule.getByHour().isEmpty() || !rrule.getByMinute().isEmpty() || !rrule.getBySecond().isEmpty())) {
1361                                warnings.add(Warning.validate(5));
1362                        }
1363                }
1364
1365                //there *should* be only 1 instance of RRULE
1366                //RFC 5545 p. 167
1367                if (getProperties(RecurrenceRule.class).size() > 1) {
1368                        warnings.add(Warning.validate(6));
1369                }
1370        }
1371}