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