diff -r 000000000000 -r fb9019fb1bf7 src/net/fortuna/ical4j/model/component/VJournal.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/net/fortuna/ical4j/model/component/VJournal.java Tue Feb 10 18:12:00 2015 +0100 @@ -0,0 +1,543 @@ +/** + * Copyright (c) 2012, Ben Fortuna + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * o Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * o Neither the name of Ben Fortuna nor the names of any other contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.fortuna.ical4j.model.component; + +import java.util.HashMap; +import java.util.Map; + +import net.fortuna.ical4j.model.Date; +import net.fortuna.ical4j.model.Property; +import net.fortuna.ical4j.model.PropertyList; +import net.fortuna.ical4j.model.ValidationException; +import net.fortuna.ical4j.model.Validator; +import net.fortuna.ical4j.model.property.Clazz; +import net.fortuna.ical4j.model.property.Created; +import net.fortuna.ical4j.model.property.Description; +import net.fortuna.ical4j.model.property.DtStamp; +import net.fortuna.ical4j.model.property.DtStart; +import net.fortuna.ical4j.model.property.LastModified; +import net.fortuna.ical4j.model.property.Method; +import net.fortuna.ical4j.model.property.Organizer; +import net.fortuna.ical4j.model.property.RecurrenceId; +import net.fortuna.ical4j.model.property.Sequence; +import net.fortuna.ical4j.model.property.Status; +import net.fortuna.ical4j.model.property.Summary; +import net.fortuna.ical4j.model.property.Uid; +import net.fortuna.ical4j.model.property.Url; +import net.fortuna.ical4j.util.CompatibilityHints; +import net.fortuna.ical4j.util.PropertyValidator; + +/** + * $Id$ [Apr 5, 2004] + * + * Defines an iCalendar VJOURNAL component. + * + *
+ * 4.6.3 Journal Component + * + * Component Name: VJOURNAL + * + * Purpose: Provide a grouping of component properties that describe a + * journal entry. + * + * Formal Definition: A "VJOURNAL" calendar component is defined by the + * following notation: + * + * journalc = "BEGIN" ":" "VJOURNAL" CRLF + * jourprop + * "END" ":" "VJOURNAL" CRLF + * + * jourprop = *( + * + * ; the following are optional, + * ; but MUST NOT occur more than once + * + * class / created / description / dtstart / dtstamp / + * last-mod / organizer / recurid / seq / status / + * summary / uid / url / + * + * ; the following are optional, + * ; and MAY occur more than once + * + * attach / attendee / categories / comment / + * contact / exdate / exrule / related / rdate / + * rrule / rstatus / x-prop + * + * ) + *+ * + * Example 1 - Creating a journal associated with an event: + * + *
+ * DtStart meetingDate = (DtStart) meeting.getProperties().getProperty(
+ * Property.DTSTART);
+ *
+ * VJournal minutes = new VJournal(meetingDate.getTime(),
+ * "Progress Meeting - Minutes");
+ *
+ * // add timezone information..
+ * TzId tzParam = meetingDate.getParameters().getParmaeter(Parameter.TZID);
+ * minutes.getProperties().getProperty(Property.DTSTART).getParameters().add(
+ * tzParam);
+ *
+ * // add description..
+ * minutes.getProperties().add(new Description("1. Agenda.., 2. Action Items.."));
+ *
+ *
+ * @author Ben Fortuna
+ */
+public class VJournal extends CalendarComponent {
+
+ private static final long serialVersionUID = -7635140949183238830L;
+
+ private final Map methodValidators = new HashMap();
+ {
+ methodValidators.put(Method.ADD, new AddValidator());
+ methodValidators.put(Method.CANCEL, new CancelValidator());
+ methodValidators.put(Method.PUBLISH, new PublishValidator());
+ }
+
+ /**
+ * Default constructor.
+ */
+ public VJournal() {
+ super(VJOURNAL);
+ getProperties().add(new DtStamp());
+ }
+
+ /**
+ * Constructor.
+ * @param properties a list of properties
+ */
+ public VJournal(final PropertyList properties) {
+ super(VJOURNAL, properties);
+ }
+
+ /**
+ * Constructs a new VJOURNAL instance associated with the specified time with the specified summary.
+ * @param start the date the journal entry is associated with
+ * @param summary the journal summary
+ */
+ public VJournal(final Date start, final String summary) {
+ this();
+ getProperties().add(new DtStart(start));
+ getProperties().add(new Summary(summary));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void validate(final boolean recurse)
+ throws ValidationException {
+
+ if (!CompatibilityHints
+ .isHintEnabled(CompatibilityHints.KEY_RELAXED_VALIDATION)) {
+
+ // From "4.8.4.7 Unique Identifier":
+ // Conformance: The property MUST be specified in the "VEVENT", "VTODO",
+ // "VJOURNAL" or "VFREEBUSY" calendar components.
+ PropertyValidator.getInstance().assertOne(Property.UID,
+ getProperties());
+
+ // From "4.8.7.2 Date/Time Stamp":
+ // Conformance: This property MUST be included in the "VEVENT", "VTODO",
+ // "VJOURNAL" or "VFREEBUSY" calendar components.
+ PropertyValidator.getInstance().assertOne(Property.DTSTAMP,
+ getProperties());
+ }
+
+ /*
+ * ; the following are optional, ; but MUST NOT occur more than once class / created / description / dtstart /
+ * dtstamp / last-mod / organizer / recurid / seq / status / summary / uid / url /
+ */
+ PropertyValidator.getInstance().assertOneOrLess(Property.CLASS,
+ getProperties());
+ PropertyValidator.getInstance().assertOneOrLess(Property.CREATED,
+ getProperties());
+ PropertyValidator.getInstance().assertOneOrLess(Property.DESCRIPTION,
+ getProperties());
+ PropertyValidator.getInstance().assertOneOrLess(Property.DTSTART,
+ getProperties());
+ PropertyValidator.getInstance().assertOneOrLess(Property.DTSTAMP,
+ getProperties());
+ PropertyValidator.getInstance().assertOneOrLess(Property.LAST_MODIFIED,
+ getProperties());
+ PropertyValidator.getInstance().assertOneOrLess(Property.ORGANIZER,
+ getProperties());
+ PropertyValidator.getInstance().assertOneOrLess(Property.RECURRENCE_ID,
+ getProperties());
+ PropertyValidator.getInstance().assertOneOrLess(Property.SEQUENCE,
+ getProperties());
+ PropertyValidator.getInstance().assertOneOrLess(Property.STATUS,
+ getProperties());
+ PropertyValidator.getInstance().assertOneOrLess(Property.SUMMARY,
+ getProperties());
+ PropertyValidator.getInstance().assertOneOrLess(Property.UID,
+ getProperties());
+ PropertyValidator.getInstance().assertOneOrLess(Property.URL,
+ getProperties());
+
+ final Status status = (Status) getProperty(Property.STATUS);
+ if (status != null && !Status.VJOURNAL_DRAFT.getValue().equals(status.getValue())
+ && !Status.VJOURNAL_FINAL.getValue().equals(status.getValue())
+ && !Status.VJOURNAL_CANCELLED.getValue().equals(status.getValue())) {
+ throw new ValidationException("Status property ["
+ + status.toString() + "] may not occur in VJOURNAL");
+ }
+
+ /*
+ * ; the following are optional, ; and MAY occur more than once attach / attendee / categories / comment /
+ * contact / exdate / exrule / related / rdate / rrule / rstatus / x-prop
+ */
+
+ if (recurse) {
+ validateProperties();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected Validator getValidator(Method method) {
+ return (Validator) methodValidators.get(method);
+ }
+
+ /**
+ * + * Component/Property Presence + * ------------------- ---------------------------------------------- + * METHOD 1 MUST be "ADD" + * VJOURNAL 1 + * DESCRIPTION 1 Can be null. + * DTSTAMP 1 + * DTSTART 1 + * ORGANIZER 1 + * SEQUENCE 1 MUST be greater than 0 + * UID 1 MUST match that of the original journal + * + * ATTACH 0+ + * CATEGORIES 0 or 1 This property MAY contain a list of values + * CLASS 0 or 1 + * COMMENT 0 or 1 + * CONTACT 0+ + * CREATED 0 or 1 + * EXDATE 0+ + * EXRULE 0+ + * LAST-MODIFIED 0 or 1 + * RDATE 0+ + * RELATED-TO 0+ + * RRULE 0+ + * STATUS 0 or 1 MAY be one of DRAFT/FINAL/CANCELLED + * SUMMARY 0 or 1 Can be null + * URL 0 or 1 + * X-PROPERTY 0+ + * + * ATTENDEE 0 + * RECURRENCE-ID 0 + * + * VALARM 0+ + * VTIMEZONE 0 or 1 MUST be present if any date/time refers to + * a timezone + * X-COMPONENT 0+ + * + * VEVENT 0 + * VFREEBUSY 0 + * VTODO 0 + *+ * + */ + private class AddValidator implements Validator { + + private static final long serialVersionUID = 1L; + + public void validate() throws ValidationException { + PropertyValidator.getInstance().assertOne(Property.DESCRIPTION, getProperties()); + PropertyValidator.getInstance().assertOne(Property.DTSTAMP, getProperties()); + PropertyValidator.getInstance().assertOne(Property.DTSTART, getProperties()); + PropertyValidator.getInstance().assertOne(Property.ORGANIZER, getProperties()); + PropertyValidator.getInstance().assertOne(Property.SEQUENCE, getProperties()); + PropertyValidator.getInstance().assertOne(Property.UID, getProperties()); + + PropertyValidator.getInstance().assertOneOrLess(Property.CATEGORIES, getProperties()); + PropertyValidator.getInstance().assertOneOrLess(Property.CLASS, getProperties()); + PropertyValidator.getInstance().assertOneOrLess(Property.COMMENT, getProperties()); + PropertyValidator.getInstance().assertOneOrLess(Property.CREATED, getProperties()); + PropertyValidator.getInstance().assertOneOrLess(Property.LAST_MODIFIED, getProperties()); + PropertyValidator.getInstance().assertOneOrLess(Property.STATUS, getProperties()); + PropertyValidator.getInstance().assertOneOrLess(Property.SUMMARY, getProperties()); + PropertyValidator.getInstance().assertOneOrLess(Property.URL, getProperties()); + + PropertyValidator.getInstance().assertNone(Property.ATTENDEE, getProperties()); + PropertyValidator.getInstance().assertNone(Property.RECURRENCE_ID, getProperties()); + } + } + + /** + *
+ * Component/Property Presence + * ------------------- --------------------------------------------- + * METHOD 1 MUST be "CANCEL" + * VJOURNAL 1+ All MUST have the same UID + * DTSTAMP 1 + * ORGANIZER 1 + * SEQUENCE 1 + * UID 1 MUST be the UID of the original REQUEST + * + * ATTACH 0+ + * ATTENDEE 0+ + * CATEGORIES 0 or 1 This property MAY contain a list of values + * CLASS 0 or 1 + * COMMENT 0 or 1 + * CONTACT 0+ + * CREATED 0 or 1 + * DESCRIPTION 0 or 1 + * DTSTART 0 or 1 + * EXDATE 0+ + * EXRULE 0+ + * LAST-MODIFIED 0 or 1 + * RDATE 0+ + * RECURRENCE-ID 0 or 1 only if referring to an instance of a + * recurring calendar component. Otherwise + * it MUST NOT be present. + * RELATED-TO 0+ + * RRULE 0+ + * STATUS 0 or 1 MAY be present, must be "CANCELLED" if + * present + * SUMMARY 0 or 1 + * URL 0 or 1 + * X-PROPERTY 0+ + * + * REQUEST-STATUS 0 + * + * VTIMEZONE 0+ MUST be present if any date/time refers to + * a timezone + * X-COMPONENT 0+ + * VALARM 0 + * VEVENT 0 + * VFREEBUSY 0 + * VTODO 0 + *+ * + */ + private class CancelValidator implements Validator { + + private static final long serialVersionUID = 1L; + + public void validate() throws ValidationException { + PropertyValidator.getInstance().assertOne(Property.DTSTAMP, getProperties()); + PropertyValidator.getInstance().assertOne(Property.ORGANIZER, getProperties()); + PropertyValidator.getInstance().assertOne(Property.SEQUENCE, getProperties()); + PropertyValidator.getInstance().assertOne(Property.UID, getProperties()); + + PropertyValidator.getInstance().assertOneOrLess(Property.CATEGORIES, getProperties()); + PropertyValidator.getInstance().assertOneOrLess(Property.CLASS, getProperties()); + PropertyValidator.getInstance().assertOneOrLess(Property.COMMENT, getProperties()); + PropertyValidator.getInstance().assertOneOrLess(Property.CREATED, getProperties()); + PropertyValidator.getInstance().assertOneOrLess(Property.DESCRIPTION, getProperties()); + PropertyValidator.getInstance().assertOneOrLess(Property.DTSTART, getProperties()); + PropertyValidator.getInstance().assertOneOrLess(Property.LAST_MODIFIED, getProperties()); + PropertyValidator.getInstance().assertOneOrLess(Property.RECURRENCE_ID, getProperties()); + PropertyValidator.getInstance().assertOneOrLess(Property.STATUS, getProperties()); + PropertyValidator.getInstance().assertOneOrLess(Property.SUMMARY, getProperties()); + PropertyValidator.getInstance().assertOneOrLess(Property.URL, getProperties()); + + PropertyValidator.getInstance().assertNone(Property.REQUEST_STATUS, getProperties()); + } + } + + /** + *
+ * Component/Property Presence + * ------------------- ---------------------------------------------- + * METHOD 1 MUST be "PUBLISH" + * VJOURNAL 1+ + * DESCRIPTION 1 Can be null. + * DTSTAMP 1 + * DTSTART 1 + * ORGANIZER 1 + * UID 1 + * + * ATTACH 0+ + * CATEGORIES 0 or 1 This property MAY contain a list of values + * CLASS 0 or 1 + * COMMENT 0 or 1 + * CONTACT 0+ + * CREATED 0 or 1 + * EXDATE 0+ + * EXRULE 0+ + * LAST-MODIFIED 0 or 1 + * RDATE 0+ + * RECURRENCE-ID 0 or 1 MUST only if referring to an instance of a + * recurring calendar component. Otherwise + * it MUST NOT be present. + * RELATED-TO 0+ + * RRULE 0+ + * SEQUENCE 0 or 1 MUST echo the original SEQUENCE number. + * MUST be present if non-zero. MAY be + * present if zero. + * STATUS 0 or 1 MAY be one of DRAFT/FINAL/CANCELLED + * SUMMARY 0 or 1 Can be null + * URL 0 or 1 + * X-PROPERTY 0+ + * + * ATTENDEE 0 + * + * VALARM 0+ + * VTIMEZONE 0+ MUST be present if any date/time refers to + * a timezone + * X-COMPONENT 0+ + * + * VEVENT 0 + * VFREEBUSY 0 + * VTODO 0 + *+ * + */ + private class PublishValidator implements Validator { + + private static final long serialVersionUID = 1L; + + public void validate() throws ValidationException { + PropertyValidator.getInstance().assertOne(Property.DESCRIPTION, getProperties()); + PropertyValidator.getInstance().assertOne(Property.DTSTAMP, getProperties()); + PropertyValidator.getInstance().assertOne(Property.DTSTART, getProperties()); + PropertyValidator.getInstance().assertOne(Property.ORGANIZER, getProperties()); + PropertyValidator.getInstance().assertOne(Property.UID, getProperties()); + + PropertyValidator.getInstance().assertOneOrLess(Property.CATEGORIES, getProperties()); + PropertyValidator.getInstance().assertOneOrLess(Property.CLASS, getProperties()); + PropertyValidator.getInstance().assertOneOrLess(Property.COMMENT, getProperties()); + PropertyValidator.getInstance().assertOneOrLess(Property.CREATED, getProperties()); + PropertyValidator.getInstance().assertOneOrLess(Property.LAST_MODIFIED, getProperties()); + PropertyValidator.getInstance().assertOneOrLess(Property.RECURRENCE_ID, getProperties()); + PropertyValidator.getInstance().assertOneOrLess(Property.SEQUENCE, getProperties()); + PropertyValidator.getInstance().assertOneOrLess(Property.STATUS, getProperties()); + PropertyValidator.getInstance().assertOneOrLess(Property.SUMMARY, getProperties()); + PropertyValidator.getInstance().assertOneOrLess(Property.URL, getProperties()); + + PropertyValidator.getInstance().assertNone(Property.ATTENDEE, getProperties()); + } + } + + /** + * @return the optional access classification property for a journal entry + */ + public final Clazz getClassification() { + return (Clazz) getProperty(Property.CLASS); + } + + /** + * @return the optional creation-time property for a journal entry + */ + public final Created getCreated() { + return (Created) getProperty(Property.CREATED); + } + + /** + * @return the optional description property for a journal entry + */ + public final Description getDescription() { + return (Description) getProperty(Property.DESCRIPTION); + } + + /** + * Convenience method to pull the DTSTART out of the property list. + * @return The DtStart object representation of the start Date + */ + public final DtStart getStartDate() { + return (DtStart) getProperty(Property.DTSTART); + } + + /** + * @return the optional last-modified property for a journal entry + */ + public final LastModified getLastModified() { + return (LastModified) getProperty(Property.LAST_MODIFIED); + } + + /** + * @return the optional organizer property for a journal entry + */ + public final Organizer getOrganizer() { + return (Organizer) getProperty(Property.ORGANIZER); + } + + /** + * @return the optional date-stamp property + */ + public final DtStamp getDateStamp() { + return (DtStamp) getProperty(Property.DTSTAMP); + } + + /** + * @return the optional sequence number property for a journal entry + */ + public final Sequence getSequence() { + return (Sequence) getProperty(Property.SEQUENCE); + } + + /** + * @return the optional status property for a journal entry + */ + public final Status getStatus() { + return (Status) getProperty(Property.STATUS); + } + + /** + * @return the optional summary property for a journal entry + */ + public final Summary getSummary() { + return (Summary) getProperty(Property.SUMMARY); + } + + /** + * @return the optional URL property for a journal entry + */ + public final Url getUrl() { + return (Url) getProperty(Property.URL); + } + + /** + * @return the optional recurrence identifier property for a journal entry + */ + public final RecurrenceId getRecurrenceId() { + return (RecurrenceId) getProperty(Property.RECURRENCE_ID); + } + + /** + * Returns the UID property of this component if available. + * @return a Uid instance, or null if no UID property exists + */ + public final Uid getUid() { + return (Uid) getProperty(Property.UID); + } +}