src/net/fortuna/ical4j/model/Calendar.java

Tue, 10 Feb 2015 18:12:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 10 Feb 2015 18:12:00 +0100
changeset 0
fb9019fb1bf7
child 4
45d57ecba757
permissions
-rw-r--r--

Import initial revisions of existing project AndroidCaldavSyncAdapater,
forked from upstream repository at 27e8a0f8495c92e0780d450bdf0c7cec77a03a55.

michael@0 1 /**
michael@0 2 * Copyright (c) 2012, Ben Fortuna
michael@0 3 * All rights reserved.
michael@0 4 *
michael@0 5 * Redistribution and use in source and binary forms, with or without
michael@0 6 * modification, are permitted provided that the following conditions
michael@0 7 * are met:
michael@0 8 *
michael@0 9 * o Redistributions of source code must retain the above copyright
michael@0 10 * notice, this list of conditions and the following disclaimer.
michael@0 11 *
michael@0 12 * o Redistributions in binary form must reproduce the above copyright
michael@0 13 * notice, this list of conditions and the following disclaimer in the
michael@0 14 * documentation and/or other materials provided with the distribution.
michael@0 15 *
michael@0 16 * o Neither the name of Ben Fortuna nor the names of any other contributors
michael@0 17 * may be used to endorse or promote products derived from this software
michael@0 18 * without specific prior written permission.
michael@0 19 *
michael@0 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
michael@0 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
michael@0 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
michael@0 23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
michael@0 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
michael@0 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
michael@0 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
michael@0 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
michael@0 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
michael@0 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
michael@0 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
michael@0 31 */
michael@0 32 package net.fortuna.ical4j.model;
michael@0 33
michael@0 34 import java.io.IOException;
michael@0 35 import java.io.Serializable;
michael@0 36 import java.net.URISyntaxException;
michael@0 37 import java.text.ParseException;
michael@0 38 import java.util.Iterator;
michael@0 39
michael@0 40 import net.fortuna.ical4j.model.component.CalendarComponent;
michael@0 41 import net.fortuna.ical4j.model.property.CalScale;
michael@0 42 import net.fortuna.ical4j.model.property.Method;
michael@0 43 import net.fortuna.ical4j.model.property.ProdId;
michael@0 44 import net.fortuna.ical4j.model.property.Version;
michael@0 45 import net.fortuna.ical4j.model.property.XProperty;
michael@0 46 import net.fortuna.ical4j.util.CompatibilityHints;
michael@0 47 import net.fortuna.ical4j.util.ComponentValidator;
michael@0 48 import net.fortuna.ical4j.util.PropertyValidator;
michael@0 49 import net.fortuna.ical4j.util.Strings;
michael@0 50
michael@0 51 import org.apache.commons.lang.builder.EqualsBuilder;
michael@0 52 import org.apache.commons.lang.builder.HashCodeBuilder;
michael@0 53
michael@0 54 /**
michael@0 55 * $Id$ [Apr 5, 2004]
michael@0 56 *
michael@0 57 * Defines an iCalendar calendar.
michael@0 58 *
michael@0 59 * <pre>
michael@0 60 * 4.6 Calendar Components
michael@0 61 *
michael@0 62 * The body of the iCalendar object consists of a sequence of calendar
michael@0 63 * properties and one or more calendar components. The calendar
michael@0 64 * properties are attributes that apply to the calendar as a whole. The
michael@0 65 * calendar components are collections of properties that express a
michael@0 66 * particular calendar semantic. For example, the calendar component can
michael@0 67 * specify an event, a to-do, a journal entry, time zone information, or
michael@0 68 * free/busy time information, or an alarm.
michael@0 69 *
michael@0 70 * The body of the iCalendar object is defined by the following
michael@0 71 * notation:
michael@0 72 *
michael@0 73 * icalbody = calprops component
michael@0 74 *
michael@0 75 * calprops = 2*(
michael@0 76 *
michael@0 77 * ; 'prodid' and 'version' are both REQUIRED,
michael@0 78 * ; but MUST NOT occur more than once
michael@0 79 *
michael@0 80 * prodid /version /
michael@0 81 *
michael@0 82 * ; 'calscale' and 'method' are optional,
michael@0 83 * ; but MUST NOT occur more than once
michael@0 84 *
michael@0 85 * calscale /
michael@0 86 * method /
michael@0 87 *
michael@0 88 * x-prop
michael@0 89 *
michael@0 90 * )
michael@0 91 *
michael@0 92 * component = 1*(eventc / todoc / journalc / freebusyc /
michael@0 93 * / timezonec / iana-comp / x-comp)
michael@0 94 *
michael@0 95 * iana-comp = &quot;BEGIN&quot; &quot;:&quot; iana-token CRLF
michael@0 96 *
michael@0 97 * 1*contentline
michael@0 98 *
michael@0 99 * &quot;END&quot; &quot;:&quot; iana-token CRLF
michael@0 100 *
michael@0 101 * x-comp = &quot;BEGIN&quot; &quot;:&quot; x-name CRLF
michael@0 102 *
michael@0 103 * 1*contentline
michael@0 104 *
michael@0 105 * &quot;END&quot; &quot;:&quot; x-name CRLF
michael@0 106 * </pre>
michael@0 107 *
michael@0 108 * Example 1 - Creating a new calendar:
michael@0 109 *
michael@0 110 * <pre><code>
michael@0 111 * Calendar calendar = new Calendar();
michael@0 112 * calendar.getProperties().add(new ProdId(&quot;-//Ben Fortuna//iCal4j 1.0//EN&quot;));
michael@0 113 * calendar.getProperties().add(Version.VERSION_2_0);
michael@0 114 * calendar.getProperties().add(CalScale.GREGORIAN);
michael@0 115 *
michael@0 116 * // Add events, etc..
michael@0 117 * </code></pre>
michael@0 118 *
michael@0 119 * @author Ben Fortuna
michael@0 120 */
michael@0 121 public class Calendar implements Serializable {
michael@0 122
michael@0 123 private static final long serialVersionUID = -1654118204678581940L;
michael@0 124
michael@0 125 /**
michael@0 126 * Begin token.
michael@0 127 */
michael@0 128 public static final String BEGIN = "BEGIN";
michael@0 129
michael@0 130 /**
michael@0 131 * Calendar token.
michael@0 132 */
michael@0 133 public static final String VCALENDAR = "VCALENDAR";
michael@0 134
michael@0 135 /**
michael@0 136 * End token.
michael@0 137 */
michael@0 138 public static final String END = "END";
michael@0 139
michael@0 140 private PropertyList properties;
michael@0 141
michael@0 142 private ComponentList components;
michael@0 143
michael@0 144 /**
michael@0 145 * Default constructor.
michael@0 146 */
michael@0 147 public Calendar() {
michael@0 148 this(new PropertyList(), new ComponentList());
michael@0 149 }
michael@0 150
michael@0 151 /**
michael@0 152 * Constructs a new calendar with no properties and the specified components.
michael@0 153 * @param components a list of components to add to the calendar
michael@0 154 */
michael@0 155 public Calendar(final ComponentList components) {
michael@0 156 this(new PropertyList(), components);
michael@0 157 }
michael@0 158
michael@0 159 /**
michael@0 160 * Constructor.
michael@0 161 * @param p a list of properties
michael@0 162 * @param c a list of components
michael@0 163 */
michael@0 164 public Calendar(final PropertyList p, final ComponentList c) {
michael@0 165 this.properties = p;
michael@0 166 this.components = c;
michael@0 167 }
michael@0 168
michael@0 169 /**
michael@0 170 * Creates a deep copy of the specified calendar.
michael@0 171 * @param c the calendar to copy
michael@0 172 * @throws IOException where an error occurs reading calendar data
michael@0 173 * @throws ParseException where calendar parsing fails
michael@0 174 * @throws URISyntaxException where an invalid URI string is encountered
michael@0 175 */
michael@0 176 public Calendar(Calendar c) throws ParseException, IOException,
michael@0 177 URISyntaxException {
michael@0 178
michael@0 179 this(new PropertyList(c.getProperties()), new ComponentList(c
michael@0 180 .getComponents()));
michael@0 181 }
michael@0 182
michael@0 183 /**
michael@0 184 * {@inheritDoc}
michael@0 185 */
michael@0 186 public final String toString() {
michael@0 187 final StringBuffer buffer = new StringBuffer();
michael@0 188 buffer.append(BEGIN);
michael@0 189 buffer.append(':');
michael@0 190 buffer.append(VCALENDAR);
michael@0 191 buffer.append(Strings.LINE_SEPARATOR);
michael@0 192 buffer.append(getProperties());
michael@0 193 buffer.append(getComponents());
michael@0 194 buffer.append(END);
michael@0 195 buffer.append(':');
michael@0 196 buffer.append(VCALENDAR);
michael@0 197 buffer.append(Strings.LINE_SEPARATOR);
michael@0 198
michael@0 199 return buffer.toString();
michael@0 200 }
michael@0 201
michael@0 202 /**
michael@0 203 * @return Returns the components.
michael@0 204 */
michael@0 205 public final ComponentList getComponents() {
michael@0 206 return components;
michael@0 207 }
michael@0 208
michael@0 209 /**
michael@0 210 * Convenience method for retrieving a list of named components.
michael@0 211 * @param name name of components to retrieve
michael@0 212 * @return a component list containing only components with the specified name
michael@0 213 */
michael@0 214 public final ComponentList getComponents(final String name) {
michael@0 215 return getComponents().getComponents(name);
michael@0 216 }
michael@0 217
michael@0 218 /**
michael@0 219 * Convenience method for retrieving a named component.
michael@0 220 * @param name name of the component to retrieve
michael@0 221 * @return the first matching component in the component list with the specified name
michael@0 222 */
michael@0 223 public final Component getComponent(final String name) {
michael@0 224 return getComponents().getComponent(name);
michael@0 225 }
michael@0 226
michael@0 227 /**
michael@0 228 * @return Returns the properties.
michael@0 229 */
michael@0 230 public final PropertyList getProperties() {
michael@0 231 return properties;
michael@0 232 }
michael@0 233
michael@0 234 /**
michael@0 235 * Convenience method for retrieving a list of named properties.
michael@0 236 * @param name name of properties to retrieve
michael@0 237 * @return a property list containing only properties with the specified name
michael@0 238 */
michael@0 239 public final PropertyList getProperties(final String name) {
michael@0 240 return getProperties().getProperties(name);
michael@0 241 }
michael@0 242
michael@0 243 /**
michael@0 244 * Convenience method for retrieving a named property.
michael@0 245 * @param name name of the property to retrieve
michael@0 246 * @return the first matching property in the property list with the specified name
michael@0 247 */
michael@0 248 public final Property getProperty(final String name) {
michael@0 249 return getProperties().getProperty(name);
michael@0 250 }
michael@0 251
michael@0 252 /**
michael@0 253 * Perform validation on the calendar, its properties and its components in its current state.
michael@0 254 * @throws ValidationException where the calendar is not in a valid state
michael@0 255 */
michael@0 256 public final void validate() throws ValidationException {
michael@0 257 validate(true);
michael@0 258 }
michael@0 259
michael@0 260 /**
michael@0 261 * Perform validation on the calendar in its current state.
michael@0 262 * @param recurse indicates whether to validate the calendar's properties and components
michael@0 263 * @throws ValidationException where the calendar is not in a valid state
michael@0 264 */
michael@0 265 public void validate(final boolean recurse) throws ValidationException {
michael@0 266 // 'prodid' and 'version' are both REQUIRED,
michael@0 267 // but MUST NOT occur more than once
michael@0 268 PropertyValidator.getInstance().assertOne(Property.PRODID, properties);
michael@0 269 PropertyValidator.getInstance().assertOne(Property.VERSION, properties);
michael@0 270
michael@0 271 if (!CompatibilityHints.isHintEnabled(CompatibilityHints.KEY_RELAXED_VALIDATION)) {
michael@0 272 // require VERSION:2.0 for RFC2445..
michael@0 273 if (!Version.VERSION_2_0.equals(getProperty(Property.VERSION))) {
michael@0 274 throw new ValidationException("Unsupported Version: " + getProperty(Property.VERSION).getValue());
michael@0 275 }
michael@0 276 }
michael@0 277
michael@0 278 // 'calscale' and 'method' are optional,
michael@0 279 // but MUST NOT occur more than once
michael@0 280 PropertyValidator.getInstance().assertOneOrLess(Property.CALSCALE,
michael@0 281 properties);
michael@0 282 PropertyValidator.getInstance().assertOneOrLess(Property.METHOD,
michael@0 283 properties);
michael@0 284
michael@0 285 // must contain at least one component
michael@0 286 if (getComponents().isEmpty()) {
michael@0 287 throw new ValidationException(
michael@0 288 "Calendar must contain at least one component");
michael@0 289 }
michael@0 290
michael@0 291 // validate properties..
michael@0 292 for (final Iterator i = getProperties().iterator(); i.hasNext();) {
michael@0 293 final Property property = (Property) i.next();
michael@0 294
michael@0 295 if (!(property instanceof XProperty)
michael@0 296 && !property.isCalendarProperty()) {
michael@0 297 throw new ValidationException("Invalid property: "
michael@0 298 + property.getName());
michael@0 299 }
michael@0 300 }
michael@0 301
michael@0 302 // validate components..
michael@0 303 for (final Iterator i = getComponents().iterator(); i.hasNext();) {
michael@0 304 final Component component = (Component) i.next();
michael@0 305 if (!(component instanceof CalendarComponent)) {
michael@0 306 throw new ValidationException("Not a valid calendar component: " + component.getName());
michael@0 307 }
michael@0 308 }
michael@0 309
michael@0 310 // if (!CompatibilityHints.isHintEnabled(CompatibilityHints.KEY_RELAXED_VALIDATION)) {
michael@0 311 // validate method..
michael@0 312 final Method method = (Method) getProperty(Property.METHOD);
michael@0 313 if (Method.PUBLISH.equals(method)) {
michael@0 314 if (getComponent(Component.VEVENT) != null) {
michael@0 315 ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
michael@0 316 ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
michael@0 317
michael@0 318 if (!CompatibilityHints.isHintEnabled(CompatibilityHints.KEY_RELAXED_VALIDATION)) {
michael@0 319 ComponentValidator.assertNone(Component.VTODO, getComponents());
michael@0 320 }
michael@0 321 }
michael@0 322 else if (getComponent(Component.VFREEBUSY) != null) {
michael@0 323 ComponentValidator.assertNone(Component.VTODO, getComponents());
michael@0 324 ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
michael@0 325 ComponentValidator.assertNone(Component.VTIMEZONE, getComponents());
michael@0 326 ComponentValidator.assertNone(Component.VALARM, getComponents());
michael@0 327 }
michael@0 328 else if (getComponent(Component.VTODO) != null) {
michael@0 329 // ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
michael@0 330 // ComponentValidator.assertNone(Component.VEVENT, getComponents());
michael@0 331 ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
michael@0 332 }
michael@0 333 else if (getComponent(Component.VJOURNAL) != null) {
michael@0 334 // ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
michael@0 335 // ComponentValidator.assertNone(Component.VEVENT, getComponents());
michael@0 336 // ComponentValidator.assertNone(Component.VTODO, getComponents());
michael@0 337 }
michael@0 338 }
michael@0 339 else if (Method.REQUEST.equals(getProperty(Property.METHOD))) {
michael@0 340 if (getComponent(Component.VEVENT) != null) {
michael@0 341 ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
michael@0 342 ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
michael@0 343 ComponentValidator.assertNone(Component.VTODO, getComponents());
michael@0 344 }
michael@0 345 else if (getComponent(Component.VFREEBUSY) != null) {
michael@0 346 ComponentValidator.assertNone(Component.VTODO, getComponents());
michael@0 347 ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
michael@0 348 ComponentValidator.assertNone(Component.VTIMEZONE, getComponents());
michael@0 349 ComponentValidator.assertNone(Component.VALARM, getComponents());
michael@0 350 }
michael@0 351 else if (getComponent(Component.VTODO) != null) {
michael@0 352 // ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
michael@0 353 // ComponentValidator.assertNone(Component.VEVENT, getComponents());
michael@0 354 ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
michael@0 355 }
michael@0 356 }
michael@0 357 else if (Method.REPLY.equals(getProperty(Property.METHOD))) {
michael@0 358 if (getComponent(Component.VEVENT) != null) {
michael@0 359 ComponentValidator.assertOneOrLess(Component.VTIMEZONE, getComponents());
michael@0 360
michael@0 361 ComponentValidator.assertNone(Component.VALARM, getComponents());
michael@0 362 ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
michael@0 363 ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
michael@0 364 ComponentValidator.assertNone(Component.VTODO, getComponents());
michael@0 365 }
michael@0 366 else if (getComponent(Component.VFREEBUSY) != null) {
michael@0 367 ComponentValidator.assertNone(Component.VTODO, getComponents());
michael@0 368 ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
michael@0 369 ComponentValidator.assertNone(Component.VTIMEZONE, getComponents());
michael@0 370 ComponentValidator.assertNone(Component.VALARM, getComponents());
michael@0 371 }
michael@0 372 else if (getComponent(Component.VTODO) != null) {
michael@0 373 ComponentValidator.assertOneOrLess(Component.VTIMEZONE, getComponents());
michael@0 374
michael@0 375 ComponentValidator.assertNone(Component.VALARM, getComponents());
michael@0 376 // ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
michael@0 377 // ComponentValidator.assertNone(Component.VEVENT, getComponents());
michael@0 378 ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
michael@0 379 }
michael@0 380 }
michael@0 381 else if (Method.ADD.equals(getProperty(Property.METHOD))) {
michael@0 382 if (getComponent(Component.VEVENT) != null) {
michael@0 383 ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
michael@0 384 ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
michael@0 385 ComponentValidator.assertNone(Component.VTODO, getComponents());
michael@0 386 }
michael@0 387 else if (getComponent(Component.VTODO) != null) {
michael@0 388 ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
michael@0 389 // ComponentValidator.assertNone(Component.VEVENT, getComponents());
michael@0 390 ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
michael@0 391 }
michael@0 392 else if (getComponent(Component.VJOURNAL) != null) {
michael@0 393 ComponentValidator.assertOneOrLess(Component.VTIMEZONE, getComponents());
michael@0 394
michael@0 395 ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
michael@0 396 // ComponentValidator.assertNone(Component.VEVENT, getComponents());
michael@0 397 // ComponentValidator.assertNone(Component.VTODO, getComponents());
michael@0 398 }
michael@0 399 }
michael@0 400 else if (Method.CANCEL.equals(getProperty(Property.METHOD))) {
michael@0 401 if (getComponent(Component.VEVENT) != null) {
michael@0 402 ComponentValidator.assertNone(Component.VALARM, getComponents());
michael@0 403 ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
michael@0 404 ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
michael@0 405 ComponentValidator.assertNone(Component.VTODO, getComponents());
michael@0 406 }
michael@0 407 else if (getComponent(Component.VTODO) != null) {
michael@0 408 ComponentValidator.assertOneOrLess(Component.VTIMEZONE, getComponents());
michael@0 409
michael@0 410 ComponentValidator.assertNone(Component.VALARM, getComponents());
michael@0 411 ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
michael@0 412 // ComponentValidator.assertNone(Component.VEVENT, getComponents());
michael@0 413 ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
michael@0 414 }
michael@0 415 else if (getComponent(Component.VJOURNAL) != null) {
michael@0 416 ComponentValidator.assertNone(Component.VALARM, getComponents());
michael@0 417 ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
michael@0 418 // ComponentValidator.assertNone(Component.VEVENT, getComponents());
michael@0 419 // ComponentValidator.assertNone(Component.VTODO, getComponents());
michael@0 420 }
michael@0 421 }
michael@0 422 else if (Method.REFRESH.equals(getProperty(Property.METHOD))) {
michael@0 423 if (getComponent(Component.VEVENT) != null) {
michael@0 424 ComponentValidator.assertNone(Component.VALARM, getComponents());
michael@0 425 ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
michael@0 426 ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
michael@0 427 ComponentValidator.assertNone(Component.VTODO, getComponents());
michael@0 428 }
michael@0 429 else if (getComponent(Component.VTODO) != null) {
michael@0 430 ComponentValidator.assertNone(Component.VALARM, getComponents());
michael@0 431 ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
michael@0 432 // ComponentValidator.assertNone(Component.VEVENT, getComponents());
michael@0 433 ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
michael@0 434 ComponentValidator.assertNone(Component.VTIMEZONE, getComponents());
michael@0 435 }
michael@0 436 }
michael@0 437 else if (Method.COUNTER.equals(getProperty(Property.METHOD))) {
michael@0 438 if (getComponent(Component.VEVENT) != null) {
michael@0 439 ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
michael@0 440 ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
michael@0 441 ComponentValidator.assertNone(Component.VTODO, getComponents());
michael@0 442 }
michael@0 443 else if (getComponent(Component.VTODO) != null) {
michael@0 444 ComponentValidator.assertOneOrLess(Component.VTIMEZONE, getComponents());
michael@0 445
michael@0 446 ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
michael@0 447 // ComponentValidator.assertNone(Component.VEVENT, getComponents());
michael@0 448 ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
michael@0 449 }
michael@0 450 }
michael@0 451 else if (Method.DECLINE_COUNTER.equals(getProperty(Property.METHOD))) {
michael@0 452 if (getComponent(Component.VEVENT) != null) {
michael@0 453 ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
michael@0 454 ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
michael@0 455 ComponentValidator.assertNone(Component.VTODO, getComponents());
michael@0 456 ComponentValidator.assertNone(Component.VTIMEZONE, getComponents());
michael@0 457 ComponentValidator.assertNone(Component.VALARM, getComponents());
michael@0 458 }
michael@0 459 else if (getComponent(Component.VTODO) != null) {
michael@0 460 ComponentValidator.assertNone(Component.VALARM, getComponents());
michael@0 461 ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
michael@0 462 // ComponentValidator.assertNone(Component.VEVENT, getComponents());
michael@0 463 ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
michael@0 464 }
michael@0 465 }
michael@0 466 // }
michael@0 467
michael@0 468 // perform ITIP validation on components..
michael@0 469 if (method != null) {
michael@0 470 for (final Iterator i = getComponents().iterator(); i.hasNext();) {
michael@0 471 final CalendarComponent component = (CalendarComponent) i.next();
michael@0 472 component.validate(method);
michael@0 473 }
michael@0 474 }
michael@0 475
michael@0 476 if (recurse) {
michael@0 477 validateProperties();
michael@0 478 validateComponents();
michael@0 479 }
michael@0 480 }
michael@0 481
michael@0 482 /**
michael@0 483 * Invoke validation on the calendar properties in its current state.
michael@0 484 * @throws ValidationException where any of the calendar properties is not in a valid state
michael@0 485 */
michael@0 486 private void validateProperties() throws ValidationException {
michael@0 487 for (final Iterator i = getProperties().iterator(); i.hasNext();) {
michael@0 488 final Property property = (Property) i.next();
michael@0 489 property.validate();
michael@0 490 }
michael@0 491 }
michael@0 492
michael@0 493 /**
michael@0 494 * Invoke validation on the calendar components in its current state.
michael@0 495 * @throws ValidationException where any of the calendar components is not in a valid state
michael@0 496 */
michael@0 497 private void validateComponents() throws ValidationException {
michael@0 498 for (final Iterator i = getComponents().iterator(); i.hasNext();) {
michael@0 499 final Component component = (Component) i.next();
michael@0 500 component.validate();
michael@0 501 }
michael@0 502 }
michael@0 503
michael@0 504 /**
michael@0 505 * Returns the mandatory prodid property.
michael@0 506 * @return the PRODID property, or null if property doesn't exist
michael@0 507 */
michael@0 508 public final ProdId getProductId() {
michael@0 509 return (ProdId) getProperty(Property.PRODID);
michael@0 510 }
michael@0 511
michael@0 512 /**
michael@0 513 * Returns the mandatory version property.
michael@0 514 * @return the VERSION property, or null if property doesn't exist
michael@0 515 */
michael@0 516 public final Version getVersion() {
michael@0 517 return (Version) getProperty(Property.VERSION);
michael@0 518 }
michael@0 519
michael@0 520 /**
michael@0 521 * Returns the optional calscale property.
michael@0 522 * @return the CALSCALE property, or null if property doesn't exist
michael@0 523 */
michael@0 524 public final CalScale getCalendarScale() {
michael@0 525 return (CalScale) getProperty(Property.CALSCALE);
michael@0 526 }
michael@0 527
michael@0 528 /**
michael@0 529 * Returns the optional method property.
michael@0 530 * @return the METHOD property, or null if property doesn't exist
michael@0 531 */
michael@0 532 public final Method getMethod() {
michael@0 533 return (Method) getProperty(Property.METHOD);
michael@0 534 }
michael@0 535
michael@0 536 /**
michael@0 537 * {@inheritDoc}
michael@0 538 */
michael@0 539 public final boolean equals(final Object arg0) {
michael@0 540 if (arg0 instanceof Calendar) {
michael@0 541 final Calendar calendar = (Calendar) arg0;
michael@0 542 return new EqualsBuilder().append(getProperties(), calendar.getProperties())
michael@0 543 .append(getComponents(), calendar.getComponents()).isEquals();
michael@0 544 }
michael@0 545 return super.equals(arg0);
michael@0 546 }
michael@0 547
michael@0 548 /**
michael@0 549 * {@inheritDoc}
michael@0 550 */
michael@0 551 public final int hashCode() {
michael@0 552 return new HashCodeBuilder().append(getProperties()).append(
michael@0 553 getComponents()).toHashCode();
michael@0 554 }
michael@0 555 }

mercurial