src/net/fortuna/ical4j/model/component/VTimeZone.java

Tue, 10 Feb 2015 19:58:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 10 Feb 2015 19:58:00 +0100
changeset 4
45d57ecba757
parent 3
73bdfa70b04e
permissions
-rw-r--r--

Upgrade the upgraded ical4j component to use org.apache.commons.lang3.

     1 /**
     2  * Copyright (c) 2012, Ben Fortuna
     3  * All rights reserved.
     4  *
     5  * Redistribution and use in source and binary forms, with or without
     6  * modification, are permitted provided that the following conditions
     7  * are met:
     8  *
     9  *  o Redistributions of source code must retain the above copyright
    10  * notice, this list of conditions and the following disclaimer.
    11  *
    12  *  o Redistributions in binary form must reproduce the above copyright
    13  * notice, this list of conditions and the following disclaimer in the
    14  * documentation and/or other materials provided with the distribution.
    15  *
    16  *  o Neither the name of Ben Fortuna nor the names of any other contributors
    17  * may be used to endorse or promote products derived from this software
    18  * without specific prior written permission.
    19  *
    20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
    24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
    28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
    29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    31  */
    32 package net.fortuna.ical4j.model.component;
    34 import java.io.IOException;
    35 import java.net.URISyntaxException;
    36 import java.text.ParseException;
    37 import java.util.Iterator;
    39 import net.fortuna.ical4j.model.Component;
    40 import net.fortuna.ical4j.model.ComponentList;
    41 import net.fortuna.ical4j.model.Date;
    42 import net.fortuna.ical4j.model.Property;
    43 import net.fortuna.ical4j.model.PropertyList;
    44 import net.fortuna.ical4j.model.ValidationException;
    45 import net.fortuna.ical4j.model.Validator;
    46 import net.fortuna.ical4j.model.property.LastModified;
    47 import net.fortuna.ical4j.model.property.Method;
    48 import net.fortuna.ical4j.model.property.TzId;
    49 import net.fortuna.ical4j.model.property.TzUrl;
    50 import net.fortuna.ical4j.util.PropertyValidator;
    51 import net.fortuna.ical4j.util.Strings;
    53 import org.apache.commons.lang3.ObjectUtils;
    54 import org.apache.commons.lang3.builder.HashCodeBuilder;
    56 /**
    57  * $Id$ [Apr 5, 2004]
    58  *
    59  * Defines an iCalendar VTIMEZONE component.
    60  * 
    61  * <pre>
    62  *       4.6.5 Time Zone Component
    63  *  
    64  *          Component Name: VTIMEZONE
    65  *  
    66  *          Purpose: Provide a grouping of component properties that defines a
    67  *          time zone.
    68  *  
    69  *          Formal Definition: A &quot;VTIMEZONE&quot; calendar component is defined by the
    70  *          following notation:
    71  *  
    72  *            timezonec  = &quot;BEGIN&quot; &quot;:&quot; &quot;VTIMEZONE&quot; CRLF
    73  *  
    74  *                         2*(
    75  *  
    76  *                         ; 'tzid' is required, but MUST NOT occur more
    77  *                         ; than once
    78  *  
    79  *                       tzid /
    80  *  
    81  *                         ; 'last-mod' and 'tzurl' are optional,
    82  *                       but MUST NOT occur more than once
    83  *  
    84  *                       last-mod / tzurl /
    85  *  
    86  *                         ; one of 'standardc' or 'daylightc' MUST occur
    87  *                       ..; and each MAY occur more than once.
    88  *  
    89  *                       standardc / daylightc /
    90  *  
    91  *                       ; the following is optional,
    92  *                       ; and MAY occur more than once
    93  *  
    94  *                         x-prop
    95  *  
    96  *                         )
    97  *  
    98  *                         &quot;END&quot; &quot;:&quot; &quot;VTIMEZONE&quot; CRLF
    99  *  
   100  *            standardc  = &quot;BEGIN&quot; &quot;:&quot; &quot;STANDARD&quot; CRLF
   101  *  
   102  *                         tzprop
   103  *  
   104  *                         &quot;END&quot; &quot;:&quot; &quot;STANDARD&quot; CRLF
   105  *  
   106  *            daylightc  = &quot;BEGIN&quot; &quot;:&quot; &quot;DAYLIGHT&quot; CRLF
   107  *  
   108  *                         tzprop
   109  *  
   110  *                         &quot;END&quot; &quot;:&quot; &quot;DAYLIGHT&quot; CRLF
   111  *  
   112  *            tzprop     = 3*(
   113  *  
   114  *                       ; the following are each REQUIRED,
   115  *                       ; but MUST NOT occur more than once
   116  *  
   117  *                       dtstart / tzoffsetto / tzoffsetfrom /
   118  *  
   119  *                       ; the following are optional,
   120  *                       ; and MAY occur more than once
   121  *  
   122  *                       comment / rdate / rrule / tzname / x-prop
   123  *  
   124  *                       )
   125  * </pre>
   126  * 
   127  * @author Ben Fortuna
   128  */
   129 public class VTimeZone extends CalendarComponent {
   131     private static final long serialVersionUID = 5629679741050917815L;
   133     private final Validator itipValidator = new ITIPValidator();
   135     private ComponentList observances;
   137     /**
   138      * Default constructor.
   139      */
   140     public VTimeZone() {
   141         super(VTIMEZONE);
   142         this.observances = new ComponentList();
   143     }
   145     /**
   146      * Constructs a new instance containing the specified properties.
   147      * @param properties a list of properties
   148      */
   149     public VTimeZone(final PropertyList properties) {
   150         super(VTIMEZONE, properties);
   151         this.observances = new ComponentList();
   152     }
   154     /**
   155      * Constructs a new vtimezone component with no properties and the specified list of type components.
   156      * @param observances a list of type components
   157      */
   158     public VTimeZone(final ComponentList observances) {
   159         super(VTIMEZONE);
   160         this.observances = observances;
   161     }
   163     /**
   164      * Constructor.
   165      * @param properties a list of properties
   166      * @param observances a list of timezone types
   167      */
   168     public VTimeZone(final PropertyList properties,
   169             final ComponentList observances) {
   170         super(VTIMEZONE, properties);
   171         this.observances = observances;
   172     }
   174     /**
   175      * {@inheritDoc}
   176      */
   177     public final String toString() {
   178         final StringBuffer b = new StringBuffer();
   179         b.append(BEGIN);
   180         b.append(':');
   181         b.append(getName());
   182         b.append(Strings.LINE_SEPARATOR);
   183         b.append(getProperties());
   184         b.append(observances);
   185         b.append(END);
   186         b.append(':');
   187         b.append(getName());
   188         b.append(Strings.LINE_SEPARATOR);
   189         return b.toString();
   190     }
   192     /**
   193      * {@inheritDoc}
   194      */
   195     public final void validate(final boolean recurse)
   196             throws ValidationException {
   198         /*
   199          * ; 'tzid' is required, but MUST NOT occur more ; than once tzid /
   200          */
   201         PropertyValidator.getInstance().assertOne(Property.TZID,
   202                 getProperties());
   204         /*
   205          * ; 'last-mod' and 'tzurl' are optional, but MUST NOT occur more than once last-mod / tzurl /
   206          */
   207         PropertyValidator.getInstance().assertOneOrLess(Property.LAST_MODIFIED,
   208                 getProperties());
   209         PropertyValidator.getInstance().assertOneOrLess(Property.TZURL,
   210                 getProperties());
   212         /*
   213          * ; one of 'standardc' or 'daylightc' MUST occur ..; and each MAY occur more than once. standardc / daylightc /
   214          */
   215         if (getObservances().getComponent(Observance.STANDARD) == null
   216                 && getObservances().getComponent(Observance.DAYLIGHT) == null) {
   217             throw new ValidationException("Sub-components ["
   218                     + Observance.STANDARD + "," + Observance.DAYLIGHT
   219                     + "] must be specified at least once");
   220         }
   222         for (final Iterator i = getObservances().iterator(); i.hasNext();) {
   223             ((Component) i.next()).validate(recurse);
   224         }
   226         /*
   227          * ; the following is optional, ; and MAY occur more than once x-prop
   228          */
   230         if (recurse) {
   231             validateProperties();
   232         }
   233     }
   235     /**
   236      * {@inheritDoc}
   237      */
   238     protected Validator getValidator(Method method) {
   239         return itipValidator;
   240     }
   242     /**
   243      * Common validation for all iTIP methods.
   244      * 
   245      * <pre>
   246      *    Component/Property  Presence
   247      *    ------------------- ----------------------------------------------
   248      *    VTIMEZONE           0+      MUST be present if any date/time refers
   249      *                                to timezone
   250      *        DAYLIGHT        0+      MUST be one or more of either STANDARD or
   251      *                                DAYLIGHT
   252      *           COMMENT      0 or 1
   253      *           DTSTART      1       MUST be local time format
   254      *           RDATE        0+      if present RRULE MUST NOT be present
   255      *           RRULE        0+      if present RDATE MUST NOT be present
   256      *           TZNAME       0 or 1
   257      *           TZOFFSET     1
   258      *           TZOFFSETFROM 1
   259      *           TZOFFSETTO   1
   260      *           X-PROPERTY   0+
   261      *        LAST-MODIFIED   0 or 1
   262      *        STANDARD        0+      MUST be one or more of either STANDARD or
   263      *                                DAYLIGHT
   264      *           COMMENT      0 or 1
   265      *           DTSTART      1       MUST be local time format
   266      *           RDATE        0+      if present RRULE MUST NOT be present
   267      *           RRULE        0+      if present RDATE MUST NOT be present
   268      *           TZNAME       0 or 1
   269      *           TZOFFSETFROM 1
   270      *           TZOFFSETTO   1
   271      *           X-PROPERTY   0+
   272      *        TZID            1
   273      *        TZURL           0 or 1
   274      *        X-PROPERTY      0+
   275      * </pre>
   276      */
   277     private class ITIPValidator implements Validator {
   279 		private static final long serialVersionUID = 1L;
   281         /**
   282          * {@inheritDoc}
   283          */
   284         public void validate() throws ValidationException {
   285             for (final Iterator i = getObservances().iterator(); i.hasNext();) {
   286                 final Observance observance = (Observance) i.next();
   287                 PropertyValidator.getInstance().assertOne(Property.DTSTART, observance.getProperties());
   288                 PropertyValidator.getInstance().assertOne(Property.TZOFFSETFROM, observance.getProperties());
   289                 PropertyValidator.getInstance().assertOne(Property.TZOFFSETTO, observance.getProperties());
   291                 PropertyValidator.getInstance().assertOneOrLess(Property.TZNAME, observance.getProperties());
   292             }
   293         }
   294     }
   296     /**
   297      * @return Returns the types.
   298      */
   299     public final ComponentList getObservances() {
   300         return observances;
   301     }
   303     /**
   304      * Returns the latest applicable timezone observance for the specified date.
   305      * @param date the latest possible date for a timezone observance onset
   306      * @return the latest applicable timezone observance for the specified date or null if there are no applicable
   307      * observances
   308      */
   309     public final Observance getApplicableObservance(final Date date) {
   310         Observance latestObservance = null;
   311         Date latestOnset = null;
   312         for (final Iterator i = getObservances().iterator(); i.hasNext();) {
   313             final Observance observance = (Observance) i.next();
   314             final Date onset = observance.getLatestOnset(date);
   315             if (latestOnset == null
   316                     || (onset != null && onset.after(latestOnset))) {
   317                 latestOnset = onset;
   318                 latestObservance = observance;
   319             }
   320         }
   321         return latestObservance;
   322     }
   324     /**
   325      * @return the mandatory timezone identifier property
   326      */
   327     public final TzId getTimeZoneId() {
   328         return (TzId) getProperty(Property.TZID);
   329     }
   331     /**
   332      * @return the optional last-modified property
   333      */
   334     public final LastModified getLastModified() {
   335         return (LastModified) getProperty(Property.LAST_MODIFIED);
   336     }
   338     /**
   339      * @return the optional timezone url property
   340      */
   341     public final TzUrl getTimeZoneUrl() {
   342         return (TzUrl) getProperty(Property.TZURL);
   343     }
   345     /**
   346      * {@inheritDoc}
   347      */
   348     public boolean equals(final Object arg0) {
   349         if (arg0 instanceof VTimeZone) {
   350             return super.equals(arg0)
   351                     && ObjectUtils.equals(observances, ((VTimeZone) arg0)
   352                             .getObservances());
   353         }
   354         return super.equals(arg0);
   355     }
   357     /**
   358      * {@inheritDoc}
   359      */
   360     public int hashCode() {
   361         return new HashCodeBuilder().append(getName()).append(getProperties())
   362                 .append(getObservances()).toHashCode();
   363     }
   365     /**
   366      * Overrides default copy method to add support for copying observance sub-components.
   367      * @return a copy of the instance
   368      * @throws ParseException where an error occurs parsing data
   369      * @throws IOException where an error occurs reading data
   370      * @throws URISyntaxException where an invalid URI is encountered
   371      * @see net.fortuna.ical4j.model.Component#copy()
   372      */
   373     public Component copy() throws ParseException, IOException, URISyntaxException {
   374         final VTimeZone copy = (VTimeZone) super.copy();
   375         copy.observances = new ComponentList(observances);
   376         return copy;
   377     }
   378 }

mercurial