001    package biweekly.component;
002    
003    import java.util.Date;
004    import java.util.List;
005    
006    import biweekly.property.LastModified;
007    import biweekly.property.TimezoneId;
008    import biweekly.property.TimezoneUrl;
009    
010    /*
011     Copyright (c) 2013, Michael Angstadt
012     All rights reserved.
013    
014     Redistribution and use in source and binary forms, with or without
015     modification, are permitted provided that the following conditions are met: 
016    
017     1. Redistributions of source code must retain the above copyright notice, this
018     list of conditions and the following disclaimer. 
019     2. Redistributions in binary form must reproduce the above copyright notice,
020     this list of conditions and the following disclaimer in the documentation
021     and/or other materials provided with the distribution. 
022    
023     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
024     ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
025     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
026     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
027     ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
028     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
029     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
030     ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
031     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
032     SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
033     */
034    
035    /**
036     * <p>
037     * Defines a timezone's UTC offsets throughout the year.
038     * </p>
039     * 
040     * <p>
041     * <b>Examples:</b>
042     * 
043     * <pre class="brush:java">
044     * VTimezone timezone = new VTimezone(&quot;Eastern Standard Time&quot;);
045     * 
046     * StandardTime standard = new StandardTime();
047     * DateTimeComponents componentsStandard = new DateTimeComponents(1998, 10, 25, 2, 0, 0, false);
048     * standard.setDateStart(componentsStandard);
049     * standard.setTimezoneOffsetFrom(-4, 0);
050     * standard.setTimezoneOffsetTo(-5, 0);
051     * timezone.addStandardTime(standard);
052     * 
053     * DaylightSavingsTime daylight = new DaylightSavingsTime();
054     * DateTimeComponents componentsDaylight = new DateTimeComponents(1999, 4, 4, 2, 0, 0, false);
055     * daylight.setDateStart(componentsDaylight);
056     * daylight.setTimezoneOffsetFrom(-5, 0);
057     * daylight.setTimezoneOffsetTo(-4, 0);
058     * timezone.addDaylightSavingsTime(daylight);
059     * </pre>
060     * 
061     * </p>
062     * @author Michael Angstadt
063     * @rfc 5545 p.62-71
064     */
065    public class VTimezone extends ICalComponent {
066            /**
067             * Creates a new timezone component.
068             * @param identifier a unique identifier for this timezone (allows it to be
069             * referenced by date-time properties that support timezones).
070             */
071            public VTimezone(String identifier) {
072                    setTimezoneId(identifier);
073            }
074    
075            /**
076             * Gets the ID for this timezone. This is a <b>required</b> property.
077             * @return the timezone ID or null if not set
078             * @rfc 5545 p.102-3
079             */
080            public TimezoneId getTimezoneId() {
081                    return getProperty(TimezoneId.class);
082            }
083    
084            /**
085             * Sets an ID for this timezone. This is a <b>required</b> property.
086             * @param timezoneId the timezone ID or null to remove
087             * @rfc 5545 p.102-3
088             */
089            public void setTimezoneId(TimezoneId timezoneId) {
090                    setProperty(TimezoneId.class, timezoneId);
091            }
092    
093            /**
094             * Sets an ID for this timezone. This is a <b>required</b> property.
095             * @param timezoneId the timezone ID or null to remove
096             * @return the property that was created
097             * @rfc 5545 p.102-3
098             */
099            public TimezoneId setTimezoneId(String timezoneId) {
100                    TimezoneId prop = (timezoneId == null) ? null : new TimezoneId(timezoneId);
101                    setTimezoneId(prop);
102                    return prop;
103            }
104    
105            /**
106             * Gets the date-time that the timezone data was last changed.
107             * @return the last modified date or null if not set
108             * @rfc 5545 p.138
109             */
110            public LastModified getLastModified() {
111                    return getProperty(LastModified.class);
112            }
113    
114            /**
115             * Sets the date-time that the timezone data was last changed.
116             * @param lastModified the last modified date or null to remove
117             * @rfc 5545 p.138
118             */
119            public void setLastModified(LastModified lastModified) {
120                    setProperty(LastModified.class, lastModified);
121            }
122    
123            /**
124             * Sets the date-time that the timezone data was last changed.
125             * @param lastModified the last modified date or null to remove
126             * @return the property that was created
127             * @rfc 5545 p.138
128             */
129            public LastModified setLastModified(Date lastModified) {
130                    LastModified prop = (lastModified == null) ? null : new LastModified(lastModified);
131                    setLastModified(prop);
132                    return prop;
133            }
134    
135            /**
136             * Gets the timezone URL, which points to an iCalendar object that contains
137             * further information on the timezone.
138             * @return the URL or null if not set
139             * @rfc 5545 p.106
140             */
141            public TimezoneUrl getTimezoneUrl() {
142                    return getProperty(TimezoneUrl.class);
143            }
144    
145            /**
146             * Sets the timezone URL, which points to an iCalendar object that contains
147             * further information on the timezone.
148             * @param url the URL or null to remove
149             * @rfc 5545 p.106
150             */
151            public void setTimezoneUrl(TimezoneUrl url) {
152                    setProperty(TimezoneUrl.class, url);
153            }
154    
155            /**
156             * Sets the timezone URL, which points to an iCalendar object that contains
157             * further information on the timezone.
158             * @param url the timezone URL (e.g.
159             * "http://example.com/America-New_York.ics") or null to remove
160             * @return the property that was created
161             * @rfc 5545 p.106
162             */
163            public TimezoneUrl setTimezoneUrl(String url) {
164                    TimezoneUrl prop = (url == null) ? null : new TimezoneUrl(url);
165                    setTimezoneUrl(prop);
166                    return prop;
167            }
168    
169            /**
170             * Gets the timezone's "standard" observance time ranges.
171             * @return the "standard" observance time ranges
172             */
173            public List<StandardTime> getStandardTimes() {
174                    return getComponents(StandardTime.class);
175            }
176    
177            /**
178             * Adds a "standard" observance time range.
179             * @param standardTime the "standard" observance time
180             */
181            public void addStandardTime(StandardTime standardTime) {
182                    addComponent(standardTime);
183            }
184    
185            /**
186             * Gets the timezone's "daylight savings" observance time ranges.
187             * @return the "daylight savings" observance time ranges
188             */
189            public List<DaylightSavingsTime> getDaylightSavingsTime() {
190                    return getComponents(DaylightSavingsTime.class);
191            }
192    
193            /**
194             * Adds a "daylight savings" observance time range.
195             * @param daylightSavingsTime the "daylight savings" observance time
196             */
197            public void addDaylightSavingsTime(DaylightSavingsTime daylightSavingsTime) {
198                    addComponent(daylightSavingsTime);
199            }
200    
201            @SuppressWarnings("unchecked")
202            @Override
203            protected void validate(List<ICalComponent> components, List<String> warnings) {
204                    checkRequiredCardinality(warnings, TimezoneId.class);
205                    checkOptionalCardinality(warnings, LastModified.class, TimezoneUrl.class);
206    
207                    if (getStandardTimes().isEmpty() && getDaylightSavingsTime().isEmpty()) {
208                            warnings.add("At least one " + StandardTime.class.getSimpleName() + " or one " + DaylightSavingsTime.class.getSimpleName() + " must be specified.");
209                    }
210            }
211    }