1.1 --- a/src/net/fortuna/ical4j/model/component/VEvent.java Thu Feb 12 18:02:00 2015 +0100 1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 1.3 @@ -1,1522 +0,0 @@ 1.4 -/** 1.5 - * Copyright (c) 2012, Ben Fortuna 1.6 - * All rights reserved. 1.7 - * 1.8 - * Redistribution and use in source and binary forms, with or without 1.9 - * modification, are permitted provided that the following conditions 1.10 - * are met: 1.11 - * 1.12 - * o Redistributions of source code must retain the above copyright 1.13 - * notice, this list of conditions and the following disclaimer. 1.14 - * 1.15 - * o Redistributions in binary form must reproduce the above copyright 1.16 - * notice, this list of conditions and the following disclaimer in the 1.17 - * documentation and/or other materials provided with the distribution. 1.18 - * 1.19 - * o Neither the name of Ben Fortuna nor the names of any other contributors 1.20 - * may be used to endorse or promote products derived from this software 1.21 - * without specific prior written permission. 1.22 - * 1.23 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.24 - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.25 - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.26 - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 1.27 - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 1.28 - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 1.29 - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 1.30 - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 1.31 - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 1.32 - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 1.33 - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.34 - */ 1.35 -package net.fortuna.ical4j.model.component; 1.36 - 1.37 -import java.io.IOException; 1.38 -import java.net.URISyntaxException; 1.39 -import java.text.ParseException; 1.40 -import java.util.HashMap; 1.41 -import java.util.Iterator; 1.42 -import java.util.Map; 1.43 - 1.44 -import net.fortuna.ical4j.model.Component; 1.45 -import net.fortuna.ical4j.model.ComponentList; 1.46 -import net.fortuna.ical4j.model.Date; 1.47 -import net.fortuna.ical4j.model.DateTime; 1.48 -import net.fortuna.ical4j.model.Dur; 1.49 -import net.fortuna.ical4j.model.Parameter; 1.50 -import net.fortuna.ical4j.model.Period; 1.51 -import net.fortuna.ical4j.model.PeriodList; 1.52 -import net.fortuna.ical4j.model.Property; 1.53 -import net.fortuna.ical4j.model.PropertyList; 1.54 -import net.fortuna.ical4j.model.ValidationException; 1.55 -import net.fortuna.ical4j.model.Validator; 1.56 -import net.fortuna.ical4j.model.parameter.Value; 1.57 -import net.fortuna.ical4j.model.property.Clazz; 1.58 -import net.fortuna.ical4j.model.property.Created; 1.59 -import net.fortuna.ical4j.model.property.Description; 1.60 -import net.fortuna.ical4j.model.property.DtEnd; 1.61 -import net.fortuna.ical4j.model.property.DtStamp; 1.62 -import net.fortuna.ical4j.model.property.DtStart; 1.63 -import net.fortuna.ical4j.model.property.Duration; 1.64 -import net.fortuna.ical4j.model.property.Geo; 1.65 -import net.fortuna.ical4j.model.property.LastModified; 1.66 -import net.fortuna.ical4j.model.property.Location; 1.67 -import net.fortuna.ical4j.model.property.Method; 1.68 -import net.fortuna.ical4j.model.property.Organizer; 1.69 -import net.fortuna.ical4j.model.property.Priority; 1.70 -import net.fortuna.ical4j.model.property.RecurrenceId; 1.71 -import net.fortuna.ical4j.model.property.Sequence; 1.72 -import net.fortuna.ical4j.model.property.Status; 1.73 -import net.fortuna.ical4j.model.property.Summary; 1.74 -import net.fortuna.ical4j.model.property.Transp; 1.75 -import net.fortuna.ical4j.model.property.Uid; 1.76 -import net.fortuna.ical4j.model.property.Url; 1.77 -import net.fortuna.ical4j.util.CompatibilityHints; 1.78 -import net.fortuna.ical4j.util.ComponentValidator; 1.79 -import net.fortuna.ical4j.util.Dates; 1.80 -import net.fortuna.ical4j.util.PropertyValidator; 1.81 -import net.fortuna.ical4j.util.Strings; 1.82 - 1.83 -import org.apache.commons.lang3.ObjectUtils; 1.84 -import org.apache.commons.lang3.builder.HashCodeBuilder; 1.85 - 1.86 -/** 1.87 - * $Id$ [Apr 5, 2004] 1.88 - * 1.89 - * Defines an iCalendar VEVENT component. 1.90 - * 1.91 - * <pre> 1.92 - * 4.6.1 Event Component 1.93 - * 1.94 - * Component Name: "VEVENT" 1.95 - * 1.96 - * Purpose: Provide a grouping of component properties that describe an 1.97 - * event. 1.98 - * 1.99 - * Format Definition: A "VEVENT" calendar component is defined by the 1.100 - * following notation: 1.101 - * 1.102 - * eventc = "BEGIN" ":" "VEVENT" CRLF 1.103 - * eventprop *alarmc 1.104 - * "END" ":" "VEVENT" CRLF 1.105 - * 1.106 - * eventprop = *( 1.107 - * 1.108 - * ; the following are optional, 1.109 - * ; but MUST NOT occur more than once 1.110 - * 1.111 - * class / created / description / dtstart / geo / 1.112 - * last-mod / location / organizer / priority / 1.113 - * dtstamp / seq / status / summary / transp / 1.114 - * uid / url / recurid / 1.115 - * 1.116 - * ; either 'dtend' or 'duration' may appear in 1.117 - * ; a 'eventprop', but 'dtend' and 'duration' 1.118 - * ; MUST NOT occur in the same 'eventprop' 1.119 - * 1.120 - * dtend / duration / 1.121 - * 1.122 - * ; the following are optional, 1.123 - * ; and MAY occur more than once 1.124 - * 1.125 - * attach / attendee / categories / comment / 1.126 - * contact / exdate / exrule / rstatus / related / 1.127 - * resources / rdate / rrule / x-prop 1.128 - * 1.129 - * ) 1.130 - * </pre> 1.131 - * 1.132 - * Example 1 - Creating a new all-day event: 1.133 - * 1.134 - * <pre><code> 1.135 - * java.util.Calendar cal = java.util.Calendar.getInstance(); 1.136 - * cal.set(java.util.Calendar.MONTH, java.util.Calendar.DECEMBER); 1.137 - * cal.set(java.util.Calendar.DAY_OF_MONTH, 25); 1.138 - * 1.139 - * VEvent christmas = new VEvent(cal.getTime(), "Christmas Day"); 1.140 - * 1.141 - * // initialise as an all-day event.. 1.142 - * christmas.getProperties().getProperty(Property.DTSTART).getParameters().add( 1.143 - * Value.DATE); 1.144 - * 1.145 - * // add timezone information.. 1.146 - * VTimeZone tz = VTimeZone.getDefault(); 1.147 - * TzId tzParam = new TzId(tz.getProperties().getProperty(Property.TZID) 1.148 - * .getValue()); 1.149 - * christmas.getProperties().getProperty(Property.DTSTART).getParameters().add( 1.150 - * tzParam); 1.151 - * </code></pre> 1.152 - * 1.153 - * Example 2 - Creating an event of one (1) hour duration: 1.154 - * 1.155 - * <pre><code> 1.156 - * java.util.Calendar cal = java.util.Calendar.getInstance(); 1.157 - * // tomorrow.. 1.158 - * cal.add(java.util.Calendar.DAY_OF_MONTH, 1); 1.159 - * cal.set(java.util.Calendar.HOUR_OF_DAY, 9); 1.160 - * cal.set(java.util.Calendar.MINUTE, 30); 1.161 - * 1.162 - * VEvent meeting = new VEvent(cal.getTime(), 1000 * 60 * 60, "Progress Meeting"); 1.163 - * 1.164 - * // add timezone information.. 1.165 - * VTimeZone tz = VTimeZone.getDefault(); 1.166 - * TzId tzParam = new TzId(tz.getProperties().getProperty(Property.TZID) 1.167 - * .getValue()); 1.168 - * meeting.getProperties().getProperty(Property.DTSTART).getParameters().add( 1.169 - * tzParam); 1.170 - * </code></pre> 1.171 - * 1.172 - * Example 3 - Retrieve a list of periods representing a recurring event in a specified range: 1.173 - * 1.174 - * <pre><code> 1.175 - * Calendar weekday9AM = Calendar.getInstance(); 1.176 - * weekday9AM.set(2005, Calendar.MARCH, 7, 9, 0, 0); 1.177 - * weekday9AM.set(Calendar.MILLISECOND, 0); 1.178 - * 1.179 - * Calendar weekday5PM = Calendar.getInstance(); 1.180 - * weekday5PM.set(2005, Calendar.MARCH, 7, 17, 0, 0); 1.181 - * weekday5PM.set(Calendar.MILLISECOND, 0); 1.182 - * 1.183 - * // Do the recurrence until December 31st. 1.184 - * Calendar untilCal = Calendar.getInstance(); 1.185 - * untilCal.set(2005, Calendar.DECEMBER, 31); 1.186 - * untilCal.set(Calendar.MILLISECOND, 0); 1.187 - * 1.188 - * // 9:00AM to 5:00PM Rule 1.189 - * Recur recur = new Recur(Recur.WEEKLY, untilCal.getTime()); 1.190 - * recur.getDayList().add(WeekDay.MO); 1.191 - * recur.getDayList().add(WeekDay.TU); 1.192 - * recur.getDayList().add(WeekDay.WE); 1.193 - * recur.getDayList().add(WeekDay.TH); 1.194 - * recur.getDayList().add(WeekDay.FR); 1.195 - * recur.setInterval(3); 1.196 - * recur.setWeekStartDay(WeekDay.MO.getDay()); 1.197 - * RRule rrule = new RRule(recur); 1.198 - * 1.199 - * Summary summary = new Summary("TEST EVENTS THAT HAPPEN 9-5 MON-FRI"); 1.200 - * 1.201 - * weekdayNineToFiveEvents = new VEvent(); 1.202 - * weekdayNineToFiveEvents.getProperties().add(rrule); 1.203 - * weekdayNineToFiveEvents.getProperties().add(summary); 1.204 - * weekdayNineToFiveEvents.getProperties().add(new DtStart(weekday9AM.getTime())); 1.205 - * weekdayNineToFiveEvents.getProperties().add(new DtEnd(weekday5PM.getTime())); 1.206 - * 1.207 - * // Test Start 04/01/2005, End One month later. 1.208 - * // Query Calendar Start and End Dates. 1.209 - * Calendar queryStartDate = Calendar.getInstance(); 1.210 - * queryStartDate.set(2005, Calendar.APRIL, 1, 14, 47, 0); 1.211 - * queryStartDate.set(Calendar.MILLISECOND, 0); 1.212 - * Calendar queryEndDate = Calendar.getInstance(); 1.213 - * queryEndDate.set(2005, Calendar.MAY, 1, 11, 15, 0); 1.214 - * queryEndDate.set(Calendar.MILLISECOND, 0); 1.215 - * 1.216 - * // This range is monday to friday every three weeks, starting from 1.217 - * // March 7th 2005, which means for our query dates we need 1.218 - * // April 18th through to the 22nd. 1.219 - * PeriodList periods = weekdayNineToFiveEvents.getPeriods(queryStartDate 1.220 - * .getTime(), queryEndDate.getTime()); 1.221 - * </code></pre> 1.222 - * 1.223 - * @author Ben Fortuna 1.224 - */ 1.225 -public class VEvent extends CalendarComponent { 1.226 - 1.227 - private static final long serialVersionUID = 2547948989200697335L; 1.228 - 1.229 - private final Map methodValidators = new HashMap(); 1.230 - { 1.231 - methodValidators.put(Method.ADD, new AddValidator()); 1.232 - methodValidators.put(Method.CANCEL, new CancelValidator()); 1.233 - methodValidators.put(Method.COUNTER, new CounterValidator()); 1.234 - methodValidators.put(Method.DECLINE_COUNTER, new DeclineCounterValidator()); 1.235 - methodValidators.put(Method.PUBLISH, new PublishValidator()); 1.236 - methodValidators.put(Method.REFRESH, new RefreshValidator()); 1.237 - methodValidators.put(Method.REPLY, new ReplyValidator()); 1.238 - methodValidators.put(Method.REQUEST, new RequestValidator()); 1.239 - } 1.240 - 1.241 - private ComponentList alarms; 1.242 - 1.243 - /** 1.244 - * Default constructor. 1.245 - */ 1.246 - public VEvent() { 1.247 - super(VEVENT); 1.248 - this.alarms = new ComponentList(); 1.249 - getProperties().add(new DtStamp()); 1.250 - } 1.251 - 1.252 - /** 1.253 - * Constructor. 1.254 - * @param properties a list of properties 1.255 - */ 1.256 - public VEvent(final PropertyList properties) { 1.257 - super(VEVENT, properties); 1.258 - this.alarms = new ComponentList(); 1.259 - } 1.260 - 1.261 - /** 1.262 - * Constructor. 1.263 - * @param properties a list of properties 1.264 - * @param alarms a list of alarms 1.265 - */ 1.266 - public VEvent(final PropertyList properties, final ComponentList alarms) { 1.267 - super(VEVENT, properties); 1.268 - this.alarms = alarms; 1.269 - } 1.270 - 1.271 - /** 1.272 - * Constructs a new VEVENT instance starting at the specified time with the specified summary. 1.273 - * @param start the start date of the new event 1.274 - * @param summary the event summary 1.275 - */ 1.276 - public VEvent(final Date start, final String summary) { 1.277 - this(); 1.278 - getProperties().add(new DtStart(start)); 1.279 - getProperties().add(new Summary(summary)); 1.280 - } 1.281 - 1.282 - /** 1.283 - * Constructs a new VEVENT instance starting and ending at the specified times with the specified summary. 1.284 - * @param start the start date of the new event 1.285 - * @param end the end date of the new event 1.286 - * @param summary the event summary 1.287 - */ 1.288 - public VEvent(final Date start, final Date end, final String summary) { 1.289 - this(); 1.290 - getProperties().add(new DtStart(start)); 1.291 - getProperties().add(new DtEnd(end)); 1.292 - getProperties().add(new Summary(summary)); 1.293 - } 1.294 - 1.295 - /** 1.296 - * Constructs a new VEVENT instance starting at the specified times, for the specified duration, with the specified 1.297 - * summary. 1.298 - * @param start the start date of the new event 1.299 - * @param duration the duration of the new event 1.300 - * @param summary the event summary 1.301 - */ 1.302 - public VEvent(final Date start, final Dur duration, final String summary) { 1.303 - this(); 1.304 - getProperties().add(new DtStart(start)); 1.305 - getProperties().add(new Duration(duration)); 1.306 - getProperties().add(new Summary(summary)); 1.307 - } 1.308 - 1.309 - /** 1.310 - * Returns the list of alarms for this event. 1.311 - * @return a component list 1.312 - */ 1.313 - public final ComponentList getAlarms() { 1.314 - return alarms; 1.315 - } 1.316 - 1.317 - /** 1.318 - * {@inheritDoc} 1.319 - */ 1.320 - public final String toString() { 1.321 - final StringBuffer b = new StringBuffer(); 1.322 - b.append(BEGIN); 1.323 - b.append(':'); 1.324 - b.append(getName()); 1.325 - b.append(Strings.LINE_SEPARATOR); 1.326 - b.append(getProperties()); 1.327 - b.append(getAlarms()); 1.328 - b.append(END); 1.329 - b.append(':'); 1.330 - b.append(getName()); 1.331 - b.append(Strings.LINE_SEPARATOR); 1.332 - return b.toString(); 1.333 - } 1.334 - 1.335 - /** 1.336 - * {@inheritDoc} 1.337 - */ 1.338 - public final void validate(final boolean recurse) throws ValidationException { 1.339 - 1.340 - // validate that getAlarms() only contains VAlarm components 1.341 - final Iterator iterator = getAlarms().iterator(); 1.342 - while (iterator.hasNext()) { 1.343 - final Component component = (Component) iterator.next(); 1.344 - 1.345 - if (!(component instanceof VAlarm)) { 1.346 - throw new ValidationException("Component [" 1.347 - + component.getName() + "] may not occur in VEVENT"); 1.348 - } 1.349 - 1.350 - ((VAlarm) component).validate(recurse); 1.351 - } 1.352 - 1.353 - if (!CompatibilityHints 1.354 - .isHintEnabled(CompatibilityHints.KEY_RELAXED_VALIDATION)) { 1.355 - 1.356 - // From "4.8.4.7 Unique Identifier": 1.357 - // Conformance: The property MUST be specified in the "VEVENT", "VTODO", 1.358 - // "VJOURNAL" or "VFREEBUSY" calendar components. 1.359 - PropertyValidator.getInstance().assertOne(Property.UID, 1.360 - getProperties()); 1.361 - 1.362 - // From "4.8.7.2 Date/Time Stamp": 1.363 - // Conformance: This property MUST be included in the "VEVENT", "VTODO", 1.364 - // "VJOURNAL" or "VFREEBUSY" calendar components. 1.365 - PropertyValidator.getInstance().assertOne(Property.DTSTAMP, 1.366 - getProperties()); 1.367 - } 1.368 - 1.369 - /* 1.370 - * ; the following are optional, ; but MUST NOT occur more than once class / created / description / dtstart / 1.371 - * geo / last-mod / location / organizer / priority / dtstamp / seq / status / summary / transp / uid / url / 1.372 - * recurid / 1.373 - */ 1.374 - PropertyValidator.getInstance().assertOneOrLess(Property.CLASS, 1.375 - getProperties()); 1.376 - PropertyValidator.getInstance().assertOneOrLess(Property.CREATED, 1.377 - getProperties()); 1.378 - PropertyValidator.getInstance().assertOneOrLess(Property.DESCRIPTION, 1.379 - getProperties()); 1.380 - PropertyValidator.getInstance().assertOneOrLess(Property.DTSTART, 1.381 - getProperties()); 1.382 - PropertyValidator.getInstance().assertOneOrLess(Property.GEO, 1.383 - getProperties()); 1.384 - PropertyValidator.getInstance().assertOneOrLess(Property.LAST_MODIFIED, 1.385 - getProperties()); 1.386 - PropertyValidator.getInstance().assertOneOrLess(Property.LOCATION, 1.387 - getProperties()); 1.388 - PropertyValidator.getInstance().assertOneOrLess(Property.ORGANIZER, 1.389 - getProperties()); 1.390 - PropertyValidator.getInstance().assertOneOrLess(Property.PRIORITY, 1.391 - getProperties()); 1.392 - PropertyValidator.getInstance().assertOneOrLess(Property.DTSTAMP, 1.393 - getProperties()); 1.394 - PropertyValidator.getInstance().assertOneOrLess(Property.SEQUENCE, 1.395 - getProperties()); 1.396 - PropertyValidator.getInstance().assertOneOrLess(Property.STATUS, 1.397 - getProperties()); 1.398 - PropertyValidator.getInstance().assertOneOrLess(Property.SUMMARY, 1.399 - getProperties()); 1.400 - PropertyValidator.getInstance().assertOneOrLess(Property.TRANSP, 1.401 - getProperties()); 1.402 - PropertyValidator.getInstance().assertOneOrLess(Property.UID, 1.403 - getProperties()); 1.404 - PropertyValidator.getInstance().assertOneOrLess(Property.URL, 1.405 - getProperties()); 1.406 - PropertyValidator.getInstance().assertOneOrLess(Property.RECURRENCE_ID, 1.407 - getProperties()); 1.408 - 1.409 - final Status status = (Status) getProperty(Property.STATUS); 1.410 - if (status != null && !Status.VEVENT_TENTATIVE.getValue().equals(status.getValue()) 1.411 - && !Status.VEVENT_CONFIRMED.getValue().equals(status.getValue()) 1.412 - && !Status.VEVENT_CANCELLED.getValue().equals(status.getValue())) { 1.413 - throw new ValidationException("Status property [" 1.414 - + status.toString() + "] is not applicable for VEVENT"); 1.415 - } 1.416 - 1.417 - /* 1.418 - * ; either 'dtend' or 'duration' may appear in ; a 'eventprop', but 'dtend' and 'duration' ; MUST NOT occur in 1.419 - * the same 'eventprop' dtend / duration / 1.420 - */ 1.421 - try { 1.422 - PropertyValidator.getInstance().assertNone(Property.DTEND, 1.423 - getProperties()); 1.424 - } 1.425 - catch (ValidationException ve) { 1.426 - PropertyValidator.getInstance().assertNone(Property.DURATION, 1.427 - getProperties()); 1.428 - } 1.429 - 1.430 - if (getProperty(Property.DTEND) != null) { 1.431 - 1.432 - /* 1.433 - * The "VEVENT" is also the calendar component used to specify an anniversary or daily reminder within a 1.434 - * calendar. These events have a DATE value type for the "DTSTART" property instead of the default data type 1.435 - * of DATE-TIME. If such a "VEVENT" has a "DTEND" property, it MUST be specified as a DATE value also. The 1.436 - * anniversary type of "VEVENT" can span more than one date (i.e, "DTEND" property value is set to a 1.437 - * calendar date after the "DTSTART" property value). 1.438 - */ 1.439 - final DtStart start = (DtStart) getProperty(Property.DTSTART); 1.440 - final DtEnd end = (DtEnd) getProperty(Property.DTEND); 1.441 - 1.442 - if (start != null) { 1.443 - final Parameter startValue = start.getParameter(Parameter.VALUE); 1.444 - final Parameter endValue = end.getParameter(Parameter.VALUE); 1.445 - 1.446 - boolean startEndValueMismatch = false; 1.447 - if (endValue != null) { 1.448 - if (startValue != null && !endValue.equals(startValue)) { 1.449 - // invalid.. 1.450 - startEndValueMismatch = true; 1.451 - } 1.452 - else if (startValue == null && !Value.DATE_TIME.equals(endValue)) { 1.453 - // invalid.. 1.454 - startEndValueMismatch = true; 1.455 - } 1.456 - } 1.457 - else if (startValue != null && !Value.DATE_TIME.equals(startValue)) { 1.458 - //invalid.. 1.459 - startEndValueMismatch = true; 1.460 - } 1.461 - if (startEndValueMismatch) { 1.462 - throw new ValidationException("Property [" + Property.DTEND 1.463 - + "] must have the same [" + Parameter.VALUE 1.464 - + "] as [" + Property.DTSTART + "]"); 1.465 - } 1.466 - } 1.467 - } 1.468 - 1.469 - /* 1.470 - * ; the following are optional, ; and MAY occur more than once attach / attendee / categories / comment / 1.471 - * contact / exdate / exrule / rstatus / related / resources / rdate / rrule / x-prop 1.472 - */ 1.473 - 1.474 - if (recurse) { 1.475 - validateProperties(); 1.476 - } 1.477 - } 1.478 - 1.479 - /** 1.480 - * {@inheritDoc} 1.481 - */ 1.482 - protected Validator getValidator(Method method) { 1.483 - return (Validator) methodValidators.get(method); 1.484 - } 1.485 - 1.486 - /** 1.487 - * METHOD:ADD Validator. 1.488 - * 1.489 - * <pre> 1.490 - * Component/Property Presence 1.491 - * ------------------- ---------------------------------------------- 1.492 - * METHOD 1 MUST be "ADD" 1.493 - * VEVENT 1 1.494 - * DTSTAMP 1 1.495 - * DTSTART 1 1.496 - * ORGANIZER 1 1.497 - * SEQUENCE 1 MUST be greater than 0 1.498 - * SUMMARY 1 Can be null 1.499 - * UID 1 MUST match that of the original event 1.500 - * 1.501 - * ATTACH 0+ 1.502 - * ATTENDEE 0+ 1.503 - * CATEGORIES 0 or 1 This property MAY contain a list of values 1.504 - * CLASS 0 or 1 1.505 - * COMMENT 0 or 1 1.506 - * CONTACT 0+ 1.507 - * CREATED 0 or 1 1.508 - * DESCRIPTION 0 or 1 Can be null 1.509 - * DTEND 0 or 1 if present DURATION MUST NOT be present 1.510 - * DURATION 0 or 1 if present DTEND MUST NOT be present 1.511 - * EXDATE 0+ 1.512 - * EXRULE 0+ 1.513 - * GEO 0 or 1 1.514 - * LAST-MODIFIED 0 or 1 1.515 - * LOCATION 0 or 1 1.516 - * PRIORITY 0 or 1 1.517 - * RDATE 0+ 1.518 - * RELATED-TO 0+ 1.519 - * RESOURCES 0 or 1 This property MAY contain a list of values 1.520 - * RRULE 0+ 1.521 - * STATUS 0 or 1 MAY be one of TENTATIVE/CONFIRMED 1.522 - * TRANSP 0 or 1 1.523 - * URL 0 or 1 1.524 - * X-PROPERTY 0+ 1.525 - * 1.526 - * RECURRENCE-ID 0 1.527 - * REQUEST-STATUS 0 1.528 - * 1.529 - * VALARM 0+ 1.530 - * VTIMEZONE 0+ MUST be present if any date/time refers to 1.531 - * a timezone 1.532 - * X-COMPONENT 0+ 1.533 - * 1.534 - * VFREEBUSY 0 1.535 - * VTODO 0 1.536 - * VJOURNAL 0 1.537 - * </pre> 1.538 - * 1.539 - */ 1.540 - private class AddValidator implements Validator { 1.541 - 1.542 - private static final long serialVersionUID = 1L; 1.543 - 1.544 - public void validate() throws ValidationException { 1.545 - PropertyValidator.getInstance().assertOne(Property.DTSTAMP, getProperties()); 1.546 - PropertyValidator.getInstance().assertOne(Property.DTSTART, getProperties()); 1.547 - PropertyValidator.getInstance().assertOne(Property.ORGANIZER, getProperties()); 1.548 - PropertyValidator.getInstance().assertOne(Property.SEQUENCE, getProperties()); 1.549 - PropertyValidator.getInstance().assertOne(Property.SUMMARY, getProperties()); 1.550 - PropertyValidator.getInstance().assertOne(Property.UID, getProperties()); 1.551 - 1.552 - PropertyValidator.getInstance().assertOneOrLess(Property.CATEGORIES, getProperties()); 1.553 - PropertyValidator.getInstance().assertOneOrLess(Property.CLASS, getProperties()); 1.554 - PropertyValidator.getInstance().assertOneOrLess(Property.CREATED, getProperties()); 1.555 - PropertyValidator.getInstance().assertOneOrLess(Property.DESCRIPTION, getProperties()); 1.556 - PropertyValidator.getInstance().assertOneOrLess(Property.DTEND, getProperties()); 1.557 - PropertyValidator.getInstance().assertOneOrLess(Property.DURATION, getProperties()); 1.558 - PropertyValidator.getInstance().assertOneOrLess(Property.GEO, getProperties()); 1.559 - PropertyValidator.getInstance().assertOneOrLess(Property.LAST_MODIFIED, getProperties()); 1.560 - PropertyValidator.getInstance().assertOneOrLess(Property.LOCATION, getProperties()); 1.561 - PropertyValidator.getInstance().assertOneOrLess(Property.PRIORITY, getProperties()); 1.562 - PropertyValidator.getInstance().assertOneOrLess(Property.RESOURCES, getProperties()); 1.563 - PropertyValidator.getInstance().assertOneOrLess(Property.STATUS, getProperties()); 1.564 - PropertyValidator.getInstance().assertOneOrLess(Property.TRANSP, getProperties()); 1.565 - PropertyValidator.getInstance().assertOneOrLess(Property.URL, getProperties()); 1.566 - 1.567 - PropertyValidator.getInstance().assertNone(Property.RECURRENCE_ID, getProperties()); 1.568 - PropertyValidator.getInstance().assertNone(Property.REQUEST_STATUS, getProperties()); 1.569 - 1.570 - for (final Iterator i = getAlarms().iterator(); i.hasNext();) { 1.571 - final VAlarm alarm = (VAlarm) i.next(); 1.572 - alarm.validate(Method.ADD); 1.573 - } 1.574 - } 1.575 - } 1.576 - 1.577 - /** 1.578 - * METHOD:CANCEL Validator. 1.579 - * 1.580 - * <pre> 1.581 - * Component/Property Presence 1.582 - * ------------------- ---------------------------------------------- 1.583 - * METHOD 1 MUST be "CANCEL" 1.584 - * 1.585 - * VEVENT 1+ All must have the same UID 1.586 - * ATTENDEE 0+ MUST include all "Attendees" being removed 1.587 - * the event. MUST include all "Attendees" if 1.588 - * the entire event is cancelled. 1.589 - * DTSTAMP 1 1.590 - * ORGANIZER 1 1.591 - * SEQUENCE 1 1.592 - * UID 1 MUST be the UID of the original REQUEST 1.593 - * 1.594 - * COMMENT 0 or 1 1.595 - * ATTACH 0+ 1.596 - * CATEGORIES 0 or 1 This property may contain a list of values 1.597 - * CLASS 0 or 1 1.598 - * CONTACT 0+ 1.599 - * CREATED 0 or 1 1.600 - * DESCRIPTION 0 or 1 1.601 - * DTEND 0 or 1 if present DURATION MUST NOT be present 1.602 - * DTSTART 0 or 1 1.603 - * DURATION 0 or 1 if present DTEND MUST NOT be present 1.604 - * EXDATE 0+ 1.605 - * EXRULE 0+ 1.606 - * GEO 0 or 1 1.607 - * LAST-MODIFIED 0 or 1 1.608 - * LOCATION 0 or 1 1.609 - * PRIORITY 0 or 1 1.610 - * RDATE 0+ 1.611 - * RECURRENCE-ID 0 or 1 MUST be present if referring to one or 1.612 - * more or more recurring instances. 1.613 - * Otherwise it MUST NOT be present 1.614 - * RELATED-TO 0+ 1.615 - * RESOURCES 0 or 1 1.616 - * RRULE 0+ 1.617 - * STATUS 0 or 1 MUST be set to CANCELLED. If uninviting 1.618 - * specific "Attendees" then MUST NOT be 1.619 - * included. 1.620 - * SUMMARY 0 or 1 1.621 - * TRANSP 0 or 1 1.622 - * URL 0 or 1 1.623 - * X-PROPERTY 0+ 1.624 - * REQUEST-STATUS 0 1.625 - * 1.626 - * VTIMEZONE 0+ MUST be present if any date/time refers to 1.627 - * a timezone 1.628 - * X-COMPONENT 0+ 1.629 - * 1.630 - * VTODO 0 1.631 - * VJOURNAL 0 1.632 - * VFREEBUSY 0 1.633 - * VALARM 0 1.634 - * </pre> 1.635 - * 1.636 - */ 1.637 - private class CancelValidator implements Validator { 1.638 - 1.639 - private static final long serialVersionUID = 1L; 1.640 - 1.641 - public final void validate() throws ValidationException { 1.642 - PropertyValidator.getInstance().assertOne(Property.DTSTAMP, getProperties()); 1.643 - PropertyValidator.getInstance().assertOne(Property.DTSTART, getProperties()); 1.644 - PropertyValidator.getInstance().assertOne(Property.ORGANIZER, getProperties()); 1.645 - PropertyValidator.getInstance().assertOne(Property.SEQUENCE, getProperties()); 1.646 - PropertyValidator.getInstance().assertOne(Property.UID, getProperties()); 1.647 - 1.648 - PropertyValidator.getInstance().assertOneOrLess(Property.CATEGORIES, getProperties()); 1.649 - PropertyValidator.getInstance().assertOneOrLess(Property.CLASS, getProperties()); 1.650 - PropertyValidator.getInstance().assertOneOrLess(Property.CREATED, getProperties()); 1.651 - PropertyValidator.getInstance().assertOneOrLess(Property.DESCRIPTION, getProperties()); 1.652 - PropertyValidator.getInstance().assertOneOrLess(Property.DTEND, getProperties()); 1.653 - PropertyValidator.getInstance().assertOneOrLess(Property.DTSTART, getProperties()); 1.654 - PropertyValidator.getInstance().assertOneOrLess(Property.DURATION, getProperties()); 1.655 - PropertyValidator.getInstance().assertOneOrLess(Property.GEO, getProperties()); 1.656 - PropertyValidator.getInstance().assertOneOrLess(Property.LAST_MODIFIED, getProperties()); 1.657 - PropertyValidator.getInstance().assertOneOrLess(Property.LOCATION, getProperties()); 1.658 - PropertyValidator.getInstance().assertOneOrLess(Property.PRIORITY, getProperties()); 1.659 - PropertyValidator.getInstance().assertOneOrLess(Property.RECURRENCE_ID, getProperties()); 1.660 - PropertyValidator.getInstance().assertOneOrLess(Property.RESOURCES, getProperties()); 1.661 - PropertyValidator.getInstance().assertOneOrLess(Property.STATUS, getProperties()); 1.662 - PropertyValidator.getInstance().assertOneOrLess(Property.SUMMARY, getProperties()); 1.663 - PropertyValidator.getInstance().assertOneOrLess(Property.TRANSP, getProperties()); 1.664 - PropertyValidator.getInstance().assertOneOrLess(Property.URL, getProperties()); 1.665 - 1.666 - PropertyValidator.getInstance().assertNone(Property.REQUEST_STATUS, getProperties()); 1.667 - 1.668 - ComponentValidator.assertNone(Component.VALARM, getAlarms()); 1.669 - } 1.670 - } 1.671 - 1.672 - /** 1.673 - * METHOD:COUNTER Validator. 1.674 - * 1.675 - * <pre> 1.676 - * Component/Property Presence 1.677 - * ------------------- ---------------------------------------------- 1.678 - * METHOD 1 MUST be "COUNTER" 1.679 - * 1.680 - * VEVENT 1 1.681 - * DTSTAMP 1 1.682 - * DTSTART 1 1.683 - * ORGANIZER 1 MUST be the "Organizer" of the original 1.684 - * event 1.685 - * SEQUENCE 1 MUST be present if value is greater than 0, 1.686 - * MAY be present if 0 1.687 - * SUMMARY 1 Can be null 1.688 - * UID 1 MUST be the UID associated with the REQUEST 1.689 - * being countered 1.690 - * 1.691 - * ATTACH 0+ 1.692 - * ATTENDEE 0+ Can also be used to propose other 1.693 - * "Attendees" 1.694 - * CATEGORIES 0 or 1 This property may contain a list of values 1.695 - * CLASS 0 or 1 1.696 - * COMMENT 0 or 1 1.697 - * CONTACT 0+ 1.698 - * CREATED 0 or 1 1.699 - * DESCRIPTION 0 or 1 1.700 - * DTEND 0 or 1 if present DURATION MUST NOT be present 1.701 - * DURATION 0 or 1 if present DTEND MUST NOT be present 1.702 - * EXDATE 0+ 1.703 - * EXRULE 0+ 1.704 - * GEO 0 or 1 1.705 - * LAST-MODIFIED 0 or 1 1.706 - * LOCATION 0 or 1 1.707 - * PRIORITY 0 or 1 1.708 - * RDATE 0+ 1.709 - * RECURRENCE-ID 0 or 1 MUST only if referring to an instance of a 1.710 - * recurring calendar component. Otherwise it 1.711 - * MUST NOT be present. 1.712 - * RELATED-TO 0+ 1.713 - * REQUEST-STATUS 0+ 1.714 - * RESOURCES 0 or 1 This property may contain a list of values 1.715 - * RRULE 0+ 1.716 - * STATUS 0 or 1 Value must be one of CONFIRMED/TENATIVE/ 1.717 - * CANCELLED 1.718 - * TRANSP 0 or 1 1.719 - * URL 0 or 1 1.720 - * X-PROPERTY 0+ 1.721 - * 1.722 - * VALARM 0+ 1.723 - * VTIMEZONE 0+ MUST be present if any date/time refers to 1.724 - * a timezone 1.725 - * X-COMPONENT 0+ 1.726 - * 1.727 - * VTODO 0 1.728 - * VJOURNAL 0 1.729 - * VFREEBUSY 0 1.730 - * </pre> 1.731 - * 1.732 - */ 1.733 - private class CounterValidator implements Validator { 1.734 - 1.735 - private static final long serialVersionUID = 1L; 1.736 - 1.737 - public void validate() throws ValidationException { 1.738 - PropertyValidator.getInstance().assertOne(Property.DTSTAMP, getProperties()); 1.739 - PropertyValidator.getInstance().assertOne(Property.DTSTART, getProperties()); 1.740 - 1.741 - if (!CompatibilityHints.isHintEnabled(CompatibilityHints.KEY_RELAXED_VALIDATION)) { 1.742 - PropertyValidator.getInstance().assertOne(Property.ORGANIZER, getProperties()); 1.743 - } 1.744 - 1.745 - PropertyValidator.getInstance().assertOne(Property.SEQUENCE, getProperties()); 1.746 - PropertyValidator.getInstance().assertOne(Property.SUMMARY, getProperties()); 1.747 - PropertyValidator.getInstance().assertOne(Property.UID, getProperties()); 1.748 - 1.749 - PropertyValidator.getInstance().assertOneOrLess(Property.CATEGORIES, getProperties()); 1.750 - PropertyValidator.getInstance().assertOneOrLess(Property.CLASS, getProperties()); 1.751 - PropertyValidator.getInstance().assertOneOrLess(Property.CREATED, getProperties()); 1.752 - PropertyValidator.getInstance().assertOneOrLess(Property.DESCRIPTION, getProperties()); 1.753 - PropertyValidator.getInstance().assertOneOrLess(Property.DTEND, getProperties()); 1.754 - PropertyValidator.getInstance().assertOneOrLess(Property.DURATION, getProperties()); 1.755 - PropertyValidator.getInstance().assertOneOrLess(Property.GEO, getProperties()); 1.756 - PropertyValidator.getInstance().assertOneOrLess(Property.LAST_MODIFIED, getProperties()); 1.757 - PropertyValidator.getInstance().assertOneOrLess(Property.LOCATION, getProperties()); 1.758 - PropertyValidator.getInstance().assertOneOrLess(Property.PRIORITY, getProperties()); 1.759 - PropertyValidator.getInstance().assertOneOrLess(Property.RECURRENCE_ID, getProperties()); 1.760 - PropertyValidator.getInstance().assertOneOrLess(Property.RESOURCES, getProperties()); 1.761 - PropertyValidator.getInstance().assertOneOrLess(Property.STATUS, getProperties()); 1.762 - PropertyValidator.getInstance().assertOneOrLess(Property.TRANSP, getProperties()); 1.763 - PropertyValidator.getInstance().assertOneOrLess(Property.URL, getProperties()); 1.764 - 1.765 - for (final Iterator i = getAlarms().iterator(); i.hasNext();) { 1.766 - final VAlarm alarm = (VAlarm) i.next(); 1.767 - alarm.validate(Method.COUNTER); 1.768 - } 1.769 - } 1.770 - } 1.771 - 1.772 - /** 1.773 - * METHOD:DECLINECOUNTER Validator. 1.774 - * 1.775 - * <pre> 1.776 - * Component/Property Presence 1.777 - * ------------------- ---------------------------------------------- 1.778 - * METHOD 1 MUST be "DECLINECOUNTER" 1.779 - * 1.780 - * VEVENT 1 1.781 - * DTSTAMP 1 1.782 - * ORGANIZER 1 1.783 - * UID 1 MUST, same UID specified in original 1.784 - * REQUEST and subsequent COUNTER 1.785 - * COMMENT 0 or 1 1.786 - * RECURRENCE-ID 0 or 1 MUST only if referring to an instance of a 1.787 - * recurring calendar component. Otherwise it 1.788 - * MUST NOT be present. 1.789 - * REQUEST-STATUS 0+ 1.790 - * SEQUENCE 0 OR 1 MUST be present if value is greater than 0, 1.791 - * MAY be present if 0 1.792 - * X-PROPERTY 0+ 1.793 - * ATTACH 0 1.794 - * ATTENDEE 0 1.795 - * CATEGORIES 0 1.796 - * CLASS 0 1.797 - * CONTACT 0 1.798 - * CREATED 0 1.799 - * DESCRIPTION 0 1.800 - * DTEND 0 1.801 - * DTSTART 0 1.802 - * DURATION 0 1.803 - * EXDATE 0 1.804 - * EXRULE 0 1.805 - * GEO 0 1.806 - * LAST-MODIFIED 0 1.807 - * LOCATION 0 1.808 - * PRIORITY 0 1.809 - * RDATE 0 1.810 - * RELATED-TO 0 1.811 - * RESOURCES 0 1.812 - * RRULE 0 1.813 - * STATUS 0 1.814 - * SUMMARY 0 1.815 - * TRANSP 0 1.816 - * URL 0 1.817 - * 1.818 - * X-COMPONENT 0+ 1.819 - * VTODO 0 1.820 - * VJOURNAL 0 1.821 - * VFREEBUSY 0 1.822 - * VTIMEZONE 0 1.823 - * VALARM 0 1.824 - * </pre> 1.825 - * 1.826 - */ 1.827 - private class DeclineCounterValidator implements Validator { 1.828 - 1.829 - private static final long serialVersionUID = 1L; 1.830 - 1.831 - public void validate() throws ValidationException { 1.832 - PropertyValidator.getInstance().assertOne(Property.DTSTAMP, getProperties()); 1.833 - PropertyValidator.getInstance().assertOne(Property.ORGANIZER, getProperties()); 1.834 - PropertyValidator.getInstance().assertOne(Property.UID, getProperties()); 1.835 - 1.836 - PropertyValidator.getInstance().assertOneOrLess(Property.RECURRENCE_ID, getProperties()); 1.837 - PropertyValidator.getInstance().assertOneOrLess(Property.SEQUENCE, getProperties()); 1.838 - 1.839 - PropertyValidator.getInstance().assertNone(Property.ATTACH, getProperties()); 1.840 - PropertyValidator.getInstance().assertNone(Property.ATTENDEE, getProperties()); 1.841 - PropertyValidator.getInstance().assertNone(Property.CATEGORIES, getProperties()); 1.842 - PropertyValidator.getInstance().assertNone(Property.CLASS, getProperties()); 1.843 - PropertyValidator.getInstance().assertNone(Property.CONTACT, getProperties()); 1.844 - PropertyValidator.getInstance().assertNone(Property.CREATED, getProperties()); 1.845 - PropertyValidator.getInstance().assertNone(Property.DESCRIPTION, getProperties()); 1.846 - PropertyValidator.getInstance().assertNone(Property.DTEND, getProperties()); 1.847 - PropertyValidator.getInstance().assertNone(Property.DTSTART, getProperties()); 1.848 - PropertyValidator.getInstance().assertNone(Property.DURATION, getProperties()); 1.849 - PropertyValidator.getInstance().assertNone(Property.EXDATE, getProperties()); 1.850 - PropertyValidator.getInstance().assertNone(Property.EXRULE, getProperties()); 1.851 - PropertyValidator.getInstance().assertNone(Property.GEO, getProperties()); 1.852 - PropertyValidator.getInstance().assertNone(Property.LAST_MODIFIED, getProperties()); 1.853 - PropertyValidator.getInstance().assertNone(Property.LOCATION, getProperties()); 1.854 - PropertyValidator.getInstance().assertNone(Property.PRIORITY, getProperties()); 1.855 - PropertyValidator.getInstance().assertNone(Property.RDATE, getProperties()); 1.856 - PropertyValidator.getInstance().assertNone(Property.RELATED_TO, getProperties()); 1.857 - PropertyValidator.getInstance().assertNone(Property.RESOURCES, getProperties()); 1.858 - PropertyValidator.getInstance().assertNone(Property.RRULE, getProperties()); 1.859 - PropertyValidator.getInstance().assertNone(Property.STATUS, getProperties()); 1.860 - PropertyValidator.getInstance().assertNone(Property.SUMMARY, getProperties()); 1.861 - PropertyValidator.getInstance().assertNone(Property.TRANSP, getProperties()); 1.862 - PropertyValidator.getInstance().assertNone(Property.URL, getProperties()); 1.863 - 1.864 - ComponentValidator.assertNone(Component.VALARM, getAlarms()); 1.865 - } 1.866 - } 1.867 - 1.868 - /** 1.869 - * METHOD:PUBLISH Validator. 1.870 - * 1.871 - * <pre> 1.872 - * Component/Property Presence 1.873 - * ------------------- ---------------------------------------------- 1.874 - * METHOD 1 MUST equal "PUBLISH" 1.875 - * VEVENT 1+ 1.876 - * DTSTAMP 1 1.877 - * DTSTART 1 1.878 - * ORGANIZER 1 1.879 - * SUMMARY 1 Can be null. 1.880 - * UID 1 1.881 - * RECURRENCE-ID 0 or 1 only if referring to an instance of a 1.882 - * recurring calendar component. Otherwise 1.883 - * it MUST NOT be present. 1.884 - * SEQUENCE 0 or 1 MUST be present if value is greater than 1.885 - * 0, MAY be present if 0 1.886 - * ATTACH 0+ 1.887 - * CATEGORIES 0 or 1 This property may contain a list of 1.888 - * values 1.889 - * CLASS 0 or 1 1.890 - * COMMENT 0 or 1 1.891 - * CONTACT 0+ 1.892 - * CREATED 0 or 1 1.893 - * DESCRIPTION 0 or 1 Can be null 1.894 - * DTEND 0 or 1 if present DURATION MUST NOT be present 1.895 - * DURATION 0 or 1 if present DTEND MUST NOT be present 1.896 - * EXDATE 0+ 1.897 - * EXRULE 0+ 1.898 - * GEO 0 or 1 1.899 - * LAST-MODIFIED 0 or 1 1.900 - * LOCATION 0 or 1 1.901 - * PRIORITY 0 or 1 1.902 - * RDATE 0+ 1.903 - * RELATED-TO 0+ 1.904 - * RESOURCES 0 or 1 This property MAY contain a list of values 1.905 - * RRULE 0+ 1.906 - * STATUS 0 or 1 MAY be one of TENTATIVE/CONFIRMED/CANCELLED 1.907 - * TRANSP 0 or 1 1.908 - * URL 0 or 1 1.909 - * X-PROPERTY 0+ 1.910 - * 1.911 - * ATTENDEE 0 1.912 - * REQUEST-STATUS 0 1.913 - * 1.914 - * VALARM 0+ 1.915 - * VFREEBUSY 0 1.916 - * VJOURNAL 0 1.917 - * VTODO 0 1.918 - * VTIMEZONE 0+ MUST be present if any date/time refers to 1.919 - * a timezone 1.920 - * X-COMPONENT 0+ 1.921 - * </pre> 1.922 - * 1.923 - */ 1.924 - private class PublishValidator implements Validator { 1.925 - 1.926 - private static final long serialVersionUID = 1L; 1.927 - 1.928 - public void validate() throws ValidationException { 1.929 - PropertyValidator.getInstance().assertOne(Property.DTSTAMP, getProperties()); 1.930 - PropertyValidator.getInstance().assertOne(Property.DTSTART, getProperties()); 1.931 - 1.932 - if (!CompatibilityHints.isHintEnabled(CompatibilityHints.KEY_RELAXED_VALIDATION)) { 1.933 - PropertyValidator.getInstance().assertOne(Property.ORGANIZER, getProperties()); 1.934 - PropertyValidator.getInstance().assertOne(Property.SUMMARY, getProperties()); 1.935 - } 1.936 - 1.937 - PropertyValidator.getInstance().assertOne(Property.UID, getProperties()); 1.938 - 1.939 - PropertyValidator.getInstance().assertOneOrLess(Property.RECURRENCE_ID, getProperties()); 1.940 - PropertyValidator.getInstance().assertOneOrLess(Property.SEQUENCE, getProperties()); 1.941 - PropertyValidator.getInstance().assertOneOrLess(Property.CATEGORIES, getProperties()); 1.942 - PropertyValidator.getInstance().assertOneOrLess(Property.CLASS, getProperties()); 1.943 - PropertyValidator.getInstance().assertOneOrLess(Property.CREATED, getProperties()); 1.944 - PropertyValidator.getInstance().assertOneOrLess(Property.DESCRIPTION, getProperties()); 1.945 - PropertyValidator.getInstance().assertOneOrLess(Property.DTEND, getProperties()); 1.946 - PropertyValidator.getInstance().assertOneOrLess(Property.DURATION, getProperties()); 1.947 - PropertyValidator.getInstance().assertOneOrLess(Property.GEO, getProperties()); 1.948 - PropertyValidator.getInstance().assertOneOrLess(Property.LAST_MODIFIED, getProperties()); 1.949 - PropertyValidator.getInstance().assertOneOrLess(Property.LOCATION, getProperties()); 1.950 - PropertyValidator.getInstance().assertOneOrLess(Property.PRIORITY, getProperties()); 1.951 - PropertyValidator.getInstance().assertOneOrLess(Property.RESOURCES, getProperties()); 1.952 - PropertyValidator.getInstance().assertOneOrLess(Property.STATUS, getProperties()); 1.953 - PropertyValidator.getInstance().assertOneOrLess(Property.TRANSP, getProperties()); 1.954 - PropertyValidator.getInstance().assertOneOrLess(Property.URL, getProperties()); 1.955 - 1.956 - if (!CompatibilityHints.isHintEnabled(CompatibilityHints.KEY_RELAXED_VALIDATION)) { 1.957 - PropertyValidator.getInstance().assertNone(Property.ATTENDEE, getProperties()); 1.958 - } 1.959 - 1.960 - PropertyValidator.getInstance().assertNone(Property.REQUEST_STATUS, getProperties()); 1.961 - 1.962 - for (final Iterator i = getAlarms().iterator(); i.hasNext();) { 1.963 - final VAlarm alarm = (VAlarm) i.next(); 1.964 - alarm.validate(Method.PUBLISH); 1.965 - } 1.966 - } 1.967 - } 1.968 - 1.969 - /** 1.970 - * METHOD:REFRESH Validator. 1.971 - * 1.972 - * <pre> 1.973 - * Component/Property Presence 1.974 - * ------------------- ---------------------------------------------- 1.975 - * METHOD 1 MUST be "REFRESH" 1.976 - * 1.977 - * VEVENT 1 1.978 - * ATTENDEE 1 MUST be the address of requestor 1.979 - * DTSTAMP 1 1.980 - * ORGANIZER 1 1.981 - * UID 1 MUST be the UID associated with original 1.982 - * REQUEST 1.983 - * COMMENT 0 or 1 1.984 - * RECURRENCE-ID 0 or 1 MUST only if referring to an instance of a 1.985 - * recurring calendar component. Otherwise 1.986 - * it must NOT be present. 1.987 - * X-PROPERTY 0+ 1.988 - * 1.989 - * ATTACH 0 1.990 - * CATEGORIES 0 1.991 - * CLASS 0 1.992 - * CONTACT 0 1.993 - * CREATED 0 1.994 - * DESCRIPTION 0 1.995 - * DTEND 0 1.996 - * DTSTART 0 1.997 - * DURATION 0 1.998 - * EXDATE 0 1.999 - * EXRULE 0 1.1000 - * GEO 0 1.1001 - * LAST-MODIFIED 0 1.1002 - * LOCATION 0 1.1003 - * PRIORITY 0 1.1004 - * RDATE 0 1.1005 - * RELATED-TO 0 1.1006 - * REQUEST-STATUS 0 1.1007 - * RESOURCES 0 1.1008 - * RRULE 0 1.1009 - * SEQUENCE 0 1.1010 - * STATUS 0 1.1011 - * SUMMARY 0 1.1012 - * TRANSP 0 1.1013 - * URL 0 1.1014 - * 1.1015 - * X-COMPONENT 0+ 1.1016 - * 1.1017 - * VTODO 0 1.1018 - * VJOURNAL 0 1.1019 - * VFREEBUSY 0 1.1020 - * VTIMEZONE 0 1.1021 - * VALARM 0 1.1022 - * </pre> 1.1023 - * 1.1024 - */ 1.1025 - private class RefreshValidator implements Validator { 1.1026 - 1.1027 - private static final long serialVersionUID = 1L; 1.1028 - 1.1029 - public void validate() throws ValidationException { 1.1030 - PropertyValidator.getInstance().assertOne(Property.ATTENDEE, getProperties()); 1.1031 - PropertyValidator.getInstance().assertOne(Property.DTSTAMP, getProperties()); 1.1032 - PropertyValidator.getInstance().assertOne(Property.ORGANIZER, getProperties()); 1.1033 - PropertyValidator.getInstance().assertOne(Property.UID, getProperties()); 1.1034 - 1.1035 - PropertyValidator.getInstance().assertOneOrLess(Property.RECURRENCE_ID, getProperties()); 1.1036 - 1.1037 - PropertyValidator.getInstance().assertNone(Property.ATTACH, getProperties()); 1.1038 - PropertyValidator.getInstance().assertNone(Property.CATEGORIES, getProperties()); 1.1039 - PropertyValidator.getInstance().assertNone(Property.CLASS, getProperties()); 1.1040 - PropertyValidator.getInstance().assertNone(Property.CONTACT, getProperties()); 1.1041 - PropertyValidator.getInstance().assertNone(Property.CREATED, getProperties()); 1.1042 - PropertyValidator.getInstance().assertNone(Property.DESCRIPTION, getProperties()); 1.1043 - PropertyValidator.getInstance().assertNone(Property.DTEND, getProperties()); 1.1044 - PropertyValidator.getInstance().assertNone(Property.DTSTART, getProperties()); 1.1045 - PropertyValidator.getInstance().assertNone(Property.DURATION, getProperties()); 1.1046 - PropertyValidator.getInstance().assertNone(Property.EXDATE, getProperties()); 1.1047 - PropertyValidator.getInstance().assertNone(Property.EXRULE, getProperties()); 1.1048 - PropertyValidator.getInstance().assertNone(Property.GEO, getProperties()); 1.1049 - PropertyValidator.getInstance().assertNone(Property.LAST_MODIFIED, getProperties()); 1.1050 - PropertyValidator.getInstance().assertNone(Property.LOCATION, getProperties()); 1.1051 - PropertyValidator.getInstance().assertNone(Property.PRIORITY, getProperties()); 1.1052 - PropertyValidator.getInstance().assertNone(Property.RDATE, getProperties()); 1.1053 - PropertyValidator.getInstance().assertNone(Property.RELATED_TO, getProperties()); 1.1054 - PropertyValidator.getInstance().assertNone(Property.REQUEST_STATUS, getProperties()); 1.1055 - PropertyValidator.getInstance().assertNone(Property.RESOURCES, getProperties()); 1.1056 - PropertyValidator.getInstance().assertNone(Property.RRULE, getProperties()); 1.1057 - PropertyValidator.getInstance().assertNone(Property.SEQUENCE, getProperties()); 1.1058 - PropertyValidator.getInstance().assertNone(Property.STATUS, getProperties()); 1.1059 - PropertyValidator.getInstance().assertNone(Property.SUMMARY, getProperties()); 1.1060 - PropertyValidator.getInstance().assertNone(Property.TRANSP, getProperties()); 1.1061 - PropertyValidator.getInstance().assertNone(Property.URL, getProperties()); 1.1062 - 1.1063 - ComponentValidator.assertNone(Component.VALARM, getAlarms()); 1.1064 - } 1.1065 - } 1.1066 - 1.1067 - /** 1.1068 - * METHOD:REPLY Validator. 1.1069 - * 1.1070 - * <pre> 1.1071 - * Component/Property Presence 1.1072 - * ------------------- ---------------------------------------------- 1.1073 - * METHOD 1 MUST be "REPLY" 1.1074 - * VEVENT 1+ All components MUST have the same UID 1.1075 - * ATTENDEE 1 MUST be the address of the Attendee 1.1076 - * replying. 1.1077 - * DTSTAMP 1 1.1078 - * ORGANIZER 1 1.1079 - * RECURRENCE-ID 0 or 1 only if referring to an instance of a 1.1080 - * recurring calendar component. Otherwise 1.1081 - * it must NOT be present. 1.1082 - * UID 1 MUST be the UID of the original REQUEST 1.1083 - * 1.1084 - * SEQUENCE 0 or 1 MUST if non-zero, MUST be the sequence 1.1085 - * number of the original REQUEST. MAY be 1.1086 - * present if 0. 1.1087 - * 1.1088 - * ATTACH 0+ 1.1089 - * CATEGORIES 0 or 1 This property may contain a list of values 1.1090 - * CLASS 0 or 1 1.1091 - * COMMENT 0 or 1 1.1092 - * CONTACT 0+ 1.1093 - * CREATED 0 or 1 1.1094 - * DESCRIPTION 0 or 1 1.1095 - * DTEND 0 or 1 if present DURATION MUST NOT be present 1.1096 - * DTSTART 0 or 1 1.1097 - * DURATION 0 or 1 if present DTEND MUST NOT be present 1.1098 - * EXDATE 0+ 1.1099 - * EXRULE 0+ 1.1100 - * GEO 0 or 1 1.1101 - * LAST-MODIFIED 0 or 1 1.1102 - * LOCATION 0 or 1 1.1103 - * PRIORITY 0 or 1 1.1104 - * RDATE 0+ 1.1105 - * RELATED-TO 0+ 1.1106 - * RESOURCES 0 or 1 This property MAY contain a list of values 1.1107 - * REQUEST-STATUS 0+ 1.1108 - * RRULE 0+ 1.1109 - * STATUS 0 or 1 1.1110 - * SUMMARY 0 or 1 1.1111 - * TRANSP 0 or 1 1.1112 - * URL 0 or 1 1.1113 - * X-PROPERTY 0+ 1.1114 - * 1.1115 - * VTIMEZONE 0 or 1 MUST be present if any date/time refers 1.1116 - * to a timezone 1.1117 - * X-COMPONENT 0+ 1.1118 - * 1.1119 - * VALARM 0 1.1120 - * VFREEBUSY 0 1.1121 - * VJOURNAL 0 1.1122 - * VTODO 0 1.1123 - * </pre> 1.1124 - * 1.1125 - */ 1.1126 - private class ReplyValidator implements Validator { 1.1127 - 1.1128 - private static final long serialVersionUID = 1L; 1.1129 - 1.1130 - public void validate() throws ValidationException { 1.1131 - PropertyValidator.getInstance().assertOne(Property.ATTENDEE, getProperties()); 1.1132 - PropertyValidator.getInstance().assertOne(Property.DTSTAMP, getProperties()); 1.1133 - PropertyValidator.getInstance().assertOne(Property.ORGANIZER, getProperties()); 1.1134 - PropertyValidator.getInstance().assertOne(Property.UID, getProperties()); 1.1135 - 1.1136 - PropertyValidator.getInstance().assertOneOrLess(Property.RECURRENCE_ID, getProperties()); 1.1137 - PropertyValidator.getInstance().assertOneOrLess(Property.SEQUENCE, getProperties()); 1.1138 - PropertyValidator.getInstance().assertOneOrLess(Property.CATEGORIES, getProperties()); 1.1139 - PropertyValidator.getInstance().assertOneOrLess(Property.CLASS, getProperties()); 1.1140 - PropertyValidator.getInstance().assertOneOrLess(Property.CREATED, getProperties()); 1.1141 - PropertyValidator.getInstance().assertOneOrLess(Property.DESCRIPTION, getProperties()); 1.1142 - PropertyValidator.getInstance().assertOneOrLess(Property.DTEND, getProperties()); 1.1143 - PropertyValidator.getInstance().assertOneOrLess(Property.DTSTART, getProperties()); 1.1144 - PropertyValidator.getInstance().assertOneOrLess(Property.DURATION, getProperties()); 1.1145 - PropertyValidator.getInstance().assertOneOrLess(Property.GEO, getProperties()); 1.1146 - PropertyValidator.getInstance().assertOneOrLess(Property.LAST_MODIFIED, getProperties()); 1.1147 - PropertyValidator.getInstance().assertOneOrLess(Property.LOCATION, getProperties()); 1.1148 - PropertyValidator.getInstance().assertOneOrLess(Property.PRIORITY, getProperties()); 1.1149 - PropertyValidator.getInstance().assertOneOrLess(Property.RESOURCES, getProperties()); 1.1150 - PropertyValidator.getInstance().assertOneOrLess(Property.STATUS, getProperties()); 1.1151 - PropertyValidator.getInstance().assertOneOrLess(Property.SUMMARY, getProperties()); 1.1152 - PropertyValidator.getInstance().assertOneOrLess(Property.TRANSP, getProperties()); 1.1153 - PropertyValidator.getInstance().assertOneOrLess(Property.URL, getProperties()); 1.1154 - 1.1155 - ComponentValidator.assertNone(Component.VALARM, getAlarms()); 1.1156 - } 1.1157 - } 1.1158 - 1.1159 - /** 1.1160 - * METHOD:REQUEST Validator. 1.1161 - * 1.1162 - * <pre> 1.1163 - * Component/Property Presence 1.1164 - * ----------------------------------------------------------------- 1.1165 - * METHOD 1 MUST be "REQUEST" 1.1166 - * VEVENT 1+ All components MUST have the same UID 1.1167 - * ATTENDEE 1+ 1.1168 - * DTSTAMP 1 1.1169 - * DTSTART 1 1.1170 - * ORGANIZER 1 1.1171 - * SEQUENCE 0 or 1 MUST be present if value is greater than 0, 1.1172 - * MAY be present if 0 1.1173 - * SUMMARY 1 Can be null 1.1174 - * UID 1 1.1175 - * 1.1176 - * ATTACH 0+ 1.1177 - * CATEGORIES 0 or 1 This property may contain a list of values 1.1178 - * CLASS 0 or 1 1.1179 - * COMMENT 0 or 1 1.1180 - * CONTACT 0+ 1.1181 - * CREATED 0 or 1 1.1182 - * DESCRIPTION 0 or 1 Can be null 1.1183 - * DTEND 0 or 1 if present DURATION MUST NOT be present 1.1184 - * DURATION 0 or 1 if present DTEND MUST NOT be present 1.1185 - * EXDATE 0+ 1.1186 - * EXRULE 0+ 1.1187 - * GEO 0 or 1 1.1188 - * LAST-MODIFIED 0 or 1 1.1189 - * LOCATION 0 or 1 1.1190 - * PRIORITY 0 or 1 1.1191 - * RDATE 0+ 1.1192 - * RECURRENCE-ID 0 or 1 only if referring to an instance of a 1.1193 - * recurring calendar component. Otherwise it 1.1194 - * MUST NOT be present. 1.1195 - * RELATED-TO 0+ 1.1196 - * REQUEST-STATUS 0+ 1.1197 - * RESOURCES 0 or 1 This property MAY contain a list of values 1.1198 - * RRULE 0+ 1.1199 - * STATUS 0 or 1 MAY be one of TENTATIVE/CONFIRMED 1.1200 - * TRANSP 0 or 1 1.1201 - * URL 0 or 1 1.1202 - * X-PROPERTY 0+ 1.1203 - * 1.1204 - * VALARM 0+ 1.1205 - * VTIMEZONE 0+ MUST be present if any date/time refers to 1.1206 - * a timezone 1.1207 - * X-COMPONENT 0+ 1.1208 - * VFREEBUSY 0 1.1209 - * VJOURNAL 0 1.1210 - * VTODO 0 1.1211 - * </pre> 1.1212 - * 1.1213 - */ 1.1214 - private class RequestValidator implements Validator { 1.1215 - 1.1216 - private static final long serialVersionUID = 1L; 1.1217 - 1.1218 - public void validate() throws ValidationException { 1.1219 - if (!CompatibilityHints.isHintEnabled(CompatibilityHints.KEY_RELAXED_VALIDATION)) { 1.1220 - PropertyValidator.getInstance().assertOneOrMore(Property.ATTENDEE, getProperties()); 1.1221 - } 1.1222 - 1.1223 - PropertyValidator.getInstance().assertOne(Property.DTSTAMP, getProperties()); 1.1224 - PropertyValidator.getInstance().assertOne(Property.DTSTART, getProperties()); 1.1225 - PropertyValidator.getInstance().assertOne(Property.ORGANIZER, getProperties()); 1.1226 - PropertyValidator.getInstance().assertOne(Property.SUMMARY, getProperties()); 1.1227 - PropertyValidator.getInstance().assertOne(Property.UID, getProperties()); 1.1228 - 1.1229 - PropertyValidator.getInstance().assertOneOrLess(Property.SEQUENCE, getProperties()); 1.1230 - PropertyValidator.getInstance().assertOneOrLess(Property.CATEGORIES, getProperties()); 1.1231 - PropertyValidator.getInstance().assertOneOrLess(Property.CLASS, getProperties()); 1.1232 - PropertyValidator.getInstance().assertOneOrLess(Property.CREATED, getProperties()); 1.1233 - PropertyValidator.getInstance().assertOneOrLess(Property.DESCRIPTION, getProperties()); 1.1234 - PropertyValidator.getInstance().assertOneOrLess(Property.DTEND, getProperties()); 1.1235 - PropertyValidator.getInstance().assertOneOrLess(Property.DURATION, getProperties()); 1.1236 - PropertyValidator.getInstance().assertOneOrLess(Property.GEO, getProperties()); 1.1237 - PropertyValidator.getInstance().assertOneOrLess(Property.LAST_MODIFIED, getProperties()); 1.1238 - PropertyValidator.getInstance().assertOneOrLess(Property.LOCATION, getProperties()); 1.1239 - PropertyValidator.getInstance().assertOneOrLess(Property.PRIORITY, getProperties()); 1.1240 - PropertyValidator.getInstance().assertOneOrLess(Property.RECURRENCE_ID, getProperties()); 1.1241 - PropertyValidator.getInstance().assertOneOrLess(Property.RESOURCES, getProperties()); 1.1242 - PropertyValidator.getInstance().assertOneOrLess(Property.STATUS, getProperties()); 1.1243 - PropertyValidator.getInstance().assertOneOrLess(Property.TRANSP, getProperties()); 1.1244 - PropertyValidator.getInstance().assertOneOrLess(Property.URL, getProperties()); 1.1245 - 1.1246 - for (final Iterator i = getAlarms().iterator(); i.hasNext();) { 1.1247 - final VAlarm alarm = (VAlarm) i.next(); 1.1248 - alarm.validate(Method.REQUEST); 1.1249 - } 1.1250 - } 1.1251 - } 1.1252 - /** 1.1253 - * Returns a normalised list of periods representing the consumed time for this event. 1.1254 - * @param rangeStart the start of a range 1.1255 - * @param rangeEnd the end of a range 1.1256 - * @return a normalised list of periods representing consumed time for this event 1.1257 - * @see VEvent#getConsumedTime(Date, Date, boolean) 1.1258 - */ 1.1259 - public final PeriodList getConsumedTime(final Date rangeStart, 1.1260 - final Date rangeEnd) { 1.1261 - return getConsumedTime(rangeStart, rangeEnd, true); 1.1262 - } 1.1263 - 1.1264 - /** 1.1265 - * Returns a list of periods representing the consumed time for this event in the specified range. Note that the 1.1266 - * returned list may contain a single period for non-recurring components or multiple periods for recurring 1.1267 - * components. If no time is consumed by this event an empty list is returned. 1.1268 - * @param rangeStart the start of the range to check for consumed time 1.1269 - * @param rangeEnd the end of the range to check for consumed time 1.1270 - * @param normalise indicate whether the returned list of periods should be normalised 1.1271 - * @return a list of periods representing consumed time for this event 1.1272 - */ 1.1273 - public final PeriodList getConsumedTime(final Date rangeStart, 1.1274 - final Date rangeEnd, final boolean normalise) { 1.1275 - PeriodList periods = new PeriodList(); 1.1276 - // if component is transparent return empty list.. 1.1277 - if (!Transp.TRANSPARENT.equals(getProperty(Property.TRANSP))) { 1.1278 - 1.1279 -// try { 1.1280 - periods = calculateRecurrenceSet(new Period(new DateTime(rangeStart), 1.1281 - new DateTime(rangeEnd))); 1.1282 -// } 1.1283 -// catch (ValidationException ve) { 1.1284 -// log.error("Invalid event data", ve); 1.1285 -// return periods; 1.1286 -// } 1.1287 - 1.1288 - // if periods already specified through recurrence, return.. 1.1289 - // ..also normalise before returning. 1.1290 - if (!periods.isEmpty() && normalise) { 1.1291 - periods = periods.normalise(); 1.1292 - } 1.1293 - } 1.1294 - 1.1295 - return periods; 1.1296 - } 1.1297 - 1.1298 - /** 1.1299 - * Returns a single occurrence of a recurring event. 1.1300 - * @param date a date on which the occurence should occur 1.1301 - * @return a single non-recurring event instance for the specified date, or null if the event doesn't 1.1302 - * occur on the specified date 1.1303 - * @throws IOException where an error occurs reading data 1.1304 - * @throws URISyntaxException where an invalid URI is encountered 1.1305 - * @throws ParseException where an error occurs parsing data 1.1306 - */ 1.1307 - public final VEvent getOccurrence(final Date date) throws IOException, 1.1308 - URISyntaxException, ParseException { 1.1309 - 1.1310 - final PeriodList consumedTime = getConsumedTime(date, date); 1.1311 - for (final Iterator i = consumedTime.iterator(); i.hasNext();) { 1.1312 - final Period p = (Period) i.next(); 1.1313 - if (p.getStart().equals(date)) { 1.1314 - final VEvent occurrence = (VEvent) this.copy(); 1.1315 - occurrence.getProperties().add(new RecurrenceId(date)); 1.1316 - return occurrence; 1.1317 - } 1.1318 - } 1.1319 - return null; 1.1320 - } 1.1321 - 1.1322 - /** 1.1323 - * @return the optional access classification property for an event 1.1324 - */ 1.1325 - public final Clazz getClassification() { 1.1326 - return (Clazz) getProperty(Property.CLASS); 1.1327 - } 1.1328 - 1.1329 - /** 1.1330 - * @return the optional creation-time property for an event 1.1331 - */ 1.1332 - public final Created getCreated() { 1.1333 - return (Created) getProperty(Property.CREATED); 1.1334 - } 1.1335 - 1.1336 - /** 1.1337 - * @return the optional description property for an event 1.1338 - */ 1.1339 - public final Description getDescription() { 1.1340 - return (Description) getProperty(Property.DESCRIPTION); 1.1341 - } 1.1342 - 1.1343 - /** 1.1344 - * Convenience method to pull the DTSTART out of the property list. 1.1345 - * @return The DtStart object representation of the start Date 1.1346 - */ 1.1347 - public final DtStart getStartDate() { 1.1348 - return (DtStart) getProperty(Property.DTSTART); 1.1349 - } 1.1350 - 1.1351 - /** 1.1352 - * @return the optional geographic position property for an event 1.1353 - */ 1.1354 - public final Geo getGeographicPos() { 1.1355 - return (Geo) getProperty(Property.GEO); 1.1356 - } 1.1357 - 1.1358 - /** 1.1359 - * @return the optional last-modified property for an event 1.1360 - */ 1.1361 - public final LastModified getLastModified() { 1.1362 - return (LastModified) getProperty(Property.LAST_MODIFIED); 1.1363 - } 1.1364 - 1.1365 - /** 1.1366 - * @return the optional location property for an event 1.1367 - */ 1.1368 - public final Location getLocation() { 1.1369 - return (Location) getProperty(Property.LOCATION); 1.1370 - } 1.1371 - 1.1372 - /** 1.1373 - * @return the optional organizer property for an event 1.1374 - */ 1.1375 - public final Organizer getOrganizer() { 1.1376 - return (Organizer) getProperty(Property.ORGANIZER); 1.1377 - } 1.1378 - 1.1379 - /** 1.1380 - * @return the optional priority property for an event 1.1381 - */ 1.1382 - public final Priority getPriority() { 1.1383 - return (Priority) getProperty(Property.PRIORITY); 1.1384 - } 1.1385 - 1.1386 - /** 1.1387 - * @return the optional date-stamp property 1.1388 - */ 1.1389 - public final DtStamp getDateStamp() { 1.1390 - return (DtStamp) getProperty(Property.DTSTAMP); 1.1391 - } 1.1392 - 1.1393 - /** 1.1394 - * @return the optional sequence number property for an event 1.1395 - */ 1.1396 - public final Sequence getSequence() { 1.1397 - return (Sequence) getProperty(Property.SEQUENCE); 1.1398 - } 1.1399 - 1.1400 - /** 1.1401 - * @return the optional status property for an event 1.1402 - */ 1.1403 - public final Status getStatus() { 1.1404 - return (Status) getProperty(Property.STATUS); 1.1405 - } 1.1406 - 1.1407 - /** 1.1408 - * @return the optional summary property for an event 1.1409 - */ 1.1410 - public final Summary getSummary() { 1.1411 - return (Summary) getProperty(Property.SUMMARY); 1.1412 - } 1.1413 - 1.1414 - /** 1.1415 - * @return the optional time transparency property for an event 1.1416 - */ 1.1417 - public final Transp getTransparency() { 1.1418 - return (Transp) getProperty(Property.TRANSP); 1.1419 - } 1.1420 - 1.1421 - /** 1.1422 - * @return the optional URL property for an event 1.1423 - */ 1.1424 - public final Url getUrl() { 1.1425 - return (Url) getProperty(Property.URL); 1.1426 - } 1.1427 - 1.1428 - /** 1.1429 - * @return the optional recurrence identifier property for an event 1.1430 - */ 1.1431 - public final RecurrenceId getRecurrenceId() { 1.1432 - return (RecurrenceId) getProperty(Property.RECURRENCE_ID); 1.1433 - } 1.1434 - 1.1435 - /** 1.1436 - * Returns the end date of this event. Where an end date is not available it will be derived from the event 1.1437 - * duration. 1.1438 - * @return a DtEnd instance, or null if one cannot be derived 1.1439 - */ 1.1440 - public final DtEnd getEndDate() { 1.1441 - return getEndDate(true); 1.1442 - } 1.1443 - 1.1444 - /** 1.1445 - * Convenience method to pull the DTEND out of the property list. If DTEND was not specified, use the DTSTART + 1.1446 - * DURATION to calculate it. 1.1447 - * @param deriveFromDuration specifies whether to derive an end date from the event duration where an end date is 1.1448 - * not found 1.1449 - * @return The end for this VEVENT. 1.1450 - */ 1.1451 - public final DtEnd getEndDate(final boolean deriveFromDuration) { 1.1452 - DtEnd dtEnd = (DtEnd) getProperty(Property.DTEND); 1.1453 - // No DTEND? No problem, we'll use the DURATION. 1.1454 - if (dtEnd == null && deriveFromDuration && getStartDate() != null) { 1.1455 - final DtStart dtStart = getStartDate(); 1.1456 - final Duration vEventDuration; 1.1457 - if (getDuration() != null) { 1.1458 - vEventDuration = getDuration(); 1.1459 - } else if (dtStart.getDate() instanceof DateTime) { 1.1460 - // If "DTSTART" is a DATE-TIME, then the event's duration is zero (see: RFC 5545, 3.6.1 Event Component) 1.1461 - vEventDuration = new Duration(new Dur(0, 0, 0, 0)); 1.1462 - } else { 1.1463 - // If "DTSTART" is a DATE, then the event's duration is one day (see: RFC 5545, 3.6.1 Event Component) 1.1464 - vEventDuration = new Duration(new Dur(1, 0, 0, 0)); 1.1465 - } 1.1466 - 1.1467 - dtEnd = new DtEnd(Dates.getInstance(vEventDuration.getDuration() 1.1468 - .getTime(dtStart.getDate()), (Value) dtStart 1.1469 - .getParameter(Parameter.VALUE))); 1.1470 - if (dtStart.isUtc()) { 1.1471 - dtEnd.setUtc(true); 1.1472 - } 1.1473 - } 1.1474 - return dtEnd; 1.1475 - } 1.1476 - 1.1477 - /** 1.1478 - * @return the optional Duration property 1.1479 - */ 1.1480 - public final Duration getDuration() { 1.1481 - return (Duration) getProperty(Property.DURATION); 1.1482 - } 1.1483 - 1.1484 - /** 1.1485 - * Returns the UID property of this component if available. 1.1486 - * @return a Uid instance, or null if no UID property exists 1.1487 - */ 1.1488 - public final Uid getUid() { 1.1489 - return (Uid) getProperty(Property.UID); 1.1490 - } 1.1491 - 1.1492 - /** 1.1493 - * {@inheritDoc} 1.1494 - */ 1.1495 - public boolean equals(final Object arg0) { 1.1496 - if (arg0 instanceof VEvent) { 1.1497 - return super.equals(arg0) 1.1498 - && ObjectUtils.equals(alarms, ((VEvent) arg0).getAlarms()); 1.1499 - } 1.1500 - return super.equals(arg0); 1.1501 - } 1.1502 - 1.1503 - /** 1.1504 - * {@inheritDoc} 1.1505 - */ 1.1506 - public int hashCode() { 1.1507 - return new HashCodeBuilder().append(getName()).append(getProperties()) 1.1508 - .append(getAlarms()).toHashCode(); 1.1509 - } 1.1510 - 1.1511 - /** 1.1512 - * Overrides default copy method to add support for copying alarm sub-components. 1.1513 - * @return a copy of the instance 1.1514 - * @throws ParseException where values in the instance cannot be parsed 1.1515 - * @throws IOException where values in the instance cannot be read 1.1516 - * @throws URISyntaxException where an invalid URI value is encountered in the instance 1.1517 - * @see net.fortuna.ical4j.model.Component#copy() 1.1518 - */ 1.1519 - public Component copy() throws ParseException, IOException, 1.1520 - URISyntaxException { 1.1521 - final VEvent copy = (VEvent) super.copy(); 1.1522 - copy.alarms = new ComponentList(alarms); 1.1523 - return copy; 1.1524 - } 1.1525 -}