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