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