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