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