/* * $Id: VToDo.java,v 1.23 2006/06/25 08:40:24 fortuna Exp $ [Apr 5, 2004] * * Copyright (c) 2004, 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.Iterator; import net.fortuna.ical4j.model.Component; import net.fortuna.ical4j.model.ComponentList; import net.fortuna.ical4j.model.Date; 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.property.Clazz; import net.fortuna.ical4j.model.property.Completed; 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.Due; import net.fortuna.ical4j.model.property.Duration; import net.fortuna.ical4j.model.property.Geo; import net.fortuna.ical4j.model.property.LastModified; import net.fortuna.ical4j.model.property.Location; import net.fortuna.ical4j.model.property.Organizer; import net.fortuna.ical4j.model.property.PercentComplete; import net.fortuna.ical4j.model.property.Priority; 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; import net.fortuna.ical4j.util.Strings; /** * Defines an iCalendar VTODO component. * * <pre> * 4.6.2 To-do Component * * Component Name: VTODO * * Purpose: Provide a grouping of calendar properties that describe a * to-do. * * Formal Definition: A "VTODO" calendar component is defined by the * following notation: * * todoc = "BEGIN" ":" "VTODO" CRLF * todoprop *alarmc * "END" ":" "VTODO" CRLF * * todoprop = *( * * ; the following are optional, * ; but MUST NOT occur more than once * * class / completed / created / description / dtstamp / * dtstart / geo / last-mod / location / organizer / * percent / priority / recurid / seq / status / * summary / uid / url / * * ; either 'due' or 'duration' may appear in * ; a 'todoprop', but 'due' and 'duration' * ; MUST NOT occur in the same 'todoprop' * * due / duration / * * ; the following are optional, * ; and MAY occur more than once * attach / attendee / categories / comment / contact / * exdate / exrule / rstatus / related / resources / * rdate / rrule / x-prop * * ) * </pre> * * Example 1 - Creating a todo of two (2) hour duration starting tomorrow: * * <pre><code> * java.util.Calendar cal = java.util.Calendar.getInstance(); * // tomorrow.. * cal.add(java.util.Calendar.DAY_OF_MONTH, 1); * cal.set(java.util.Calendar.HOUR_OF_DAY, 11); * cal.set(java.util.Calendar.MINUTE, 00); * * VToDo documentation = new VEvent(cal.getTime(), 1000 * 60 * 60 * 2, "Document calendar component usage"); * * // add timezone information.. * VTimeZone tz = VTimeZone.getDefault(); * TzId tzParam = new TzId(tz.getProperties().getProperty(Property.TZID).getValue()); * documentation.getProperties().getProperty(Property.DTSTART).getParameters().add(tzParam); * </code></pre> * * @author Ben Fortuna */ public class VToDo extends CalendarComponent { private static final long serialVersionUID = -269658210065896668L; private ComponentList alarms = new ComponentList(); /** * Default constructor. */ public VToDo() { super(VTODO); getProperties().add(new DtStamp()); } /** * Constructor. * * @param properties * a list of properties */ public VToDo(final PropertyList properties) { super(VTODO, properties); } /** * Constructs a new VTODO instance starting at the specified * time with the specified summary. * @param start the start date of the new todo * @param summary the todo summary */ public VToDo(final Date start, final String summary) { this(); getProperties().add(new DtStart(start)); getProperties().add(new Summary(summary)); } /** * Constructs a new VTODO instance starting and ending at the specified * times with the specified summary. * @param start the start date of the new todo * @param due the due date of the new todo * @param summary the todo summary */ public VToDo(final Date start, final Date due, final String summary) { this(); getProperties().add(new DtStart(start)); getProperties().add(new Due(due)); getProperties().add(new Summary(summary)); } /** * Constructs a new VTODO instance starting at the specified * times, for the specified duration, with the specified summary. * @param start the start date of the new todo * @param duration the duration of the new todo * @param summary the todo summary */ public VToDo(final Date start, final Dur duration, final String summary) { this(); getProperties().add(new DtStart(start)); getProperties().add(new Duration(duration)); getProperties().add(new Summary(summary)); } /** * Returns the list of alarms for this todo. * @return a component list */ public final ComponentList getAlarms() { return alarms; } /** * @see java.lang.Object#toString() */ public final String toString() { StringBuffer buffer = new StringBuffer(); buffer.append(BEGIN); buffer.append(':'); buffer.append(getName()); buffer.append(Strings.LINE_SEPARATOR); buffer.append(getProperties()); buffer.append(getAlarms()); buffer.append(END); buffer.append(':'); buffer.append(getName()); buffer.append(Strings.LINE_SEPARATOR); return buffer.toString(); } /* * (non-Javadoc) * * @see net.fortuna.ical4j.model.Component#validate(boolean) */ public final void validate(final boolean recurse) throws ValidationException { // validate that getAlarms() only contains VAlarm components Iterator iterator = getAlarms().iterator(); while (iterator.hasNext()) { Component component = (Component) iterator.next(); if (!(component instanceof VAlarm)) { throw new ValidationException( "Component [" + component.getName() + "] may not occur in VTODO"); } } 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 / completed / created / description / dtstamp / dtstart / geo / * last-mod / location / organizer / percent / priority / recurid / seq / * status / summary / uid / url / */ PropertyValidator.getInstance().assertOneOrLess(Property.CLASS, getProperties()); PropertyValidator.getInstance().assertOneOrLess(Property.COMPLETED, getProperties()); PropertyValidator.getInstance().assertOneOrLess(Property.CREATED, getProperties()); PropertyValidator.getInstance().assertOneOrLess(Property.DESCRIPTION, getProperties()); PropertyValidator.getInstance().assertOneOrLess(Property.DTSTAMP, getProperties()); PropertyValidator.getInstance().assertOneOrLess(Property.DTSTART, getProperties()); PropertyValidator.getInstance().assertOneOrLess(Property.GEO, getProperties()); PropertyValidator.getInstance().assertOneOrLess(Property.LAST_MODIFIED, getProperties()); PropertyValidator.getInstance().assertOneOrLess(Property.LOCATION, getProperties()); PropertyValidator.getInstance().assertOneOrLess(Property.ORGANIZER, getProperties()); PropertyValidator.getInstance().assertOneOrLess(Property.PERCENT_COMPLETE, getProperties()); PropertyValidator.getInstance().assertOneOrLess(Property.PRIORITY, 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()); Status status = (Status) getProperty(Property.STATUS); if (status != null && !Status.VTODO_NEEDS_ACTION.equals(status) && !Status.VTODO_COMPLETED.equals(status) && !Status.VTODO_IN_PROCESS.equals(status) && !Status.VTODO_CANCELLED.equals(status)) { throw new ValidationException( "Status property [" + status.toString() + "] may not occur in VTODO"); } /* * ; either 'due' or 'duration' may appear in ; a 'todoprop', but 'due' * and 'duration' ; MUST NOT occur in the same 'todoprop' * * due / duration / * */ try { PropertyValidator.getInstance().assertNone(Property.DUE, getProperties()); } catch (ValidationException ve) { PropertyValidator.getInstance().assertNone(Property.DURATION, getProperties()); } /* * ; the following are optional, ; and MAY occur more than once attach / * attendee / categories / comment / contact / exdate / exrule / rstatus / * related / resources / rdate / rrule / x-prop */ if (recurse) { validateProperties(); } } /** * @return the optional access classification property */ public final Clazz getClassification() { return (Clazz) getProperty(Property.CLASS); } /** * @return the optional date completed property */ public final Completed getDateCompleted() { return (Completed) getProperty(Property.COMPLETED); } /** * @return the optional creation-time property */ public final Created getCreated() { return (Created) getProperty(Property.CREATED); } /** * @return the optional description property */ 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 geographic position property */ public final Geo getGeographicPos() { return (Geo) getProperty(Property.GEO); } /** * @return the optional last-modified property */ public final LastModified getLastModified() { return (LastModified) getProperty(Property.LAST_MODIFIED); } /** * @return the optional location property */ public final Location getLocation() { return (Location) getProperty(Property.LOCATION); } /** * @return the optional organizer property */ public final Organizer getOrganizer() { return (Organizer) getProperty(Property.ORGANIZER); } /** * @return the optional percentage complete property */ public final PercentComplete getPercentComplete() { return (PercentComplete) getProperty(Property.PERCENT_COMPLETE); } /** * @return the optional priority property */ public final Priority getPriority() { return (Priority) getProperty(Property.PRIORITY); } /** * @return the optional date-stamp property */ public final DtStamp getDateStamp() { return (DtStamp) getProperty(Property.DTSTAMP); } /** * @return the optional sequence number property */ public final Sequence getSequence() { return (Sequence) getProperty(Property.SEQUENCE); } /** * @return the optional status property */ public final Status getStatus() { return (Status) getProperty(Property.STATUS); } /** * @return the optional summary property */ public final Summary getSummary() { return (Summary) getProperty(Property.SUMMARY); } /** * @return the optional URL property */ public final Url getUrl() { return (Url) getProperty(Property.URL); } /** * @return the optional recurrence identifier property */ public final RecurrenceId getRecurrenceId() { return (RecurrenceId) getProperty(Property.RECURRENCE_ID); } /** * @return the optional Duration property */ public final Duration getDuration() { return (Duration) getProperty(Property.DURATION); } /** * @return the optional due property */ public final Due getDue() { return (Due) getProperty(Property.DUE); } /** * 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); } }