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.DateStart; 014 import biweekly.property.DateTimeStamp; 015 import biweekly.property.Description; 016 import biweekly.property.ExceptionDates; 017 import biweekly.property.ExceptionRule; 018 import biweekly.property.LastModified; 019 import biweekly.property.Method; 020 import biweekly.property.Organizer; 021 import biweekly.property.RecurrenceDates; 022 import biweekly.property.RecurrenceId; 023 import biweekly.property.RecurrenceRule; 024 import biweekly.property.RelatedTo; 025 import biweekly.property.RequestStatus; 026 import biweekly.property.Sequence; 027 import biweekly.property.Status; 028 import biweekly.property.Summary; 029 import biweekly.property.Uid; 030 import biweekly.property.Url; 031 import biweekly.util.Recurrence; 032 033 /* 034 Copyright (c) 2013, Michael Angstadt 035 All rights reserved. 036 037 Redistribution and use in source and binary forms, with or without 038 modification, are permitted provided that the following conditions are met: 039 040 1. Redistributions of source code must retain the above copyright notice, this 041 list of conditions and the following disclaimer. 042 2. Redistributions in binary form must reproduce the above copyright notice, 043 this list of conditions and the following disclaimer in the documentation 044 and/or other materials provided with the distribution. 045 046 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 047 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 048 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 049 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 050 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 051 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 052 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 053 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 054 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 055 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 056 */ 057 058 /** 059 * <p> 060 * Defines descriptive text associated with the calendar data. 061 * </p> 062 * <p> 063 * <b>Examples:</b> 064 * 065 * <pre class="brush:java"> 066 * VJournal journal = new VJournal(); 067 * journal.setSummary("Team Meeting"); 068 * journal.setDescription("The following items were discussed: ..."); 069 * byte[] slides = ... 070 * journal.addAttachment(new Attachment("application/vnd.ms-powerpoint", slides)); 071 * </pre> 072 * 073 * </p> 074 * @author Michael Angstadt 075 * @rfc 5545 p.57-9 076 */ 077 public class VJournal extends ICalComponent { 078 /** 079 * <p> 080 * Creates a new journal entry. 081 * </p> 082 * <p> 083 * The following properties are auto-generated on object creation. These 084 * properties <b>must</b> be present in order for the journal entry to be 085 * valid: 086 * <ul> 087 * <li>{@link Uid} - Set to a UUID.</li> 088 * <li>{@link DateTimeStamp} - Set to the current date-time.</li> 089 * </ul> 090 * </p> 091 */ 092 public VJournal() { 093 setUid(Uid.random()); 094 setDateTimeStamp(new Date()); 095 } 096 097 /** 098 * Gets the unique identifier for this journal entry. This component object 099 * comes populated with a UID on creation. This is a <b>required</b> 100 * property. 101 * @return the UID or null if not set 102 * @rfc 5545 p.117-8 103 */ 104 public Uid getUid() { 105 return getProperty(Uid.class); 106 } 107 108 /** 109 * Sets the unique identifier for this journal entry. This component object 110 * comes populated with a UID on creation. This is a <b>required</b> 111 * property. 112 * @param uid the UID or null to remove 113 * @rfc 5545 p.117-8 114 */ 115 public void setUid(Uid uid) { 116 setProperty(Uid.class, uid); 117 } 118 119 /** 120 * Sets the unique identifier for this journal entry. This component object 121 * comes populated with a UID on creation. This is a <b>required</b> 122 * property. 123 * @param uid the UID or null to remove 124 * @return the property that was created 125 * @rfc 5545 p.117-8 126 */ 127 public Uid setUid(String uid) { 128 Uid prop = (uid == null) ? null : new Uid(uid); 129 setUid(prop); 130 return prop; 131 } 132 133 /** 134 * Gets either (a) the creation date of the iCalendar object (if the 135 * {@link Method} property is defined) or (b) the date that the journal 136 * entry was last modified (the {@link LastModified} property also holds 137 * this information). This journal entry object comes populated with a 138 * {@link DateTimeStamp} property that is set to the current time. This is a 139 * <b>required</b> property. 140 * @return the date time stamp or null if not set 141 * @rfc 5545 p.137-8 142 */ 143 public DateTimeStamp getDateTimeStamp() { 144 return getProperty(DateTimeStamp.class); 145 } 146 147 /** 148 * Sets either (a) the creation date of the iCalendar object (if the 149 * {@link Method} property is defined) or (b) the date that the journal 150 * entry was last modified (the {@link LastModified} property also holds 151 * this information). This journal entry object comes populated with a 152 * {@link DateTimeStamp} property that is set to the current time. This is a 153 * <b>required</b> property. 154 * @param dateTimeStamp the date time stamp or null to remove 155 * @rfc 5545 p.137-8 156 */ 157 public void setDateTimeStamp(DateTimeStamp dateTimeStamp) { 158 setProperty(DateTimeStamp.class, dateTimeStamp); 159 } 160 161 /** 162 * Sets either (a) the creation date of the iCalendar object (if the 163 * {@link Method} property is defined) or (b) the date that the journal 164 * entry was last modified (the {@link LastModified} property also holds 165 * this information). This journal entry object comes populated with a 166 * {@link DateTimeStamp} property that is set to the current time. This is a 167 * <b>required</b> property. 168 * @param dateTimeStamp the date time stamp or null to remove 169 * @return the property that was created 170 * @rfc 5545 p.137-8 171 */ 172 public DateTimeStamp setDateTimeStamp(Date dateTimeStamp) { 173 DateTimeStamp prop = (dateTimeStamp == null) ? null : new DateTimeStamp(dateTimeStamp); 174 setDateTimeStamp(prop); 175 return prop; 176 } 177 178 /** 179 * Gets the level of sensitivity of the journal entry. If not specified, the 180 * data within the journal entry should be considered "public". 181 * @return the classification level or null if not set 182 * @rfc 5545 p.82-3 183 */ 184 public Classification getClassification() { 185 return getProperty(Classification.class); 186 } 187 188 /** 189 * Sets the level of sensitivity of the journal entry. If not specified, the 190 * data within the journal entry should be considered "public". 191 * @param classification the classification level or null to remove 192 * @rfc 5545 p.82-3 193 */ 194 public void setClassification(Classification classification) { 195 setProperty(Classification.class, classification); 196 } 197 198 /** 199 * Sets the level of sensitivity of the journal entry. If not specified, the 200 * data within the journal entry should be considered "public". 201 * @param classification the classification level (e.g. "CONFIDENTIAL") or 202 * null to remove 203 * @return the property that was created 204 * @rfc 5545 p.82-3 205 */ 206 public Classification setClassification(String classification) { 207 Classification prop = (classification == null) ? null : new Classification(classification); 208 setClassification(prop); 209 return prop; 210 } 211 212 /** 213 * Gets the date-time that the journal entry was initially created. 214 * @return the creation date-time or null if not set 215 * @rfc 5545 p.136 216 */ 217 public Created getCreated() { 218 return getProperty(Created.class); 219 } 220 221 /** 222 * Sets the date-time that the journal entry was initially created. 223 * @param created the creation date-time or null to remove 224 * @rfc 5545 p.136 225 */ 226 public void setCreated(Created created) { 227 setProperty(Created.class, created); 228 } 229 230 /** 231 * Sets the date-time that the journal entry was initially created. 232 * @param created the creation date-time or null to remove 233 * @return the property that was created 234 * @rfc 5545 p.136 235 */ 236 public Created setCreated(Date created) { 237 Created prop = (created == null) ? null : new Created(created); 238 setCreated(prop); 239 return prop; 240 } 241 242 /** 243 * Gets the date that the journal entry starts. 244 * @return the start date or null if not set 245 * @rfc 5545 p.97-8 246 */ 247 public DateStart getDateStart() { 248 return getProperty(DateStart.class); 249 } 250 251 /** 252 * Sets the date that the journal entry starts. 253 * @param dateStart the start date or null to remove 254 * @rfc 5545 p.97-8 255 */ 256 public void setDateStart(DateStart dateStart) { 257 setProperty(DateStart.class, dateStart); 258 } 259 260 /** 261 * Sets the date that the journal entry starts. 262 * @param dateStart the start date or null to remove 263 * @return the property that was created 264 * @rfc 5545 p.97-8 265 */ 266 public DateStart setDateStart(Date dateStart) { 267 DateStart prop = (dateStart == null) ? null : new DateStart(dateStart); 268 setDateStart(prop); 269 return prop; 270 } 271 272 /** 273 * Gets the date-time that the journal entry was last changed. 274 * @return the last modified date or null if not set 275 * @rfc 5545 p.138 276 */ 277 public LastModified getLastModified() { 278 return getProperty(LastModified.class); 279 } 280 281 /** 282 * Sets the date-time that the journal entry was last changed. 283 * @param lastModified the last modified date or null to remove 284 * @rfc 5545 p.138 285 */ 286 public void setLastModified(LastModified lastModified) { 287 setProperty(LastModified.class, lastModified); 288 } 289 290 /** 291 * Sets the date-time that the journal entry was last changed. 292 * @param lastModified the last modified date or null to remove 293 * @return the property that was created 294 * @rfc 5545 p.138 295 */ 296 public LastModified setLastModified(Date lastModified) { 297 LastModified prop = (lastModified == null) ? null : new LastModified(lastModified); 298 setLastModified(prop); 299 return prop; 300 } 301 302 /** 303 * Gets the organizer of the journal entry. 304 * @return the organizer or null if not set 305 * @rfc 5545 p.111-2 306 */ 307 public Organizer getOrganizer() { 308 return getProperty(Organizer.class); 309 } 310 311 /** 312 * Sets the organizer of the journal entry. 313 * @param organizer the organizer or null to remove 314 * @rfc 5545 p.111-2 315 */ 316 public void setOrganizer(Organizer organizer) { 317 setProperty(Organizer.class, organizer); 318 } 319 320 /** 321 * Sets the organizer of the journal entry. 322 * @param email the organizer's email address (e.g. "johndoe@example.com") 323 * or null to remove 324 * @return the property that was created 325 * @rfc 5545 p.111-2 326 */ 327 public Organizer setOrganizer(String email) { 328 Organizer prop = (email == null) ? null : Organizer.email(email); 329 setOrganizer(prop); 330 return prop; 331 } 332 333 /** 334 * Gets the original value of the {@link DateStart} property if the event is 335 * recurring and has been modified. Used in conjunction with the {@link Uid} 336 * and {@link Sequence} properties to uniquely identify a recurrence 337 * instance. 338 * @return the recurrence ID or null if not set 339 * @rfc 5545 p.112-4 340 */ 341 public RecurrenceId getRecurrenceId() { 342 return getProperty(RecurrenceId.class); 343 } 344 345 /** 346 * Sets the original value of the {@link DateStart} property if the event is 347 * recurring and has been modified. Used in conjunction with the {@link Uid} 348 * and {@link Sequence} properties to uniquely identify a recurrence 349 * instance. 350 * @param recurrenceId the recurrence ID or null to remove 351 * @rfc 5545 p.112-4 352 */ 353 public void setRecurrenceId(RecurrenceId recurrenceId) { 354 setProperty(RecurrenceId.class, recurrenceId); 355 } 356 357 /** 358 * Sets the original value of the {@link DateStart} property if the journal 359 * entry is recurring and has been modified. Used in conjunction with the 360 * {@link Uid} and {@link Sequence} properties to uniquely identify a 361 * recurrence instance. 362 * @param originalStartDate the original start date or null to remove 363 * @return the property that was created 364 * @rfc 5545 p.112-4 365 */ 366 public RecurrenceId setRecurrenceId(Date originalStartDate) { 367 RecurrenceId prop = (originalStartDate == null) ? null : new RecurrenceId(originalStartDate); 368 setRecurrenceId(prop); 369 return prop; 370 } 371 372 /** 373 * Gets the revision number of the journal entry. The organizer can 374 * increment this number every time he or she makes a significant change. 375 * @return the sequence number 376 * @rfc 5545 p.138-9 377 */ 378 public Sequence getSequence() { 379 return getProperty(Sequence.class); 380 } 381 382 /** 383 * Sets the revision number of the journal entry. The organizer can 384 * increment this number every time he or she makes a significant change. 385 * @param sequence the sequence number 386 * @rfc 5545 p.138-9 387 */ 388 public void setSequence(Sequence sequence) { 389 setProperty(Sequence.class, sequence); 390 } 391 392 /** 393 * Sets the revision number of the journal entry. The organizer can 394 * increment this number every time he or she makes a significant change. 395 * @param sequence the sequence number 396 * @return the property that was created 397 * @rfc 5545 p.138-9 398 */ 399 public Sequence setSequence(Integer sequence) { 400 Sequence prop = (sequence == null) ? null : new Sequence(sequence); 401 setSequence(prop); 402 return prop; 403 } 404 405 /** 406 * Increments the revision number of the journal entry. The organizer can 407 * increment this number every time he or she makes a significant change. 408 * @rfc 5545 p.138-9 409 */ 410 public void incrementSequence() { 411 Sequence sequence = getSequence(); 412 if (sequence == null) { 413 setSequence(1); 414 } else { 415 sequence.increment(); 416 } 417 } 418 419 /** 420 * Gets the status of the journal entry. 421 * @return the status or null if not set 422 * @rfc 5545 p.92-3 423 */ 424 public Status getStatus() { 425 return getProperty(Status.class); 426 } 427 428 /** 429 * Sets the status of the journal entry. 430 * <p> 431 * Valid journal status codes are: 432 * <ul> 433 * <li>DRAFT</li> 434 * <li>FINAL</li> 435 * <li>CANCELLED</li> 436 * </ul> 437 * </p> 438 * @param status the status or null to remove 439 * @rfc 5545 p.92-3 440 */ 441 public void setStatus(Status status) { 442 setProperty(Status.class, status); 443 } 444 445 /** 446 * Gets the summary of the journal entry. 447 * @return the summary or null if not set 448 * @rfc 5545 p.93-4 449 */ 450 public Summary getSummary() { 451 return getProperty(Summary.class); 452 } 453 454 /** 455 * Sets the summary of the journal entry. 456 * @param summary the summary or null to remove 457 * @rfc 5545 p.93-4 458 */ 459 public void setSummary(Summary summary) { 460 setProperty(Summary.class, summary); 461 } 462 463 /** 464 * Sets the summary of the journal entry. 465 * @param summary the summary or null to remove 466 * @return the property that was created 467 * @rfc 5545 p.93-4 468 */ 469 public Summary setSummary(String summary) { 470 Summary prop = (summary == null) ? null : new Summary(summary); 471 setSummary(prop); 472 return prop; 473 } 474 475 /** 476 * Gets a URL to a resource that contains additional information about the 477 * journal entry. 478 * @return the URL or null if not set 479 * @rfc 5545 p.116-7 480 */ 481 public Url getUrl() { 482 return getProperty(Url.class); 483 } 484 485 /** 486 * Sets a URL to a resource that contains additional information about the 487 * journal entry. 488 * @param url the URL or null to remove 489 * @rfc 5545 p.116-7 490 */ 491 public void setUrl(Url url) { 492 setProperty(Url.class, url); 493 } 494 495 /** 496 * Sets a URL to a resource that contains additional information about the 497 * journal entry. 498 * @param url the URL (e.g. "http://example.com/resource.ics") or null to 499 * remove 500 * @return the property that was created 501 * @rfc 5545 p.116-7 502 */ 503 public Url setUrl(String url) { 504 Url prop = (url == null) ? null : new Url(url); 505 setUrl(prop); 506 return prop; 507 } 508 509 /** 510 * Gets how often the journal entry repeats. 511 * @return the recurrence rule or null if not set 512 * @rfc 5545 p.122-32 513 */ 514 public RecurrenceRule getRecurrenceRule() { 515 return getProperty(RecurrenceRule.class); 516 } 517 518 /** 519 * Sets how often the journal entry repeats. 520 * @param recur the recurrence rule or null to remove 521 * @return the property that was created 522 * @rfc 5545 p.122-32 523 */ 524 public RecurrenceRule setRecurrenceRule(Recurrence recur) { 525 RecurrenceRule prop = (recur == null) ? null : new RecurrenceRule(recur); 526 setRecurrenceRule(prop); 527 return prop; 528 } 529 530 /** 531 * Sets how often the journal entry repeats. 532 * @param recurrenceRule the recurrence rule or null to remove 533 * @rfc 5545 p.122-32 534 */ 535 public void setRecurrenceRule(RecurrenceRule recurrenceRule) { 536 setProperty(RecurrenceRule.class, recurrenceRule); 537 } 538 539 /** 540 * Gets any attachments that are associated with the journal entry. 541 * @return the attachments 542 * @rfc 5545 p.80-1 543 */ 544 public List<Attachment> getAttachments() { 545 return getProperties(Attachment.class); 546 } 547 548 /** 549 * Adds an attachment to the journal entry. 550 * @param attachment the attachment to add 551 * @rfc 5545 p.80-1 552 */ 553 public void addAttachment(Attachment attachment) { 554 addProperty(attachment); 555 } 556 557 /** 558 * Gets the people who are involved in the journal entry. 559 * @return the attendees 560 * @rfc 5545 p.107-9 561 */ 562 public List<Attendee> getAttendees() { 563 return getProperties(Attendee.class); 564 } 565 566 /** 567 * Adds a person who is involved in the journal entry. 568 * @param attendee the attendee 569 * @rfc 5545 p.107-9 570 */ 571 public void addAttendee(Attendee attendee) { 572 addProperty(attendee); 573 } 574 575 /** 576 * Adds a person who is involved in the journal entry. 577 * @param email the attendee's email address 578 * @return the property that was created 579 * @rfc 5545 p.107-9 580 */ 581 public Attendee addAttendee(String email) { 582 Attendee prop = Attendee.email(email); 583 addAttendee(prop); 584 return prop; 585 } 586 587 /** 588 * Gets a list of "tags" or "keywords" that describe the journal entry. 589 * @return the categories 590 * @rfc 5545 p.81-2 591 */ 592 public List<Categories> getCategories() { 593 return getProperties(Categories.class); 594 } 595 596 /** 597 * Adds a list of "tags" or "keywords" that describe the journal entry. Note 598 * that a single property can hold multiple keywords. 599 * @param categories the categories to add 600 * @rfc 5545 p.81-2 601 */ 602 public void addCategories(Categories categories) { 603 addProperty(categories); 604 } 605 606 /** 607 * Adds a list of "tags" or "keywords" that describe the journal entry. 608 * @param categories the categories to add 609 * @return the property that was created 610 * @rfc 5545 p.81-2 611 */ 612 public Categories addCategories(String... categories) { 613 Categories prop = new Categories(categories); 614 addCategories(prop); 615 return prop; 616 } 617 618 /** 619 * Adds a list of "tags" or "keywords" that describe the journal entry. 620 * @param categories the categories to add 621 * @return the property that was created 622 * @rfc 5545 p.81-2 623 */ 624 public Categories addCategories(List<String> categories) { 625 Categories prop = new Categories(categories); 626 addCategories(prop); 627 return prop; 628 } 629 630 /** 631 * Gets the comments attached to the journal entry. 632 * @return the comments 633 * @rfc 5545 p.83-4 634 */ 635 public List<Comment> getComments() { 636 return getProperties(Comment.class); 637 } 638 639 /** 640 * Adds a comment to the journal entry. 641 * @param comment the comment to add 642 * @rfc 5545 p.83-4 643 */ 644 public void addComment(Comment comment) { 645 addProperty(comment); 646 } 647 648 /** 649 * Adds a comment to the journal entry. 650 * @param comment the comment to add 651 * @return the property that was created 652 * @rfc 5545 p.83-4 653 */ 654 public Comment addComment(String comment) { 655 Comment prop = new Comment(comment); 656 addComment(prop); 657 return prop; 658 } 659 660 /** 661 * Gets the contacts associated with the journal entry. 662 * @return the contacts 663 * @rfc 5545 p.109-11 664 */ 665 public List<Contact> getContacts() { 666 return getProperties(Contact.class); 667 } 668 669 /** 670 * Adds a contact to the journal entry. 671 * @param contact the contact 672 * @rfc 5545 p.109-11 673 */ 674 public void addContact(Contact contact) { 675 addProperty(contact); 676 } 677 678 /** 679 * Adds a contact to the journal entry. 680 * @param contact the contact (e.g. "ACME Co - (123) 555-1234") 681 * @return the property that was created 682 * @rfc 5545 p.109-11 683 */ 684 public Contact addContact(String contact) { 685 Contact prop = new Contact(contact); 686 addContact(prop); 687 return prop; 688 } 689 690 /** 691 * Gets the detailed descriptions to the journal entry. The descriptions 692 * should be a more detailed version of the one provided by the 693 * {@link Summary} property. 694 * @return the descriptions 695 * @rfc 5545 p.84-5 696 */ 697 public List<Description> getDescriptions() { 698 return getProperties(Description.class); 699 } 700 701 /** 702 * Adds a detailed description to the journal entry. The description should 703 * be a more detailed version of the one provided by the {@link Summary} 704 * property. 705 * @param description the description 706 * @rfc 5545 p.84-5 707 */ 708 public void addDescription(Description description) { 709 addProperty(description); 710 } 711 712 /** 713 * Adds a detailed description to the journal entry. The description should 714 * be a more detailed version of the one provided by the {@link Summary} 715 * property. 716 * @param description the description 717 * @return the property that was created 718 * @rfc 5545 p.84-5 719 */ 720 public Description addDescription(String description) { 721 Description prop = new Description(description); 722 addDescription(prop); 723 return prop; 724 } 725 726 /** 727 * Gets the list of exceptions to the recurrence rule defined in the journal 728 * entry (if one is defined). 729 * @return the list of exceptions 730 * @rfc 5545 p.118-20 731 */ 732 public List<ExceptionDates> getExceptionDates() { 733 return getProperties(ExceptionDates.class); 734 } 735 736 /** 737 * Adds a list of exceptions to the recurrence rule defined in the journal 738 * entry (if one is defined). Note that this property can contain multiple 739 * dates. 740 * @param exceptionDates the list of exceptions 741 * @rfc 5545 p.118-20 742 */ 743 public void addExceptionDates(ExceptionDates exceptionDates) { 744 addProperty(exceptionDates); 745 } 746 747 /** 748 * Gets the components that the journal entry is related to. 749 * @return the relationships 750 * @rfc 5545 p.115-6 751 */ 752 public List<RelatedTo> getRelatedTo() { 753 return getProperties(RelatedTo.class); 754 } 755 756 /** 757 * Adds a component that the journal entry is related to. 758 * @param relatedTo the relationship 759 * @rfc 5545 p.115-6 760 */ 761 public void addRelatedTo(RelatedTo relatedTo) { 762 //TODO create a method that accepts a component and make the RelatedTo property invisible to the user 763 //@formatter:off 764 /* 765 * addRelation(RelationshipType relType, ICalComponent component){ 766 * RelatedTo prop = new RelatedTo(component.getUid().getValue()); 767 * prop.setRelationshipType(relType); 768 * addProperty(prop); 769 * } 770 */ 771 //@formatter:on 772 addProperty(relatedTo); 773 } 774 775 /** 776 * Adds a component that the journal entry is related to. 777 * @param uid the UID of the other component 778 * @return the property that was created 779 * @rfc 5545 p.115-6 780 */ 781 public RelatedTo addRelatedTo(String uid) { 782 RelatedTo prop = new RelatedTo(uid); 783 addRelatedTo(prop); 784 return prop; 785 } 786 787 /** 788 * Gets the list of dates/periods that help define the recurrence rule of 789 * this journal entry (if one is defined). 790 * @return the recurrence dates 791 * @rfc 5545 p.120-2 792 */ 793 public List<RecurrenceDates> getRecurrenceDates() { 794 return getProperties(RecurrenceDates.class); 795 } 796 797 /** 798 * Adds a list of dates/periods that help define the recurrence rule of this 799 * journal entry (if one is defined). 800 * @param recurrenceDates the recurrence dates 801 * @rfc 5545 p.120-2 802 */ 803 public void addRecurrenceDates(RecurrenceDates recurrenceDates) { 804 addProperty(recurrenceDates); 805 } 806 807 /** 808 * Gets the response to a scheduling request. 809 * @return the response 810 * @rfc 5545 p.141-3 811 */ 812 public RequestStatus getRequestStatus() { 813 return getProperty(RequestStatus.class); 814 } 815 816 /** 817 * Sets the response to a scheduling request. 818 * @param requestStatus the response 819 * @rfc 5545 p.141-3 820 */ 821 public void setRequestStatus(RequestStatus requestStatus) { 822 setProperty(RequestStatus.class, requestStatus); 823 } 824 825 /** 826 * <p> 827 * Gets the exceptions for the {@link RecurrenceRule} property. 828 * </p> 829 * <p> 830 * Note that this property has been removed from the latest version of the 831 * iCal specification. Its use should be avoided. 832 * </p> 833 * @return the exception rules 834 * @rfc 2445 p.114-15 835 */ 836 public List<ExceptionRule> getExceptionRules() { 837 return getProperties(ExceptionRule.class); 838 } 839 840 /** 841 * <p> 842 * Adds an exception for the {@link RecurrenceRule} property. 843 * </p> 844 * <p> 845 * Note that this property has been removed from the latest version of the 846 * iCal specification. Its use should be avoided. 847 * </p> 848 * @param recur the exception rule to add 849 * @return the property that was created 850 * @rfc 2445 p.114-15 851 */ 852 public ExceptionRule addExceptionRule(Recurrence recur) { 853 ExceptionRule prop = (recur == null) ? null : new ExceptionRule(recur); 854 addExceptionRule(prop); 855 return prop; 856 } 857 858 /** 859 * <p> 860 * Adds an exception for the {@link RecurrenceRule} property. 861 * </p> 862 * <p> 863 * Note that this property has been removed from the latest version of the 864 * iCal specification. Its use should be avoided. 865 * </p> 866 * @param exceptionRule the exception rule to add 867 * @rfc 2445 p.114-15 868 */ 869 public void addExceptionRule(ExceptionRule exceptionRule) { 870 addProperty(exceptionRule); 871 } 872 873 @SuppressWarnings("unchecked") 874 @Override 875 protected void validate(List<ICalComponent> components, List<String> warnings) { 876 checkRequiredCardinality(warnings, Uid.class, DateTimeStamp.class); 877 checkOptionalCardinality(warnings, Classification.class, Created.class, DateStart.class, LastModified.class, Organizer.class, RecurrenceId.class, Sequence.class, Status.class, Summary.class, Url.class); 878 879 Status status = getStatus(); 880 if (status != null && (status.isTentative() || status.isConfirmed() || status.isNeedsAction() || status.isCompleted() || status.isInProgress())) { 881 warnings.add("Invalid status value (\"" + status.getValue() + "\"). Valid status values are \"draft\", \"final\", and \"cancelled\"."); 882 } 883 884 RecurrenceId recurrenceId = getRecurrenceId(); 885 DateStart dateStart = getDateStart(); 886 if (recurrenceId != null && dateStart != null && dateStart.hasTime() != recurrenceId.hasTime()) { 887 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 datetimes)."); 888 } 889 890 //RFC 5545 p. 167 891 RecurrenceRule rrule = getRecurrenceRule(); 892 if (dateStart != null && rrule != null) { 893 Date start = dateStart.getValue(); 894 Recurrence recur = rrule.getValue(); 895 if (start != null && recur != null) { 896 if (!dateStart.hasTime() && (!recur.getByHour().isEmpty() || !recur.getByMinute().isEmpty() || !recur.getBySecond().isEmpty())) { 897 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)."); 898 } 899 } 900 } 901 902 //RFC 5545 p. 167 903 if (getProperties(RecurrenceRule.class).size() > 1) { 904 warnings.add("There should be only one instance of the " + RecurrenceRule.class.getSimpleName() + " property."); 905 } 906 } 907 }