diff -r 000000000000 -r fb9019fb1bf7 src/net/fortuna/ical4j/model/component/VAlarm.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/net/fortuna/ical4j/model/component/VAlarm.java Tue Feb 10 18:12:00 2015 +0100 @@ -0,0 +1,468 @@ +/** + * 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.DateTime; +import net.fortuna.ical4j.model.Dur; +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.Action; +import net.fortuna.ical4j.model.property.Attach; +import net.fortuna.ical4j.model.property.Description; +import net.fortuna.ical4j.model.property.Duration; +import net.fortuna.ical4j.model.property.Method; +import net.fortuna.ical4j.model.property.Repeat; +import net.fortuna.ical4j.model.property.Summary; +import net.fortuna.ical4j.model.property.Trigger; +import net.fortuna.ical4j.util.PropertyValidator; + +/** + * $Id$ [Apr 5, 2004] + * + * Defines an iCalendar VALARM component. + * + *
+ * 4.6.6 Alarm Component + * + * Component Name: VALARM + * + * Purpose: Provide a grouping of component properties that define an + * alarm. + * + * Formal Definition: A "VALARM" calendar component is defined by the + * following notation: + * + * alarmc = "BEGIN" ":" "VALARM" CRLF + * (audioprop / dispprop / emailprop / procprop) + * "END" ":" "VALARM" CRLF + * + * audioprop = 2*( + * + * ; 'action' and 'trigger' are both REQUIRED, + * ; but MUST NOT occur more than once + * + * action / trigger / + * + * ; 'duration' and 'repeat' are both optional, + * ; and MUST NOT occur more than once each, + * ; but if one occurs, so MUST the other + * + * duration / repeat / + * + * ; the following is optional, + * ; but MUST NOT occur more than once + * + * attach / + * + * ; the following is optional, + * ; and MAY occur more than once + * + * x-prop + * + * ) + * + * + * + * dispprop = 3*( + * + * ; the following are all REQUIRED, + * ; but MUST NOT occur more than once + * + * action / description / trigger / + * + * ; 'duration' and 'repeat' are both optional, + * ; and MUST NOT occur more than once each, + * ; but if one occurs, so MUST the other + * + * duration / repeat / + * + * ; the following is optional, + * ; and MAY occur more than once + * + * *x-prop + * + * ) + * + * + * + * emailprop = 5*( + * + * ; the following are all REQUIRED, + * ; but MUST NOT occur more than once + * + * action / description / trigger / summary + * + * ; the following is REQUIRED, + * ; and MAY occur more than once + * + * attendee / + * + * ; 'duration' and 'repeat' are both optional, + * ; and MUST NOT occur more than once each, + * ; but if one occurs, so MUST the other + * + * duration / repeat / + * + * ; the following are optional, + * ; and MAY occur more than once + * + * attach / x-prop + * + * ) + * + * + * + * procprop = 3*( + * + * ; the following are all REQUIRED, + * ; but MUST NOT occur more than once + * + * action / attach / trigger / + * + * ; 'duration' and 'repeat' are both optional, + * ; and MUST NOT occur more than once each, + * ; but if one occurs, so MUST the other + * + * duration / repeat / + * + * ; 'description' is optional, + * ; and MUST NOT occur more than once + * + * description / + * + * ; the following is optional, + * ; and MAY occur more than once + * + * x-prop + * + * ) + *+ * + * Example 1 - Creating an alarm to trigger at a specific time: + * + *
+ * java.util.Calendar cal = java.util.Calendar.getInstance();
+ * cal.set(java.util.Calendar.MONTH, java.util.Calendar.DECEMBER);
+ * cal.set(java.util.Calendar.DAY_OF_MONTH, 25);
+ *
+ * VAlarm christmas = new VAlarm(cal.getTime());
+ *
+ *
+ * Example 2 - Creating an alarm to trigger one (1) hour before the scheduled start of the parent event/the parent todo
+ * is due:
+ *
+ *
+ * VAlarm reminder = new VAlarm(new Dur(0, -1, 0, 0));
+ *
+ * // repeat reminder four (4) more times every fifteen (15) minutes..
+ * reminder.getProperties().add(new Repeat(4));
+ * reminder.getProperties().add(new Duration(new Dur(0, 0, 15, 0)));
+ *
+ * // display a message..
+ * reminder.getProperties().add(Action.DISPLAY);
+ * reminder.getProperties().add(new Description("Progress Meeting at 9:30am"));
+ *
+ *
+ * @author Ben Fortuna
+ */
+public class VAlarm extends CalendarComponent {
+
+ private static final long serialVersionUID = -8193965477414653802L;
+
+ private final Map actionValidators = new HashMap();
+ {
+ actionValidators.put(Action.AUDIO, new AudioValidator());
+ actionValidators.put(Action.DISPLAY, new DisplayValidator());
+ actionValidators.put(Action.EMAIL, new EmailValidator());
+ actionValidators.put(Action.PROCEDURE, new ProcedureValidator());
+ }
+
+ private final Validator itipValidator = new ITIPValidator();
+
+ /**
+ * Default constructor.
+ */
+ public VAlarm() {
+ super(VALARM);
+ }
+
+ /**
+ * Constructor.
+ * @param properties a list of properties
+ */
+ public VAlarm(final PropertyList properties) {
+ super(VALARM, properties);
+ }
+
+ /**
+ * Constructs a new VALARM instance that will trigger at the specified time.
+ * @param trigger the time the alarm will trigger
+ */
+ public VAlarm(final DateTime trigger) {
+ this();
+ getProperties().add(new Trigger(trigger));
+ }
+
+ /**
+ * Constructs a new VALARM instance that will trigger at the specified time relative to the event/todo component.
+ * @param trigger a duration of time relative to the parent component that the alarm will trigger at
+ */
+ public VAlarm(final Dur trigger) {
+ this();
+ getProperties().add(new Trigger(trigger));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void validate(final boolean recurse)
+ throws ValidationException {
+
+ /*
+ * ; 'action' and 'trigger' are both REQUIRED, ; but MUST NOT occur more than once action / trigger /
+ */
+ PropertyValidator.getInstance().assertOne(Property.ACTION, getProperties());
+ PropertyValidator.getInstance().assertOne(Property.TRIGGER, getProperties());
+
+ /*
+ * ; 'duration' and 'repeat' are both optional, ; and MUST NOT occur more than once each, ; but if one occurs,
+ * so MUST the other duration / repeat /
+ */
+ PropertyValidator.getInstance().assertOneOrLess(Property.DURATION, getProperties());
+ PropertyValidator.getInstance().assertOneOrLess(Property.REPEAT, getProperties());
+
+ try {
+ PropertyValidator.getInstance().assertNone(Property.DURATION, getProperties());
+ PropertyValidator.getInstance().assertNone(Property.REPEAT, getProperties());
+ }
+ catch (ValidationException ve) {
+ PropertyValidator.getInstance().assertOne(Property.DURATION, getProperties());
+ PropertyValidator.getInstance().assertOne(Property.REPEAT, getProperties());
+ }
+
+ /*
+ * ; the following is optional, ; and MAY occur more than once x-prop
+ */
+
+ final Validator actionValidator = (Validator) actionValidators.get(getAction());
+ if (actionValidator != null) {
+ actionValidator.validate();
+ }
+
+ if (recurse) {
+ validateProperties();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected Validator getValidator(Method method) {
+ return itipValidator;
+ }
+
+ private class AudioValidator implements Validator {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * {@inheritDoc}
+ */
+ public void validate() throws ValidationException {
+ /*
+ * ; the following is optional, ; but MUST NOT occur more than once attach /
+ */
+ PropertyValidator.getInstance().assertOneOrLess(Property.ATTACH, getProperties());
+ }
+ }
+
+ private class DisplayValidator implements Validator {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * {@inheritDoc}
+ */
+ public void validate() throws ValidationException {
+ /*
+ * ; the following are all REQUIRED, ; but MUST NOT occur more than once action / description / trigger /
+ */
+ PropertyValidator.getInstance().assertOne(Property.DESCRIPTION, getProperties());
+ }
+ }
+
+ private class EmailValidator implements Validator {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * {@inheritDoc}
+ */
+ public void validate() throws ValidationException {
+ /*
+ * ; the following are all REQUIRED,
+ * ; but MUST NOT occur more than once action / description / trigger / summary
+ * ; the following is REQUIRED,
+ * ; and MAY occur more than once attendee /
+ * ; 'duration' and 'repeat' are both optional,
+ * ; and MUST NOT occur more than once each,
+ * ; but if one occurs, so MUST the other duration / repeat /
+ * ; the following are optional,
+ * ; and MAY occur more than once attach / x-prop
+ */
+ PropertyValidator.getInstance().assertOne(Property.DESCRIPTION, getProperties());
+ PropertyValidator.getInstance().assertOne(Property.SUMMARY, getProperties());
+
+ PropertyValidator.getInstance().assertOneOrMore(Property.ATTENDEE, getProperties());
+ }
+ }
+
+ private class ProcedureValidator implements Validator {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * {@inheritDoc}
+ */
+ public void validate() throws ValidationException {
+ /*
+ * ; the following are all REQUIRED,
+ * ; but MUST NOT occur more than once action / attach / trigger /
+ * ; 'duration' and 'repeat' are both optional,
+ * ; and MUST NOT occur more than once each,
+ * ; but if one occurs, so MUST the other duration / repeat /
+ * ; 'description' is optional,
+ * ; and MUST NOT occur more than once description /
+ * ; the following is optional, ; and MAY occur more than once x-prop
+ */
+ PropertyValidator.getInstance().assertOne(Property.ATTACH, getProperties());
+
+ PropertyValidator.getInstance().assertOneOrLess(Property.DESCRIPTION, getProperties());
+ }
+ }
+
+ /**
+ * Common validation for all iTIP methods.
+ *
+ * + * Component/Property Presence + * ------------------- ---------------------------------------------- + * VALARM 0+ + * ACTION 1 + * ATTACH 0+ + * DESCRIPTION 0 or 1 + * DURATION 0 or 1 if present REPEAT MUST be present + * REPEAT 0 or 1 if present DURATION MUST be present + * SUMMARY 0 or 1 + * TRIGGER 1 + * X-PROPERTY 0+ + *+ */ + private class ITIPValidator implements Validator { + + private static final long serialVersionUID = 1L; + + /** + * {@inheritDoc} + */ + public void validate() throws ValidationException { + PropertyValidator.getInstance().assertOne(Property.ACTION, getProperties()); + PropertyValidator.getInstance().assertOne(Property.TRIGGER, getProperties()); + + PropertyValidator.getInstance().assertOneOrLess(Property.DESCRIPTION, getProperties()); + PropertyValidator.getInstance().assertOneOrLess(Property.DURATION, getProperties()); + PropertyValidator.getInstance().assertOneOrLess(Property.REPEAT, getProperties()); + PropertyValidator.getInstance().assertOneOrLess(Property.SUMMARY, getProperties()); + } + } + + /** + * Returns the mandatory action property. + * @return the ACTION property or null if not specified + */ + public final Action getAction() { + return (Action) getProperty(Property.ACTION); + } + + /** + * Returns the mandatory trigger property. + * @return the TRIGGER property or null if not specified + */ + public final Trigger getTrigger() { + return (Trigger) getProperty(Property.TRIGGER); + } + + /** + * Returns the optional duration property. + * @return the DURATION property or null if not specified + */ + public final Duration getDuration() { + return (Duration) getProperty(Property.DURATION); + } + + /** + * Returns the optional repeat property. + * @return the REPEAT property or null if not specified + */ + public final Repeat getRepeat() { + return (Repeat) getProperty(Property.REPEAT); + } + + /** + * Returns the optional attachment property. + * @return the ATTACH property or null if not specified + */ + public final Attach getAttachment() { + return (Attach) getProperty(Property.ATTACH); + } + + /** + * Returns the optional description property. + * @return the DESCRIPTION property or null if not specified + */ + public final Description getDescription() { + return (Description) getProperty(Property.DESCRIPTION); + } + + /** + * Returns the optional summary property. + * @return the SUMMARY property or null if not specified + */ + public final Summary getSummary() { + return (Summary) getProperty(Property.SUMMARY); + } +}