1.1 --- a/src/net/fortuna/ical4j/model/component/VFreeBusy.java Thu Feb 12 18:02:00 2015 +0100 1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 1.3 @@ -1,805 +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.util.HashMap; 1.38 -import java.util.Iterator; 1.39 -import java.util.Map; 1.40 - 1.41 -import net.fortuna.ical4j.model.Component; 1.42 -import net.fortuna.ical4j.model.ComponentList; 1.43 -import net.fortuna.ical4j.model.DateRange; 1.44 -import net.fortuna.ical4j.model.DateTime; 1.45 -import net.fortuna.ical4j.model.Dur; 1.46 -import net.fortuna.ical4j.model.Period; 1.47 -import net.fortuna.ical4j.model.PeriodList; 1.48 -import net.fortuna.ical4j.model.Property; 1.49 -import net.fortuna.ical4j.model.PropertyList; 1.50 -import net.fortuna.ical4j.model.ValidationException; 1.51 -import net.fortuna.ical4j.model.Validator; 1.52 -import net.fortuna.ical4j.model.parameter.FbType; 1.53 -import net.fortuna.ical4j.model.property.Contact; 1.54 -import net.fortuna.ical4j.model.property.DtEnd; 1.55 -import net.fortuna.ical4j.model.property.DtStamp; 1.56 -import net.fortuna.ical4j.model.property.DtStart; 1.57 -import net.fortuna.ical4j.model.property.Duration; 1.58 -import net.fortuna.ical4j.model.property.FreeBusy; 1.59 -import net.fortuna.ical4j.model.property.Method; 1.60 -import net.fortuna.ical4j.model.property.Organizer; 1.61 -import net.fortuna.ical4j.model.property.Uid; 1.62 -import net.fortuna.ical4j.model.property.Url; 1.63 -import net.fortuna.ical4j.util.CompatibilityHints; 1.64 -import net.fortuna.ical4j.util.PropertyValidator; 1.65 - 1.66 -/** 1.67 - * $Id$ [Apr 5, 2004] 1.68 - * 1.69 - * Defines an iCalendar VFREEBUSY component. 1.70 - * 1.71 - * <pre> 1.72 - * 4.6.4 Free/Busy Component 1.73 - * 1.74 - * Component Name: VFREEBUSY 1.75 - * 1.76 - * Purpose: Provide a grouping of component properties that describe 1.77 - * either a request for free/busy time, describe a response to a request 1.78 - * for free/busy time or describe a published set of busy time. 1.79 - * 1.80 - * Formal Definition: A "VFREEBUSY" calendar component is defined by the 1.81 - * following notation: 1.82 - * 1.83 - * freebusyc = "BEGIN" ":" "VFREEBUSY" CRLF 1.84 - * fbprop 1.85 - * "END" ":" "VFREEBUSY" CRLF 1.86 - * 1.87 - * fbprop = *( 1.88 - * 1.89 - * ; the following are optional, 1.90 - * ; but MUST NOT occur more than once 1.91 - * 1.92 - * contact / dtstart / dtend / duration / dtstamp / 1.93 - * organizer / uid / url / 1.94 - * 1.95 - * ; the following are optional, 1.96 - * ; and MAY occur more than once 1.97 - * 1.98 - * attendee / comment / freebusy / rstatus / x-prop 1.99 - * 1.100 - * ) 1.101 - * 1.102 - * Description: A "VFREEBUSY" calendar component is a grouping of 1.103 - * component properties that represents either a request for, a reply to 1.104 - * a request for free or busy time information or a published set of 1.105 - * busy time information. 1.106 - * 1.107 - * When used to request free/busy time information, the "ATTENDEE" 1.108 - * property specifies the calendar users whose free/busy time is being 1.109 - * requested; the "ORGANIZER" property specifies the calendar user who 1.110 - * is requesting the free/busy time; the "DTSTART" and "DTEND" 1.111 - * properties specify the window of time for which the free/busy time is 1.112 - * being requested; the "UID" and "DTSTAMP" properties are specified to 1.113 - * assist in proper sequencing of multiple free/busy time requests. 1.114 - * 1.115 - * When used to reply to a request for free/busy time, the "ATTENDEE" 1.116 - * property specifies the calendar user responding to the free/busy time 1.117 - * request; the "ORGANIZER" property specifies the calendar user that 1.118 - * originally requested the free/busy time; the "FREEBUSY" property 1.119 - * specifies the free/busy time information (if it exists); and the 1.120 - * "UID" and "DTSTAMP" properties are specified to assist in proper 1.121 - * sequencing of multiple free/busy time replies. 1.122 - * 1.123 - * When used to publish busy time, the "ORGANIZER" property specifies 1.124 - * the calendar user associated with the published busy time; the 1.125 - * "DTSTART" and "DTEND" properties specify an inclusive time window 1.126 - * that surrounds the busy time information; the "FREEBUSY" property 1.127 - * specifies the published busy time information; and the "DTSTAMP" 1.128 - * property specifies the date/time that iCalendar object was created. 1.129 - * 1.130 - * The "VFREEBUSY" calendar component cannot be nested within another 1.131 - * calendar component. Multiple "VFREEBUSY" calendar components can be 1.132 - * specified within an iCalendar object. This permits the grouping of 1.133 - * Free/Busy information into logical collections, such as monthly 1.134 - * groups of busy time information. 1.135 - * 1.136 - * The "VFREEBUSY" calendar component is intended for use in iCalendar 1.137 - * object methods involving requests for free time, requests for busy 1.138 - * time, requests for both free and busy, and the associated replies. 1.139 - * 1.140 - * Free/Busy information is represented with the "FREEBUSY" property. 1.141 - * This property provides a terse representation of time periods. One or 1.142 - * more "FREEBUSY" properties can be specified in the "VFREEBUSY" 1.143 - * calendar component. 1.144 - * 1.145 - * When present in a "VFREEBUSY" calendar component, the "DTSTART" and 1.146 - * "DTEND" properties SHOULD be specified prior to any "FREEBUSY" 1.147 - * properties. In a free time request, these properties can be used in 1.148 - * combination with the "DURATION" property to represent a request for a 1.149 - * duration of free time within a specified window of time. 1.150 - * 1.151 - * The recurrence properties ("RRULE", "EXRULE", "RDATE", "EXDATE") are 1.152 - * not permitted within a "VFREEBUSY" calendar component. Any recurring 1.153 - * events are resolved into their individual busy time periods using the 1.154 - * "FREEBUSY" property. 1.155 - * 1.156 - * Example: The following is an example of a "VFREEBUSY" calendar 1.157 - * component used to request free or busy time information: 1.158 - * 1.159 - * BEGIN:VFREEBUSY 1.160 - * ORGANIZER:MAILTO:jane_doe@host1.com 1.161 - * ATTENDEE:MAILTO:john_public@host2.com 1.162 - * DTSTART:19971015T050000Z 1.163 - * DTEND:19971016T050000Z 1.164 - * DTSTAMP:19970901T083000Z 1.165 - * END:VFREEBUSY 1.166 - * 1.167 - * The following is an example of a "VFREEBUSY" calendar component used 1.168 - * to reply to the request with busy time information: 1.169 - * 1.170 - * BEGIN:VFREEBUSY 1.171 - * ORGANIZER:MAILTO:jane_doe@host1.com 1.172 - * ATTENDEE:MAILTO:john_public@host2.com 1.173 - * DTSTAMP:19970901T100000Z 1.174 - * FREEBUSY;VALUE=PERIOD:19971015T050000Z/PT8H30M, 1.175 - * 19971015T160000Z/PT5H30M,19971015T223000Z/PT6H30M 1.176 - * URL:http://host2.com/pub/busy/jpublic-01.ifb 1.177 - * COMMENT:This iCalendar file contains busy time information for 1.178 - * the next three months. 1.179 - * END:VFREEBUSY 1.180 - * 1.181 - * The following is an example of a "VFREEBUSY" calendar component used 1.182 - * to publish busy time information. 1.183 - * 1.184 - * BEGIN:VFREEBUSY 1.185 - * ORGANIZER:jsmith@host.com 1.186 - * DTSTART:19980313T141711Z 1.187 - * DTEND:19980410T141711Z 1.188 - * FREEBUSY:19980314T233000Z/19980315T003000Z 1.189 - * FREEBUSY:19980316T153000Z/19980316T163000Z 1.190 - * FREEBUSY:19980318T030000Z/19980318T040000Z 1.191 - * URL:http://www.host.com/calendar/busytime/jsmith.ifb 1.192 - * END:VFREEBUSY 1.193 - * </pre> 1.194 - * 1.195 - * Example 1 - Requesting all busy time slots for a given period: 1.196 - * 1.197 - * <pre><code> 1.198 - * // request all busy times between today and 1 week from now.. 1.199 - * DateTime start = new DateTime(); 1.200 - * DateTime end = new DateTime(start.getTime() + 1000 * 60 * 60 * 24 * 7); 1.201 - * 1.202 - * VFreeBusy request = new VFreeBusy(start, end); 1.203 - * 1.204 - * VFreeBusy reply = new VFreeBusy(request, calendar.getComponents()); 1.205 - * </code></pre> 1.206 - * 1.207 - * Example 2 - Requesting all free time slots for a given period of at least the specified duration: 1.208 - * 1.209 - * <pre><code> 1.210 - * // request all free time between today and 1 week from now of 1.211 - * // duration 2 hours or more.. 1.212 - * DateTime start = new DateTime(); 1.213 - * DateTime end = new DateTime(start.getTime() + 1000 * 60 * 60 * 24 * 7); 1.214 - * 1.215 - * VFreeBusy request = new VFreeBusy(start, end, new Dur(0, 2, 0, 0)); 1.216 - * 1.217 - * VFreeBusy response = new VFreeBusy(request, myCalendar.getComponents()); 1.218 - * </code></pre> 1.219 - * 1.220 - * @author Ben Fortuna 1.221 - */ 1.222 -public class VFreeBusy extends CalendarComponent { 1.223 - 1.224 - private static final long serialVersionUID = 1046534053331139832L; 1.225 - 1.226 - private final Map methodValidators = new HashMap(); 1.227 - { 1.228 - methodValidators.put(Method.PUBLISH, new PublishValidator()); 1.229 - methodValidators.put(Method.REPLY, new ReplyValidator()); 1.230 - methodValidators.put(Method.REQUEST, new RequestValidator()); 1.231 - } 1.232 - 1.233 - /** 1.234 - * Default constructor. 1.235 - */ 1.236 - public VFreeBusy() { 1.237 - super(VFREEBUSY); 1.238 - getProperties().add(new DtStamp()); 1.239 - } 1.240 - 1.241 - /** 1.242 - * Constructor. 1.243 - * @param properties a list of properties 1.244 - */ 1.245 - public VFreeBusy(final PropertyList properties) { 1.246 - super(VFREEBUSY, properties); 1.247 - } 1.248 - 1.249 - /** 1.250 - * Constructs a new VFreeBusy instance with the specified start and end boundaries. This constructor should be used 1.251 - * for requesting busy time for a specified period. 1.252 - * @param start the starting boundary for the VFreeBusy 1.253 - * @param end the ending boundary for the VFreeBusy 1.254 - */ 1.255 - public VFreeBusy(final DateTime start, final DateTime end) { 1.256 - this(); 1.257 - 1.258 - // 4.8.2.4 Date/Time Start: 1.259 - // 1.260 - // Within the "VFREEBUSY" calendar component, this property defines the 1.261 - // start date and time for the free or busy time information. The time 1.262 - // MUST be specified in UTC time. 1.263 - getProperties().add(new DtStart(start, true)); 1.264 - 1.265 - // 4.8.2.2 Date/Time End 1.266 - // 1.267 - // Within the "VFREEBUSY" calendar component, this property defines the 1.268 - // end date and time for the free or busy time information. The time 1.269 - // MUST be specified in the UTC time format. The value MUST be later in 1.270 - // time than the value of the "DTSTART" property. 1.271 - getProperties().add(new DtEnd(end, true)); 1.272 - } 1.273 - 1.274 - /** 1.275 - * Constructs a new VFreeBusy instance with the specified start and end boundaries. This constructor should be used 1.276 - * for requesting free time for a specified duration in given period defined by the start date and end date. 1.277 - * @param start the starting boundary for the VFreeBusy 1.278 - * @param end the ending boundary for the VFreeBusy 1.279 - * @param duration the length of the period being requested 1.280 - */ 1.281 - public VFreeBusy(final DateTime start, final DateTime end, final Dur duration) { 1.282 - this(); 1.283 - 1.284 - // 4.8.2.4 Date/Time Start: 1.285 - // 1.286 - // Within the "VFREEBUSY" calendar component, this property defines the 1.287 - // start date and time for the free or busy time information. The time 1.288 - // MUST be specified in UTC time. 1.289 - getProperties().add(new DtStart(start, true)); 1.290 - 1.291 - // 4.8.2.2 Date/Time End 1.292 - // 1.293 - // Within the "VFREEBUSY" calendar component, this property defines the 1.294 - // end date and time for the free or busy time information. The time 1.295 - // MUST be specified in the UTC time format. The value MUST be later in 1.296 - // time than the value of the "DTSTART" property. 1.297 - getProperties().add(new DtEnd(end, true)); 1.298 - 1.299 - getProperties().add(new Duration(duration)); 1.300 - } 1.301 - 1.302 - /** 1.303 - * Constructs a new VFreeBusy instance representing a reply to the specified VFREEBUSY request according to the 1.304 - * specified list of components. 1.305 - * If the request argument has its duration set, then the result 1.306 - * represents a list of <em>free</em> times (that is, parameter FBTYPE 1.307 - * is set to FbType.FREE). 1.308 - * If the request argument does not have its duration set, then the result 1.309 - * represents a list of <em>busy</em> times. 1.310 - * @param request a VFREEBUSY request 1.311 - * @param components a component list used to initialise busy time 1.312 - * @throws ValidationException 1.313 - */ 1.314 - public VFreeBusy(final VFreeBusy request, final ComponentList components) { 1.315 - this(); 1.316 - 1.317 - final DtStart start = (DtStart) request.getProperty(Property.DTSTART); 1.318 - 1.319 - final DtEnd end = (DtEnd) request.getProperty(Property.DTEND); 1.320 - 1.321 - final Duration duration = (Duration) request.getProperty(Property.DURATION); 1.322 - 1.323 - // 4.8.2.4 Date/Time Start: 1.324 - // 1.325 - // Within the "VFREEBUSY" calendar component, this property defines the 1.326 - // start date and time for the free or busy time information. The time 1.327 - // MUST be specified in UTC time. 1.328 - getProperties().add(new DtStart(start.getDate(), true)); 1.329 - 1.330 - // 4.8.2.2 Date/Time End 1.331 - // 1.332 - // Within the "VFREEBUSY" calendar component, this property defines the 1.333 - // end date and time for the free or busy time information. The time 1.334 - // MUST be specified in the UTC time format. The value MUST be later in 1.335 - // time than the value of the "DTSTART" property. 1.336 - getProperties().add(new DtEnd(end.getDate(), true)); 1.337 - 1.338 - if (duration != null) { 1.339 - getProperties().add(new Duration(duration.getDuration())); 1.340 - // Initialise with all free time of at least the specified duration.. 1.341 - final DateTime freeStart = new DateTime(start.getDate()); 1.342 - final DateTime freeEnd = new DateTime(end.getDate()); 1.343 - final FreeBusy fb = new FreeTimeBuilder().start(freeStart) 1.344 - .end(freeEnd) 1.345 - .duration(duration.getDuration()) 1.346 - .components(components) 1.347 - .build(); 1.348 - if (fb != null && !fb.getPeriods().isEmpty()) { 1.349 - getProperties().add(fb); 1.350 - } 1.351 - } 1.352 - else { 1.353 - // initialise with all busy time for the specified period.. 1.354 - final DateTime busyStart = new DateTime(start.getDate()); 1.355 - final DateTime busyEnd = new DateTime(end.getDate()); 1.356 - final FreeBusy fb = new BusyTimeBuilder().start(busyStart) 1.357 - .end(busyEnd) 1.358 - .components(components) 1.359 - .build(); 1.360 - if (fb != null && !fb.getPeriods().isEmpty()) { 1.361 - getProperties().add(fb); 1.362 - } 1.363 - } 1.364 - } 1.365 - 1.366 - /** 1.367 - * Create a FREEBUSY property representing the busy time for the specified component list. If the component is not 1.368 - * applicable to FREEBUSY time, or if the component is outside the bounds of the start and end dates, null is 1.369 - * returned. If no valid busy periods are identified in the component an empty FREEBUSY property is returned (i.e. 1.370 - * empty period list). 1.371 - */ 1.372 - private class BusyTimeBuilder { 1.373 - 1.374 - private DateTime start; 1.375 - 1.376 - private DateTime end; 1.377 - 1.378 - private ComponentList components; 1.379 - 1.380 - public BusyTimeBuilder start(DateTime start) { 1.381 - this.start = start; 1.382 - return this; 1.383 - } 1.384 - 1.385 - public BusyTimeBuilder end(DateTime end) { 1.386 - this.end = end; 1.387 - return this; 1.388 - } 1.389 - 1.390 - public BusyTimeBuilder components(ComponentList components) { 1.391 - this.components = components; 1.392 - return this; 1.393 - } 1.394 - 1.395 - public FreeBusy build() { 1.396 - final PeriodList periods = getConsumedTime(components, start, end); 1.397 - final DateRange range = new DateRange(start, end); 1.398 - // periods must be in UTC time for freebusy.. 1.399 - periods.setUtc(true); 1.400 - for (final Iterator i = periods.iterator(); i.hasNext();) { 1.401 - final Period period = (Period) i.next(); 1.402 - // check if period outside bounds.. 1.403 - if (!range.intersects(period)) { 1.404 - i.remove(); 1.405 - } 1.406 - } 1.407 - return new FreeBusy(periods); 1.408 - } 1.409 - } 1.410 - 1.411 - /** 1.412 - * Create a FREEBUSY property representing the free time available of the specified duration for the given list of 1.413 - * components. component. If the component is not applicable to FREEBUSY time, or if the component is outside the 1.414 - * bounds of the start and end dates, null is returned. If no valid busy periods are identified in the component an 1.415 - * empty FREEBUSY property is returned (i.e. empty period list). 1.416 - */ 1.417 - private class FreeTimeBuilder { 1.418 - 1.419 - private DateTime start; 1.420 - 1.421 - private DateTime end; 1.422 - 1.423 - private Dur duration; 1.424 - 1.425 - private ComponentList components; 1.426 - 1.427 - public FreeTimeBuilder start(DateTime start) { 1.428 - this.start = start; 1.429 - return this; 1.430 - } 1.431 - 1.432 - public FreeTimeBuilder end(DateTime end) { 1.433 - this.end = end; 1.434 - return this; 1.435 - } 1.436 - 1.437 - private FreeTimeBuilder duration(Dur duration) { 1.438 - this.duration = duration; 1.439 - return this; 1.440 - } 1.441 - 1.442 - public FreeTimeBuilder components(ComponentList components) { 1.443 - this.components = components; 1.444 - return this; 1.445 - } 1.446 - 1.447 - public FreeBusy build() { 1.448 - final FreeBusy fb = new FreeBusy(); 1.449 - fb.getParameters().add(FbType.FREE); 1.450 - final PeriodList periods = getConsumedTime(components, start, end); 1.451 - final DateRange range = new DateRange(start, end); 1.452 - // Add final consumed time to avoid special-case end-of-list processing 1.453 - periods.add(new Period(end, end)); 1.454 - DateTime lastPeriodEnd = new DateTime(start); 1.455 - // where no time is consumed set the last period end as the range start.. 1.456 - for (final Iterator i = periods.iterator(); i.hasNext();) { 1.457 - final Period period = (Period) i.next(); 1.458 - 1.459 - // check if period outside bounds.. or period intersects with the end of the range.. 1.460 - if (range.contains(period) || 1.461 - (range.intersects(period) && period.getStart().after(range.getRangeStart()))) { 1.462 - 1.463 - // calculate duration between this period start and last period end.. 1.464 - final Duration freeDuration = new Duration(lastPeriodEnd, period.getStart()); 1.465 - if (freeDuration.getDuration().compareTo(duration) >= 0) { 1.466 - fb.getPeriods().add(new Period(lastPeriodEnd, freeDuration.getDuration())); 1.467 - } 1.468 - } 1.469 - 1.470 - if (period.getEnd().after(lastPeriodEnd)) { 1.471 - lastPeriodEnd = period.getEnd(); 1.472 - } 1.473 - } 1.474 - return fb; 1.475 - } 1.476 - } 1.477 - 1.478 - /** 1.479 - * Creates a list of periods representing the time consumed by the specified list of components. 1.480 - * @param components 1.481 - * @return 1.482 - */ 1.483 - private PeriodList getConsumedTime(final ComponentList components, final DateTime rangeStart, 1.484 - final DateTime rangeEnd) { 1.485 - 1.486 - final PeriodList periods = new PeriodList(); 1.487 - // only events consume time.. 1.488 - for (final Iterator i = components.getComponents(Component.VEVENT).iterator(); i.hasNext();) { 1.489 - final Component component = (Component) i.next(); 1.490 - periods.addAll(((VEvent) component).getConsumedTime(rangeStart, rangeEnd, false)); 1.491 - } 1.492 - return periods.normalise(); 1.493 - } 1.494 - 1.495 - /** 1.496 - * {@inheritDoc} 1.497 - */ 1.498 - public final void validate(final boolean recurse) throws ValidationException { 1.499 - 1.500 - if (!CompatibilityHints.isHintEnabled(CompatibilityHints.KEY_RELAXED_VALIDATION)) { 1.501 - 1.502 - // From "4.8.4.7 Unique Identifier": 1.503 - // Conformance: The property MUST be specified in the "VEVENT", "VTODO", 1.504 - // "VJOURNAL" or "VFREEBUSY" calendar components. 1.505 - PropertyValidator.getInstance().assertOne(Property.UID, 1.506 - getProperties()); 1.507 - 1.508 - // From "4.8.7.2 Date/Time Stamp": 1.509 - // Conformance: This property MUST be included in the "VEVENT", "VTODO", 1.510 - // "VJOURNAL" or "VFREEBUSY" calendar components. 1.511 - PropertyValidator.getInstance().assertOne(Property.DTSTAMP, 1.512 - getProperties()); 1.513 - } 1.514 - 1.515 - final PropertyValidator validator = PropertyValidator.getInstance(); 1.516 - 1.517 - /* 1.518 - * ; the following are optional, ; but MUST NOT occur more than once contact / dtstart / dtend / duration / 1.519 - * dtstamp / organizer / uid / url / 1.520 - */ 1.521 - validator.assertOneOrLess(Property.CONTACT, getProperties()); 1.522 - validator.assertOneOrLess(Property.DTSTART, getProperties()); 1.523 - validator.assertOneOrLess(Property.DTEND, getProperties()); 1.524 - validator.assertOneOrLess(Property.DURATION, getProperties()); 1.525 - validator.assertOneOrLess(Property.DTSTAMP, getProperties()); 1.526 - validator.assertOneOrLess(Property.ORGANIZER, getProperties()); 1.527 - validator.assertOneOrLess(Property.UID, getProperties()); 1.528 - validator.assertOneOrLess(Property.URL, getProperties()); 1.529 - 1.530 - /* 1.531 - * ; the following are optional, ; and MAY occur more than once attendee / comment / freebusy / rstatus / x-prop 1.532 - */ 1.533 - 1.534 - /* 1.535 - * The recurrence properties ("RRULE", "EXRULE", "RDATE", "EXDATE") are not permitted within a "VFREEBUSY" 1.536 - * calendar component. Any recurring events are resolved into their individual busy time periods using the 1.537 - * "FREEBUSY" property. 1.538 - */ 1.539 - validator.assertNone(Property.RRULE, getProperties()); 1.540 - validator.assertNone(Property.EXRULE, getProperties()); 1.541 - validator.assertNone(Property.RDATE, getProperties()); 1.542 - validator.assertNone(Property.EXDATE, getProperties()); 1.543 - 1.544 - // DtEnd value must be later in time that DtStart.. 1.545 - final DtStart dtStart = (DtStart) getProperty(Property.DTSTART); 1.546 - 1.547 - // 4.8.2.4 Date/Time Start: 1.548 - // 1.549 - // Within the "VFREEBUSY" calendar component, this property defines the 1.550 - // start date and time for the free or busy time information. The time 1.551 - // MUST be specified in UTC time. 1.552 - if (dtStart != null && !dtStart.isUtc()) { 1.553 - throw new ValidationException("DTSTART must be specified in UTC time"); 1.554 - } 1.555 - 1.556 - final DtEnd dtEnd = (DtEnd) getProperty(Property.DTEND); 1.557 - 1.558 - // 4.8.2.2 Date/Time End 1.559 - // 1.560 - // Within the "VFREEBUSY" calendar component, this property defines the 1.561 - // end date and time for the free or busy time information. The time 1.562 - // MUST be specified in the UTC time format. The value MUST be later in 1.563 - // time than the value of the "DTSTART" property. 1.564 - if (dtEnd != null && !dtEnd.isUtc()) { 1.565 - throw new ValidationException("DTEND must be specified in UTC time"); 1.566 - } 1.567 - 1.568 - if (dtStart != null && dtEnd != null 1.569 - && !dtStart.getDate().before(dtEnd.getDate())) { 1.570 - throw new ValidationException("Property [" + Property.DTEND 1.571 - + "] must be later in time than [" + Property.DTSTART + "]"); 1.572 - } 1.573 - 1.574 - if (recurse) { 1.575 - validateProperties(); 1.576 - } 1.577 - } 1.578 - 1.579 - /** 1.580 - * {@inheritDoc} 1.581 - */ 1.582 - protected Validator getValidator(Method method) { 1.583 - return (Validator) methodValidators.get(method); 1.584 - } 1.585 - 1.586 - /** 1.587 - * <pre> 1.588 - * Component/Property Presence 1.589 - * ------------------- ---------------------------------------------- 1.590 - * METHOD 1 MUST be "PUBLISH" 1.591 - * 1.592 - * VFREEBUSY 1+ 1.593 - * DTSTAMP 1 1.594 - * DTSTART 1 DateTime values must be in UTC 1.595 - * DTEND 1 DateTime values must be in UTC 1.596 - * FREEBUSY 1+ MUST be BUSYTIME. Multiple instances are 1.597 - * allowed. Multiple instances must be sorted 1.598 - * in ascending order 1.599 - * ORGANIZER 1 MUST contain the address of originator of 1.600 - * busy time data. 1.601 - * UID 1 1.602 - * COMMENT 0 or 1 1.603 - * CONTACT 0+ 1.604 - * X-PROPERTY 0+ 1.605 - * URL 0 or 1 Specifies busy time URL 1.606 - * 1.607 - * ATTENDEE 0 1.608 - * DURATION 0 1.609 - * REQUEST-STATUS 0 1.610 - * 1.611 - * X-COMPONENT 0+ 1.612 - * 1.613 - * VEVENT 0 1.614 - * VTODO 0 1.615 - * VJOURNAL 0 1.616 - * VTIMEZONE 0 1.617 - * VALARM 0 1.618 - * </pre> 1.619 - * 1.620 - */ 1.621 - private class PublishValidator implements Validator { 1.622 - 1.623 - private static final long serialVersionUID = 1L; 1.624 - 1.625 - public void validate() throws ValidationException { 1.626 - PropertyValidator.getInstance().assertOneOrMore(Property.FREEBUSY, getProperties()); 1.627 - 1.628 - PropertyValidator.getInstance().assertOne(Property.DTSTAMP, getProperties()); 1.629 - PropertyValidator.getInstance().assertOne(Property.DTSTART, getProperties()); 1.630 - PropertyValidator.getInstance().assertOne(Property.DTEND, getProperties()); 1.631 - PropertyValidator.getInstance().assertOne(Property.ORGANIZER, getProperties()); 1.632 - PropertyValidator.getInstance().assertOne(Property.UID, getProperties()); 1.633 - 1.634 - PropertyValidator.getInstance().assertOneOrLess(Property.URL, getProperties()); 1.635 - 1.636 - PropertyValidator.getInstance().assertNone(Property.ATTENDEE, getProperties()); 1.637 - PropertyValidator.getInstance().assertNone(Property.DURATION, getProperties()); 1.638 - PropertyValidator.getInstance().assertNone(Property.REQUEST_STATUS, getProperties()); 1.639 - } 1.640 - } 1.641 - 1.642 - /** 1.643 - * <pre> 1.644 - * Component/Property Presence 1.645 - * ------------------- ---------------------------------------------- 1.646 - * METHOD 1 MUST be "REPLY" 1.647 - * 1.648 - * VFREEBUSY 1 1.649 - * ATTENDEE 1 (address of recipient replying) 1.650 - * DTSTAMP 1 1.651 - * DTEND 1 DateTime values must be in UTC 1.652 - * DTSTART 1 DateTime values must be in UTC 1.653 - * FREEBUSY 0+ (values MUST all be of the same data 1.654 - * type. Multiple instances are allowed. 1.655 - * Multiple instances MUST be sorted in 1.656 - * ascending order. Values MAY NOT overlap) 1.657 - * ORGANIZER 1 MUST be the request originator's address 1.658 - * UID 1 1.659 - * 1.660 - * COMMENT 0 or 1 1.661 - * CONTACT 0+ 1.662 - * REQUEST-STATUS 0+ 1.663 - * URL 0 or 1 (specifies busy time URL) 1.664 - * X-PROPERTY 0+ 1.665 - * DURATION 0 1.666 - * SEQUENCE 0 1.667 - * 1.668 - * X-COMPONENT 0+ 1.669 - * VALARM 0 1.670 - * VEVENT 0 1.671 - * VTODO 0 1.672 - * VJOURNAL 0 1.673 - * VTIMEZONE 0 1.674 - * </pre> 1.675 - * 1.676 - */ 1.677 - private class ReplyValidator implements Validator { 1.678 - 1.679 - private static final long serialVersionUID = 1L; 1.680 - 1.681 - public void validate() throws ValidationException { 1.682 - 1.683 - // FREEBUSY is 1+ in RFC2446 but 0+ in Calsify 1.684 - 1.685 - PropertyValidator.getInstance().assertOne(Property.ATTENDEE, getProperties()); 1.686 - PropertyValidator.getInstance().assertOne(Property.DTSTAMP, getProperties()); 1.687 - PropertyValidator.getInstance().assertOne(Property.DTEND, getProperties()); 1.688 - PropertyValidator.getInstance().assertOne(Property.DTSTART, getProperties()); 1.689 - PropertyValidator.getInstance().assertOne(Property.ORGANIZER, getProperties()); 1.690 - PropertyValidator.getInstance().assertOne(Property.UID, getProperties()); 1.691 - 1.692 - PropertyValidator.getInstance().assertOneOrLess(Property.URL, getProperties()); 1.693 - 1.694 - PropertyValidator.getInstance().assertNone(Property.DURATION, getProperties()); 1.695 - PropertyValidator.getInstance().assertNone(Property.SEQUENCE, getProperties()); 1.696 - } 1.697 - } 1.698 - 1.699 - /** 1.700 - * METHOD:REQUEST Validator. 1.701 - * 1.702 - * <pre> 1.703 - * Component/Property Presence 1.704 - * ------------------- ---------------------------------------------- 1.705 - * METHOD 1 MUST be "REQUEST" 1.706 - * 1.707 - * VFREEBUSY 1 1.708 - * ATTENDEE 1+ contain the address of the calendar store 1.709 - * DTEND 1 DateTime values must be in UTC 1.710 - * DTSTAMP 1 1.711 - * DTSTART 1 DateTime values must be in UTC 1.712 - * ORGANIZER 1 MUST be the request originator's address 1.713 - * UID 1 1.714 - * COMMENT 0 or 1 1.715 - * CONTACT 0+ 1.716 - * X-PROPERTY 0+ 1.717 - * 1.718 - * FREEBUSY 0 1.719 - * DURATION 0 1.720 - * REQUEST-STATUS 0 1.721 - * URL 0 1.722 - * 1.723 - * X-COMPONENT 0+ 1.724 - * VALARM 0 1.725 - * VEVENT 0 1.726 - * VTODO 0 1.727 - * VJOURNAL 0 1.728 - * VTIMEZONE 0 1.729 - * </pre> 1.730 - * 1.731 - */ 1.732 - private class RequestValidator implements Validator { 1.733 - 1.734 - private static final long serialVersionUID = 1L; 1.735 - 1.736 - public void validate() throws ValidationException { 1.737 - PropertyValidator.getInstance().assertOneOrMore(Property.ATTENDEE, getProperties()); 1.738 - 1.739 - PropertyValidator.getInstance().assertOne(Property.DTEND, getProperties()); 1.740 - PropertyValidator.getInstance().assertOne(Property.DTSTAMP, getProperties()); 1.741 - PropertyValidator.getInstance().assertOne(Property.DTSTART, getProperties()); 1.742 - PropertyValidator.getInstance().assertOne(Property.ORGANIZER, getProperties()); 1.743 - PropertyValidator.getInstance().assertOne(Property.UID, getProperties()); 1.744 - 1.745 - PropertyValidator.getInstance().assertNone(Property.FREEBUSY, getProperties()); 1.746 - PropertyValidator.getInstance().assertNone(Property.DURATION, getProperties()); 1.747 - PropertyValidator.getInstance().assertNone(Property.REQUEST_STATUS, getProperties()); 1.748 - PropertyValidator.getInstance().assertNone(Property.URL, getProperties()); 1.749 - } 1.750 - } 1.751 - 1.752 - /** 1.753 - * @return the CONTACT property or null if not specified 1.754 - */ 1.755 - public final Contact getContact() { 1.756 - return (Contact) getProperty(Property.CONTACT); 1.757 - } 1.758 - 1.759 - /** 1.760 - * @return the DTSTART propery or null if not specified 1.761 - */ 1.762 - public final DtStart getStartDate() { 1.763 - return (DtStart) getProperty(Property.DTSTART); 1.764 - } 1.765 - 1.766 - /** 1.767 - * @return the DTEND property or null if not specified 1.768 - */ 1.769 - public final DtEnd getEndDate() { 1.770 - return (DtEnd) getProperty(Property.DTEND); 1.771 - } 1.772 - 1.773 - /** 1.774 - * @return the DURATION property or null if not specified 1.775 - */ 1.776 - public final Duration getDuration() { 1.777 - return (Duration) getProperty(Property.DURATION); 1.778 - } 1.779 - 1.780 - /** 1.781 - * @return the DTSTAMP property or null if not specified 1.782 - */ 1.783 - public final DtStamp getDateStamp() { 1.784 - return (DtStamp) getProperty(Property.DTSTAMP); 1.785 - } 1.786 - 1.787 - /** 1.788 - * @return the ORGANIZER property or null if not specified 1.789 - */ 1.790 - public final Organizer getOrganizer() { 1.791 - return (Organizer) getProperty(Property.ORGANIZER); 1.792 - } 1.793 - 1.794 - /** 1.795 - * @return the URL property or null if not specified 1.796 - */ 1.797 - public final Url getUrl() { 1.798 - return (Url) getProperty(Property.URL); 1.799 - } 1.800 - 1.801 - /** 1.802 - * Returns the UID property of this component if available. 1.803 - * @return a Uid instance, or null if no UID property exists 1.804 - */ 1.805 - public final Uid getUid() { 1.806 - return (Uid) getProperty(Property.UID); 1.807 - } 1.808 -}