001    package biweekly.property;
002    
003    import java.util.ArrayList;
004    import java.util.Collection;
005    import java.util.List;
006    
007    import biweekly.ICalendar;
008    import biweekly.Warning;
009    import biweekly.component.ICalComponent;
010    import biweekly.component.VTimezone;
011    import biweekly.parameter.ICalParameters;
012    
013    /*
014     Copyright (c) 2013, Michael Angstadt
015     All rights reserved.
016    
017     Redistribution and use in source and binary forms, with or without
018     modification, are permitted provided that the following conditions are met: 
019    
020     1. Redistributions of source code must retain the above copyright notice, this
021     list of conditions and the following disclaimer. 
022     2. Redistributions in binary form must reproduce the above copyright notice,
023     this list of conditions and the following disclaimer in the documentation
024     and/or other materials provided with the distribution. 
025    
026     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
027     ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
028     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
029     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
030     ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
031     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
032     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
033     ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
034     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
035     SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
036     */
037    
038    /**
039     * Base class for all iCalendar properties.
040     * @author Michael Angstadt
041     */
042    public abstract class ICalProperty {
043            /**
044             * The property parameters.
045             */
046            protected ICalParameters parameters = new ICalParameters();
047    
048            /**
049             * Gets the property's parameters.
050             * @return the parameters
051             */
052            public ICalParameters getParameters() {
053                    return parameters;
054            }
055    
056            /**
057             * Sets the property's parameters
058             * @param parameters the parameters
059             */
060            public void setParameters(ICalParameters parameters) {
061                    this.parameters = parameters;
062            }
063    
064            /**
065             * Gets the first value of a parameter with the given name.
066             * @param name the parameter name (case insensitive, e.g. "LANGUAGE")
067             * @return the parameter value or null if not found
068             */
069            public String getParameter(String name) {
070                    return parameters.first(name);
071            }
072    
073            /**
074             * Gets all values of a parameter with the given name.
075             * @param name the parameter name (case insensitive, e.g. "LANGUAGE")
076             * @return the parameter values
077             */
078            public List<String> getParameters(String name) {
079                    return parameters.get(name);
080            }
081    
082            /**
083             * Adds a value to a parameter.
084             * @param name the parameter name (case insensitive, e.g. "LANGUAGE")
085             * @param value the parameter value
086             */
087            public void addParameter(String name, String value) {
088                    parameters.put(name, value);
089            }
090    
091            /**
092             * Replaces all existing values of a parameter with the given value.
093             * @param name the parameter name (case insensitive, e.g. "LANGUAGE")
094             * @param value the parameter value
095             */
096            public void setParameter(String name, String value) {
097                    parameters.replace(name, value);
098            }
099    
100            /**
101             * Replaces all existing values of a parameter with the given values.
102             * @param name the parameter name (case insensitive, e.g. "LANGUAGE")
103             * @param values the parameter values
104             */
105            public void setParameter(String name, Collection<String> values) {
106                    parameters.replace(name, values);
107            }
108    
109            /**
110             * Removes a parameter from the property.
111             * @param name the parameter name (case insensitive, e.g. "LANGUAGE")
112             */
113            public void removeParameter(String name) {
114                    parameters.removeAll(name);
115            }
116    
117            //Note: The following parameter helper methods are package-scoped to prevent them from cluttering up the Javadocs
118    
119            /**
120             * Gets a URI pointing to additional information about the entity
121             * represented by the property.
122             * @return the URI or null if not set
123             * @rfc 5545 p.14-5
124             */
125            String getAltRepresentation() {
126                    return parameters.getAltRepresentation();
127            }
128    
129            /**
130             * Sets a URI pointing to additional information about the entity
131             * represented by the property.
132             * @param uri the URI or null to remove
133             * @rfc 5545 p.14-5
134             */
135            void setAltRepresentation(String uri) {
136                    parameters.setAltRepresentation(uri);
137            }
138    
139            /**
140             * Gets the content-type of the property's value.
141             * @return the content type (e.g. "image/png") or null if not set
142             * @rfc 5545 p.19-20
143             */
144            String getFormatType() {
145                    return parameters.getFormatType();
146            }
147    
148            /**
149             * Sets the content-type of the property's value.
150             * @param formatType the content type (e.g. "image/png") or null to remove
151             * @rfc 5545 p.19-20
152             */
153            void setFormatType(String formatType) {
154                    parameters.setFormatType(formatType);
155            }
156    
157            /**
158             * Gets the language that the property value is written in.
159             * @return the language (e.g. "en" for English) or null if not set
160             * @rfc 5545 p.21
161             */
162            String getLanguage() {
163                    return parameters.getLanguage();
164            }
165    
166            /**
167             * Sets the language that the property value is written in.
168             * @param language the language (e.g. "en" for English) or null to remove
169             * @rfc 5545 p.21
170             */
171            void setLanguage(String language) {
172                    parameters.setLanguage(language);
173            }
174    
175            /**
176             * Gets the timezone identifier. This either (a) references the
177             * {@link TimezoneId} property of a {@link VTimezone} component, or (b)
178             * specifies a globally-defined timezone (e.g. "America/New_York"). For a
179             * list of globally-defined timezones, see the <a
180             * href="http://www.twinsun.com/tz/tz-link.htm">TZ database</a>.
181             * @return the timezone identifier or null if not set
182             * @rfc 5545 p.27-8
183             */
184            String getTimezoneId() {
185                    return parameters.getTimezoneId();
186            }
187    
188            /**
189             * Sets the timezone identifier. This either (a) references the
190             * {@link TimezoneId} property of a {@link VTimezone} component, or (b)
191             * specifies a globally-defined timezone (e.g. "America/New_York"). For a
192             * list of globally-defined timezones, see the <a
193             * href="http://www.twinsun.com/tz/tz-link.htm">TZ database</a>.
194             * @param timezoneId the timezone identifier (e.g. "America/New_York") or
195             * null to remove
196             * @rfc 5545 p.27-8
197             */
198            void setTimezoneId(String timezoneId) {
199                    parameters.setTimezoneId(timezoneId);
200            }
201    
202            /**
203             * Sets the property's timezone to a timezone that is defined within the
204             * iCalendar object. Use {@link #setTimezoneId(String)} to use a
205             * globally-defined timezone (e.g. "America/New_York").
206             * @param timezone the timezone component to reference or null to remove
207             * @rfc 5545 p.27-8
208             */
209            void setTimezone(VTimezone timezone) {
210                    if (timezone == null) {
211                            setTimezoneId(null);
212                            return;
213                    }
214    
215                    TimezoneId tzid = timezone.getTimezoneId();
216                    if (tzid != null) {
217                            setTimezoneId(tzid.getValue());
218                    }
219            }
220    
221            /**
222             * Gets a person that is acting on behalf of the person defined in the
223             * property.
224             * @return a URI representing the person (typically, an email URI, e.g.
225             * "mailto:janedoe@example.com") or null if not set
226             * @rfc 5545 p.27
227             */
228            String getSentBy() {
229                    return parameters.getSentBy();
230            }
231    
232            /**
233             * Sets a person that is acting on behalf of the person defined in the
234             * property.
235             * @param uri a URI representing the person (typically, an email URI, e.g.
236             * "mailto:janedoe@example.com") or null to remove
237             * @rfc 5545 p.27
238             */
239            void setSentBy(String uri) {
240                    parameters.setSentBy(uri);
241            }
242    
243            /**
244             * Gets the display name of the person.
245             * @return the display name (e.g. "John Doe") or null if not set
246             * @rfc 5545 p.15-6
247             */
248            String getCommonName() {
249                    return parameters.getCommonName();
250            }
251    
252            /**
253             * Sets the display name of the person.
254             * @param commonName the display name (e.g. "John Doe") or null to remove
255             * @rfc 5545 p.15-6
256             */
257            void setCommonName(String commonName) {
258                    parameters.setCommonName(commonName);
259            }
260    
261            /**
262             * Gets a URI that contains additional information about the person.
263             * @return the URI (e.g. an LDAP URI) or null if not set
264             * @rfc 5545 p.18
265             */
266            String getDirectoryEntry() {
267                    return parameters.getDirectoryEntry();
268            }
269    
270            /**
271             * Sets a URI that contains additional information about the person.
272             * @param uri the URI (e.g. an LDAP URI) or null to remove
273             * @rfc 5545 p.18
274             */
275            void setDirectoryEntry(String uri) {
276                    parameters.setDirectoryEntry(uri);
277            }
278    
279            /**
280             * Checks the property for data consistency problems or deviations from the
281             * spec. These problems will not prevent the property from being written to
282             * a data stream, but may prevent it from being parsed correctly by the
283             * consuming application. These problems can largely be avoided by reading
284             * the Javadocs of the property class, or by being familiar with the
285             * iCalendar standard.
286             * @param components the hierarchy of components that the property belongs
287             * to
288             * @see ICalendar#validate
289             * @return a list of warnings or an empty list if no problems were found
290             */
291            public final List<Warning> validate(List<ICalComponent> components) {
292                    //validate property value
293                    List<Warning> warnings = new ArrayList<Warning>(0);
294                    validate(components, warnings);
295    
296                    //validate parameters
297                    warnings.addAll(parameters.validate());
298    
299                    return warnings;
300            }
301    
302            /**
303             * Checks the property for data consistency problems or deviations from the
304             * spec. Meant to be overridden by child classes that wish to provide
305             * validation logic.
306             * @param components the hierarchy of components that the property belongs
307             * to
308             * @param warnings the list to add the warnings to
309             */
310            protected void validate(List<ICalComponent> components, List<Warning> warnings) {
311                    //do nothing
312            }
313    }