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