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