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

changeset 0
fb9019fb1bf7
child 4
45d57ecba757
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/net/fortuna/ical4j/model/Calendar.java	Tue Feb 10 18:12:00 2015 +0100
     1.3 @@ -0,0 +1,555 @@
     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;
    1.36 +
    1.37 +import java.io.IOException;
    1.38 +import java.io.Serializable;
    1.39 +import java.net.URISyntaxException;
    1.40 +import java.text.ParseException;
    1.41 +import java.util.Iterator;
    1.42 +
    1.43 +import net.fortuna.ical4j.model.component.CalendarComponent;
    1.44 +import net.fortuna.ical4j.model.property.CalScale;
    1.45 +import net.fortuna.ical4j.model.property.Method;
    1.46 +import net.fortuna.ical4j.model.property.ProdId;
    1.47 +import net.fortuna.ical4j.model.property.Version;
    1.48 +import net.fortuna.ical4j.model.property.XProperty;
    1.49 +import net.fortuna.ical4j.util.CompatibilityHints;
    1.50 +import net.fortuna.ical4j.util.ComponentValidator;
    1.51 +import net.fortuna.ical4j.util.PropertyValidator;
    1.52 +import net.fortuna.ical4j.util.Strings;
    1.53 +
    1.54 +import org.apache.commons.lang.builder.EqualsBuilder;
    1.55 +import org.apache.commons.lang.builder.HashCodeBuilder;
    1.56 +
    1.57 +/**
    1.58 + * $Id$ [Apr 5, 2004]
    1.59 + *
    1.60 + * Defines an iCalendar calendar.
    1.61 + * 
    1.62 + * <pre>
    1.63 + *    4.6 Calendar Components
    1.64 + *    
    1.65 + *       The body of the iCalendar object consists of a sequence of calendar
    1.66 + *       properties and one or more calendar components. The calendar
    1.67 + *       properties are attributes that apply to the calendar as a whole. The
    1.68 + *       calendar components are collections of properties that express a
    1.69 + *       particular calendar semantic. For example, the calendar component can
    1.70 + *       specify an event, a to-do, a journal entry, time zone information, or
    1.71 + *       free/busy time information, or an alarm.
    1.72 + *    
    1.73 + *       The body of the iCalendar object is defined by the following
    1.74 + *       notation:
    1.75 + *    
    1.76 + *         icalbody   = calprops component
    1.77 + *    
    1.78 + *         calprops   = 2*(
    1.79 + *    
    1.80 + *                    ; 'prodid' and 'version' are both REQUIRED,
    1.81 + *                    ; but MUST NOT occur more than once
    1.82 + *    
    1.83 + *                    prodid /version /
    1.84 + *    
    1.85 + *                    ; 'calscale' and 'method' are optional,
    1.86 + *                    ; but MUST NOT occur more than once
    1.87 + *    
    1.88 + *                    calscale        /
    1.89 + *                    method          /
    1.90 + *    
    1.91 + *                    x-prop
    1.92 + *    
    1.93 + *                    )
    1.94 + *    
    1.95 + *         component  = 1*(eventc / todoc / journalc / freebusyc /
    1.96 + *                    / timezonec / iana-comp / x-comp)
    1.97 + *    
    1.98 + *         iana-comp  = &quot;BEGIN&quot; &quot;:&quot; iana-token CRLF
    1.99 + *    
   1.100 + *                      1*contentline
   1.101 + *    
   1.102 + *                      &quot;END&quot; &quot;:&quot; iana-token CRLF
   1.103 + *    
   1.104 + *         x-comp     = &quot;BEGIN&quot; &quot;:&quot; x-name CRLF
   1.105 + *    
   1.106 + *                      1*contentline
   1.107 + *    
   1.108 + *                      &quot;END&quot; &quot;:&quot; x-name CRLF
   1.109 + * </pre>
   1.110 + * 
   1.111 + * Example 1 - Creating a new calendar:
   1.112 + * 
   1.113 + * <pre><code>
   1.114 + * Calendar calendar = new Calendar();
   1.115 + * calendar.getProperties().add(new ProdId(&quot;-//Ben Fortuna//iCal4j 1.0//EN&quot;));
   1.116 + * calendar.getProperties().add(Version.VERSION_2_0);
   1.117 + * calendar.getProperties().add(CalScale.GREGORIAN);
   1.118 + * 
   1.119 + * // Add events, etc..
   1.120 + * </code></pre>
   1.121 + * 
   1.122 + * @author Ben Fortuna
   1.123 + */
   1.124 +public class Calendar implements Serializable {
   1.125 +
   1.126 +    private static final long serialVersionUID = -1654118204678581940L;
   1.127 +
   1.128 +    /**
   1.129 +     * Begin token.
   1.130 +     */
   1.131 +    public static final String BEGIN = "BEGIN";
   1.132 +
   1.133 +    /**
   1.134 +     * Calendar token.
   1.135 +     */
   1.136 +    public static final String VCALENDAR = "VCALENDAR";
   1.137 +
   1.138 +    /**
   1.139 +     * End token.
   1.140 +     */
   1.141 +    public static final String END = "END";
   1.142 +
   1.143 +    private PropertyList properties;
   1.144 +
   1.145 +    private ComponentList components;
   1.146 +
   1.147 +    /**
   1.148 +     * Default constructor.
   1.149 +     */
   1.150 +    public Calendar() {
   1.151 +        this(new PropertyList(), new ComponentList());
   1.152 +    }
   1.153 +
   1.154 +    /**
   1.155 +     * Constructs a new calendar with no properties and the specified components.
   1.156 +     * @param components a list of components to add to the calendar
   1.157 +     */
   1.158 +    public Calendar(final ComponentList components) {
   1.159 +        this(new PropertyList(), components);
   1.160 +    }
   1.161 +
   1.162 +    /**
   1.163 +     * Constructor.
   1.164 +     * @param p a list of properties
   1.165 +     * @param c a list of components
   1.166 +     */
   1.167 +    public Calendar(final PropertyList p, final ComponentList c) {
   1.168 +        this.properties = p;
   1.169 +        this.components = c;
   1.170 +    }
   1.171 +
   1.172 +    /**
   1.173 +     * Creates a deep copy of the specified calendar.
   1.174 +     * @param c the calendar to copy
   1.175 +     * @throws IOException where an error occurs reading calendar data
   1.176 +     * @throws ParseException where calendar parsing fails
   1.177 +     * @throws URISyntaxException where an invalid URI string is encountered
   1.178 +     */
   1.179 +    public Calendar(Calendar c) throws ParseException, IOException,
   1.180 +            URISyntaxException {
   1.181 +        
   1.182 +        this(new PropertyList(c.getProperties()), new ComponentList(c
   1.183 +                .getComponents()));
   1.184 +    }
   1.185 +
   1.186 +    /**
   1.187 +     * {@inheritDoc}
   1.188 +     */
   1.189 +    public final String toString() {
   1.190 +        final StringBuffer buffer = new StringBuffer();
   1.191 +        buffer.append(BEGIN);
   1.192 +        buffer.append(':');
   1.193 +        buffer.append(VCALENDAR);
   1.194 +        buffer.append(Strings.LINE_SEPARATOR);
   1.195 +        buffer.append(getProperties());
   1.196 +        buffer.append(getComponents());
   1.197 +        buffer.append(END);
   1.198 +        buffer.append(':');
   1.199 +        buffer.append(VCALENDAR);
   1.200 +        buffer.append(Strings.LINE_SEPARATOR);
   1.201 +
   1.202 +        return buffer.toString();
   1.203 +    }
   1.204 +
   1.205 +    /**
   1.206 +     * @return Returns the components.
   1.207 +     */
   1.208 +    public final ComponentList getComponents() {
   1.209 +        return components;
   1.210 +    }
   1.211 +
   1.212 +    /**
   1.213 +     * Convenience method for retrieving a list of named components.
   1.214 +     * @param name name of components to retrieve
   1.215 +     * @return a component list containing only components with the specified name
   1.216 +     */
   1.217 +    public final ComponentList getComponents(final String name) {
   1.218 +        return getComponents().getComponents(name);
   1.219 +    }
   1.220 +
   1.221 +    /**
   1.222 +     * Convenience method for retrieving a named component.
   1.223 +     * @param name name of the component to retrieve
   1.224 +     * @return the first matching component in the component list with the specified name
   1.225 +     */
   1.226 +    public final Component getComponent(final String name) {
   1.227 +        return getComponents().getComponent(name);
   1.228 +    }
   1.229 +
   1.230 +    /**
   1.231 +     * @return Returns the properties.
   1.232 +     */
   1.233 +    public final PropertyList getProperties() {
   1.234 +        return properties;
   1.235 +    }
   1.236 +
   1.237 +    /**
   1.238 +     * Convenience method for retrieving a list of named properties.
   1.239 +     * @param name name of properties to retrieve
   1.240 +     * @return a property list containing only properties with the specified name
   1.241 +     */
   1.242 +    public final PropertyList getProperties(final String name) {
   1.243 +        return getProperties().getProperties(name);
   1.244 +    }
   1.245 +
   1.246 +    /**
   1.247 +     * Convenience method for retrieving a named property.
   1.248 +     * @param name name of the property to retrieve
   1.249 +     * @return the first matching property in the property list with the specified name
   1.250 +     */
   1.251 +    public final Property getProperty(final String name) {
   1.252 +        return getProperties().getProperty(name);
   1.253 +    }
   1.254 +
   1.255 +    /**
   1.256 +     * Perform validation on the calendar, its properties and its components in its current state.
   1.257 +     * @throws ValidationException where the calendar is not in a valid state
   1.258 +     */
   1.259 +    public final void validate() throws ValidationException {
   1.260 +        validate(true);
   1.261 +    }
   1.262 +
   1.263 +    /**
   1.264 +     * Perform validation on the calendar in its current state.
   1.265 +     * @param recurse indicates whether to validate the calendar's properties and components
   1.266 +     * @throws ValidationException where the calendar is not in a valid state
   1.267 +     */
   1.268 +    public void validate(final boolean recurse) throws ValidationException {
   1.269 +        // 'prodid' and 'version' are both REQUIRED,
   1.270 +        // but MUST NOT occur more than once
   1.271 +        PropertyValidator.getInstance().assertOne(Property.PRODID, properties);
   1.272 +        PropertyValidator.getInstance().assertOne(Property.VERSION, properties);
   1.273 +
   1.274 +        if (!CompatibilityHints.isHintEnabled(CompatibilityHints.KEY_RELAXED_VALIDATION)) {
   1.275 +            // require VERSION:2.0 for RFC2445..
   1.276 +            if (!Version.VERSION_2_0.equals(getProperty(Property.VERSION))) {
   1.277 +                throw new ValidationException("Unsupported Version: " + getProperty(Property.VERSION).getValue());
   1.278 +            }
   1.279 +        }
   1.280 +        
   1.281 +        // 'calscale' and 'method' are optional,
   1.282 +        // but MUST NOT occur more than once
   1.283 +        PropertyValidator.getInstance().assertOneOrLess(Property.CALSCALE,
   1.284 +                properties);
   1.285 +        PropertyValidator.getInstance().assertOneOrLess(Property.METHOD,
   1.286 +                properties);
   1.287 +
   1.288 +        // must contain at least one component
   1.289 +        if (getComponents().isEmpty()) {
   1.290 +            throw new ValidationException(
   1.291 +                    "Calendar must contain at least one component");
   1.292 +        }
   1.293 +
   1.294 +        // validate properties..
   1.295 +        for (final Iterator i = getProperties().iterator(); i.hasNext();) {
   1.296 +            final Property property = (Property) i.next();
   1.297 +
   1.298 +            if (!(property instanceof XProperty)
   1.299 +                    && !property.isCalendarProperty()) {
   1.300 +                throw new ValidationException("Invalid property: "
   1.301 +                        + property.getName());
   1.302 +            }
   1.303 +        }
   1.304 +
   1.305 +        // validate components..
   1.306 +        for (final Iterator i = getComponents().iterator(); i.hasNext();) {
   1.307 +            final Component component = (Component) i.next();
   1.308 +            if (!(component instanceof CalendarComponent)) {
   1.309 +                throw new ValidationException("Not a valid calendar component: " + component.getName());
   1.310 +            }
   1.311 +        }
   1.312 +
   1.313 +//        if (!CompatibilityHints.isHintEnabled(CompatibilityHints.KEY_RELAXED_VALIDATION)) {
   1.314 +            // validate method..
   1.315 +            final Method method = (Method) getProperty(Property.METHOD);
   1.316 +            if (Method.PUBLISH.equals(method)) {
   1.317 +                if (getComponent(Component.VEVENT) != null) {
   1.318 +                    ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
   1.319 +                    ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
   1.320 +                    
   1.321 +                    if (!CompatibilityHints.isHintEnabled(CompatibilityHints.KEY_RELAXED_VALIDATION)) {
   1.322 +                        ComponentValidator.assertNone(Component.VTODO, getComponents());
   1.323 +                    }
   1.324 +                }
   1.325 +                else if (getComponent(Component.VFREEBUSY) != null) {
   1.326 +                    ComponentValidator.assertNone(Component.VTODO, getComponents());
   1.327 +                    ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
   1.328 +                    ComponentValidator.assertNone(Component.VTIMEZONE, getComponents());
   1.329 +                    ComponentValidator.assertNone(Component.VALARM, getComponents());
   1.330 +                }
   1.331 +                else if (getComponent(Component.VTODO) != null) {
   1.332 +//                    ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
   1.333 +//                    ComponentValidator.assertNone(Component.VEVENT, getComponents());
   1.334 +                    ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
   1.335 +                }
   1.336 +                else if (getComponent(Component.VJOURNAL) != null) {
   1.337 +//                    ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
   1.338 +//                    ComponentValidator.assertNone(Component.VEVENT, getComponents());
   1.339 +//                    ComponentValidator.assertNone(Component.VTODO, getComponents());
   1.340 +                }
   1.341 +            }
   1.342 +            else if (Method.REQUEST.equals(getProperty(Property.METHOD))) {
   1.343 +                if (getComponent(Component.VEVENT) != null) {
   1.344 +                    ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
   1.345 +                    ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
   1.346 +                    ComponentValidator.assertNone(Component.VTODO, getComponents());
   1.347 +                }
   1.348 +                else if (getComponent(Component.VFREEBUSY) != null) {
   1.349 +                    ComponentValidator.assertNone(Component.VTODO, getComponents());
   1.350 +                    ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
   1.351 +                    ComponentValidator.assertNone(Component.VTIMEZONE, getComponents());
   1.352 +                    ComponentValidator.assertNone(Component.VALARM, getComponents());
   1.353 +                }
   1.354 +                else if (getComponent(Component.VTODO) != null) {
   1.355 +//                  ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
   1.356 +//                  ComponentValidator.assertNone(Component.VEVENT, getComponents());
   1.357 +                    ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
   1.358 +                }
   1.359 +            }
   1.360 +            else if (Method.REPLY.equals(getProperty(Property.METHOD))) {
   1.361 +                if (getComponent(Component.VEVENT) != null) {
   1.362 +                    ComponentValidator.assertOneOrLess(Component.VTIMEZONE, getComponents());
   1.363 +                    
   1.364 +                    ComponentValidator.assertNone(Component.VALARM, getComponents());
   1.365 +                    ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
   1.366 +                    ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
   1.367 +                    ComponentValidator.assertNone(Component.VTODO, getComponents());
   1.368 +                }
   1.369 +                else if (getComponent(Component.VFREEBUSY) != null) {
   1.370 +                    ComponentValidator.assertNone(Component.VTODO, getComponents());
   1.371 +                    ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
   1.372 +                    ComponentValidator.assertNone(Component.VTIMEZONE, getComponents());
   1.373 +                    ComponentValidator.assertNone(Component.VALARM, getComponents());
   1.374 +                }
   1.375 +                else if (getComponent(Component.VTODO) != null) {
   1.376 +                    ComponentValidator.assertOneOrLess(Component.VTIMEZONE, getComponents());
   1.377 +                    
   1.378 +                    ComponentValidator.assertNone(Component.VALARM, getComponents());
   1.379 +//                  ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
   1.380 +//                  ComponentValidator.assertNone(Component.VEVENT, getComponents());
   1.381 +                    ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
   1.382 +                }
   1.383 +            }
   1.384 +            else if (Method.ADD.equals(getProperty(Property.METHOD))) {
   1.385 +                if (getComponent(Component.VEVENT) != null) {
   1.386 +                    ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
   1.387 +                    ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
   1.388 +                    ComponentValidator.assertNone(Component.VTODO, getComponents());
   1.389 +                }
   1.390 +                else if (getComponent(Component.VTODO) != null) {
   1.391 +                    ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
   1.392 +//                  ComponentValidator.assertNone(Component.VEVENT, getComponents());
   1.393 +                    ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
   1.394 +                }
   1.395 +                else if (getComponent(Component.VJOURNAL) != null) {
   1.396 +                    ComponentValidator.assertOneOrLess(Component.VTIMEZONE, getComponents());
   1.397 +                    
   1.398 +                    ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
   1.399 +//                  ComponentValidator.assertNone(Component.VEVENT, getComponents());
   1.400 +//                  ComponentValidator.assertNone(Component.VTODO, getComponents());
   1.401 +                }
   1.402 +            }
   1.403 +            else if (Method.CANCEL.equals(getProperty(Property.METHOD))) {
   1.404 +                if (getComponent(Component.VEVENT) != null) {
   1.405 +                    ComponentValidator.assertNone(Component.VALARM, getComponents());
   1.406 +                    ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
   1.407 +                    ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
   1.408 +                    ComponentValidator.assertNone(Component.VTODO, getComponents());
   1.409 +                }
   1.410 +                else if (getComponent(Component.VTODO) != null) {
   1.411 +                    ComponentValidator.assertOneOrLess(Component.VTIMEZONE, getComponents());
   1.412 +                    
   1.413 +                    ComponentValidator.assertNone(Component.VALARM, getComponents());
   1.414 +                    ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
   1.415 +//                  ComponentValidator.assertNone(Component.VEVENT, getComponents());
   1.416 +                    ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
   1.417 +                }
   1.418 +                else if (getComponent(Component.VJOURNAL) != null) {
   1.419 +                    ComponentValidator.assertNone(Component.VALARM, getComponents());
   1.420 +                    ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
   1.421 +//                  ComponentValidator.assertNone(Component.VEVENT, getComponents());
   1.422 +//                  ComponentValidator.assertNone(Component.VTODO, getComponents());
   1.423 +                }
   1.424 +            }
   1.425 +            else if (Method.REFRESH.equals(getProperty(Property.METHOD))) {
   1.426 +                if (getComponent(Component.VEVENT) != null) {
   1.427 +                    ComponentValidator.assertNone(Component.VALARM, getComponents());
   1.428 +                    ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
   1.429 +                    ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
   1.430 +                    ComponentValidator.assertNone(Component.VTODO, getComponents());
   1.431 +                }
   1.432 +                else if (getComponent(Component.VTODO) != null) {
   1.433 +                    ComponentValidator.assertNone(Component.VALARM, getComponents());
   1.434 +                    ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
   1.435 +//                  ComponentValidator.assertNone(Component.VEVENT, getComponents());
   1.436 +                    ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
   1.437 +                    ComponentValidator.assertNone(Component.VTIMEZONE, getComponents());
   1.438 +                }
   1.439 +            }
   1.440 +            else if (Method.COUNTER.equals(getProperty(Property.METHOD))) {
   1.441 +                if (getComponent(Component.VEVENT) != null) {
   1.442 +                    ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
   1.443 +                    ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
   1.444 +                    ComponentValidator.assertNone(Component.VTODO, getComponents());
   1.445 +                }
   1.446 +                else if (getComponent(Component.VTODO) != null) {
   1.447 +                    ComponentValidator.assertOneOrLess(Component.VTIMEZONE, getComponents());
   1.448 +                    
   1.449 +                    ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
   1.450 +//                  ComponentValidator.assertNone(Component.VEVENT, getComponents());
   1.451 +                    ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
   1.452 +                }
   1.453 +            }
   1.454 +            else if (Method.DECLINE_COUNTER.equals(getProperty(Property.METHOD))) {
   1.455 +                if (getComponent(Component.VEVENT) != null) {
   1.456 +                    ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
   1.457 +                    ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
   1.458 +                    ComponentValidator.assertNone(Component.VTODO, getComponents());
   1.459 +                    ComponentValidator.assertNone(Component.VTIMEZONE, getComponents());
   1.460 +                    ComponentValidator.assertNone(Component.VALARM, getComponents());
   1.461 +                }
   1.462 +                else if (getComponent(Component.VTODO) != null) {
   1.463 +                    ComponentValidator.assertNone(Component.VALARM, getComponents());
   1.464 +                    ComponentValidator.assertNone(Component.VFREEBUSY, getComponents());
   1.465 +//                  ComponentValidator.assertNone(Component.VEVENT, getComponents());
   1.466 +                    ComponentValidator.assertNone(Component.VJOURNAL, getComponents());
   1.467 +                }
   1.468 +            }
   1.469 +//        }
   1.470 +            
   1.471 +            // perform ITIP validation on components..
   1.472 +            if (method != null) {
   1.473 +                for (final Iterator i = getComponents().iterator(); i.hasNext();) {
   1.474 +                    final CalendarComponent component = (CalendarComponent) i.next();
   1.475 +                    component.validate(method);
   1.476 +                }
   1.477 +            }
   1.478 +        
   1.479 +        if (recurse) {
   1.480 +            validateProperties();
   1.481 +            validateComponents();
   1.482 +        }
   1.483 +    }
   1.484 +
   1.485 +    /**
   1.486 +     * Invoke validation on the calendar properties in its current state.
   1.487 +     * @throws ValidationException where any of the calendar properties is not in a valid state
   1.488 +     */
   1.489 +    private void validateProperties() throws ValidationException {
   1.490 +        for (final Iterator i = getProperties().iterator(); i.hasNext();) {
   1.491 +            final Property property = (Property) i.next();
   1.492 +            property.validate();
   1.493 +        }
   1.494 +    }
   1.495 +
   1.496 +    /**
   1.497 +     * Invoke validation on the calendar components in its current state.
   1.498 +     * @throws ValidationException where any of the calendar components is not in a valid state
   1.499 +     */
   1.500 +    private void validateComponents() throws ValidationException {
   1.501 +        for (final Iterator i = getComponents().iterator(); i.hasNext();) {
   1.502 +            final Component component = (Component) i.next();
   1.503 +            component.validate();
   1.504 +        }
   1.505 +    }
   1.506 +
   1.507 +    /**
   1.508 +     * Returns the mandatory prodid property.
   1.509 +     * @return the PRODID property, or null if property doesn't exist
   1.510 +     */
   1.511 +    public final ProdId getProductId() {
   1.512 +        return (ProdId) getProperty(Property.PRODID);
   1.513 +    }
   1.514 +
   1.515 +    /**
   1.516 +     * Returns the mandatory version property.
   1.517 +     * @return the VERSION property, or null if property doesn't exist
   1.518 +     */
   1.519 +    public final Version getVersion() {
   1.520 +        return (Version) getProperty(Property.VERSION);
   1.521 +    }
   1.522 +
   1.523 +    /**
   1.524 +     * Returns the optional calscale property.
   1.525 +     * @return the CALSCALE property, or null if property doesn't exist
   1.526 +     */
   1.527 +    public final CalScale getCalendarScale() {
   1.528 +        return (CalScale) getProperty(Property.CALSCALE);
   1.529 +    }
   1.530 +
   1.531 +    /**
   1.532 +     * Returns the optional method property.
   1.533 +     * @return the METHOD property, or null if property doesn't exist
   1.534 +     */
   1.535 +    public final Method getMethod() {
   1.536 +        return (Method) getProperty(Property.METHOD);
   1.537 +    }
   1.538 +
   1.539 +    /**
   1.540 +     * {@inheritDoc}
   1.541 +     */
   1.542 +    public final boolean equals(final Object arg0) {
   1.543 +        if (arg0 instanceof Calendar) {
   1.544 +            final Calendar calendar = (Calendar) arg0;
   1.545 +            return new EqualsBuilder().append(getProperties(), calendar.getProperties())
   1.546 +                .append(getComponents(), calendar.getComponents()).isEquals();
   1.547 +        }
   1.548 +        return super.equals(arg0);
   1.549 +    }
   1.550 +
   1.551 +    /**
   1.552 +     * {@inheritDoc}
   1.553 +     */
   1.554 +    public final int hashCode() {
   1.555 +        return new HashCodeBuilder().append(getProperties()).append(
   1.556 +                getComponents()).toHashCode();
   1.557 +    }
   1.558 +}

mercurial