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 }