Tue, 10 Feb 2015 18:12:00 +0100
Import initial revisions of existing project AndroidCaldavSyncAdapater,
forked from upstream repository at 27e8a0f8495c92e0780d450bdf0c7cec77a03a55.
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;
34 import java.io.IOException;
35 import java.net.URISyntaxException;
36 import java.text.ParseException;
37 import net.fortuna.ical4j.model.parameter.Value;
38 import net.fortuna.ical4j.model.property.XProperty;
40 import net.fortuna.ical4j.util.Strings;
42 import org.apache.commons.lang.builder.EqualsBuilder;
43 import org.apache.commons.lang.builder.HashCodeBuilder;
45 /**
46 * Defines an iCalendar property. Subclasses of this class provide additional validation and typed values for specific
47 * iCalendar properties.
48 *
49 * Note that subclasses must provide a reference to the factory used to create the
50 * property to support property cloning (copy). If no factory is specified an
51 * {@link UnsupportedOperationException} will be thrown by the {@link #copy()} method.
52 *
53 * @author Ben Fortuna
54 *
55 * $Id$ [Apr 5, 2004]
56 */
57 public abstract class Property extends Content {
59 private static final long serialVersionUID = 7048785558435608687L;
61 // iCalendar properties..
63 /**
64 * Product identifier property name.
65 */
66 public static final String PRODID = "PRODID";
68 /**
69 * iCalendar version property name.
70 */
71 public static final String VERSION = "VERSION";
73 /**
74 * Calendar scale property name.
75 */
76 public static final String CALSCALE = "CALSCALE";
78 /**
79 * iTIP method property name.
80 */
81 public static final String METHOD = "METHOD";
83 // Component properties..
85 /**
86 * Busy type property name.
87 */
88 public static final String BUSYTYPE = "BUSYTYPE";
90 /**
91 * Classifier property name.
92 */
93 public static final String CLASS = "CLASS";
95 /**
96 * Creation date property name.
97 */
98 public static final String CREATED = "CREATED";
100 /**
101 * Description property name.
102 */
103 public static final String DESCRIPTION = "DESCRIPTION";
105 /**
106 * Start date property name.
107 */
108 public static final String DTSTART = "DTSTART";
110 /**
111 * Geographic location property name.
112 */
113 public static final String GEO = "GEO";
115 /**
116 * Last modified date property name.
117 */
118 public static final String LAST_MODIFIED = "LAST-MODIFIED";
120 /**
121 * Location property name.
122 */
123 public static final String LOCATION = "LOCATION";
125 /**
126 * Organiser property name.
127 */
128 public static final String ORGANIZER = "ORGANIZER";
130 /**
131 * Percentage complete property name.
132 */
133 public static final String PERCENT_COMPLETE = "PERCENT-COMPLETE";
135 /**
136 * Prority property name.
137 */
138 public static final String PRIORITY = "PRIORITY";
140 /**
141 * Date-stamp property name.
142 */
143 public static final String DTSTAMP = "DTSTAMP";
145 /**
146 * Sequence property name.
147 */
148 public static final String SEQUENCE = "SEQUENCE";
150 /**
151 * Status property name.
152 */
153 public static final String STATUS = "STATUS";
155 /**
156 * Summary property name.
157 */
158 public static final String SUMMARY = "SUMMARY";
160 /**
161 * Transparency property name.
162 */
163 public static final String TRANSP = "TRANSP";
165 /**
166 * Unique identifier property name.
167 */
168 public static final String UID = "UID";
170 /**
171 * Uniform resource locator property name.
172 */
173 public static final String URL = "URL";
175 /**
176 * Recurrence identifier property name.
177 */
178 public static final String RECURRENCE_ID = "RECURRENCE-ID";
180 /**
181 * Completed date property name.
182 */
183 public static final String COMPLETED = "COMPLETED";
185 /**
186 * Due date property name.
187 */
188 public static final String DUE = "DUE";
190 /**
191 * Free/busy property name.
192 */
193 public static final String FREEBUSY = "FREEBUSY";
195 /**
196 * Timezone identifier property name.
197 */
198 public static final String TZID = "TZID";
200 /**
201 * Timezone name property name.
202 */
203 public static final String TZNAME = "TZNAME";
205 /**
206 * Prior timezone offset property name.
207 */
208 public static final String TZOFFSETFROM = "TZOFFSETFROM";
210 /**
211 * New timezone offset property name.
212 */
213 public static final String TZOFFSETTO = "TZOFFSETTO";
215 /**
216 * URL for timezone definition property name.
217 */
218 public static final String TZURL = "TZURL";
220 /**
221 * Alarm action property name.
222 */
223 public static final String ACTION = "ACTION";
225 /**
226 * Repeat rule property name.
227 */
228 public static final String REPEAT = "REPEAT";
230 /**
231 * Alarm trigger property name.
232 */
233 public static final String TRIGGER = "TRIGGER";
235 /**
236 * Request status property name.
237 */
238 public static final String REQUEST_STATUS = "REQUEST-STATUS";
240 /**
241 * End date property name.
242 */
243 public static final String DTEND = "DTEND";
245 /**
246 * Duration property name.
247 */
248 public static final String DURATION = "DURATION";
250 /**
251 * Attachment property name.
252 */
253 public static final String ATTACH = "ATTACH";
255 /**
256 * Attendee property name.
257 */
258 public static final String ATTENDEE = "ATTENDEE";
260 /**
261 * Categories property name.
262 */
263 public static final String CATEGORIES = "CATEGORIES";
265 /**
266 * Comment property name.
267 */
268 public static final String COMMENT = "COMMENT";
270 /**
271 * Contact property name.
272 */
273 public static final String CONTACT = "CONTACT";
275 /**
276 * Exclusion date property name.
277 */
278 public static final String EXDATE = "EXDATE";
280 /**
281 * Exclusion rule property name.
282 */
283 public static final String EXRULE = "EXRULE";
285 /**
286 * Relationship property name.
287 */
288 public static final String RELATED_TO = "RELATED-TO";
290 /**
291 * Resources property name.
292 */
293 public static final String RESOURCES = "RESOURCES";
295 /**
296 * Recurrence date property name.
297 */
298 public static final String RDATE = "RDATE";
300 /**
301 * Recurrence rule property name.
302 */
303 public static final String RRULE = "RRULE";
305 /**
306 * Prefix for non-standard properties.
307 */
308 public static final String EXPERIMENTAL_PREFIX = "X-";
310 /**
311 * VVENUE country property name.
312 */
313 public static final String COUNTRY = "COUNTRY";
315 /**
316 * VVENUE extended address property name.
317 */
318 public static final String EXTENDED_ADDRESS = "EXTENDED-ADDRESS";
320 /**
321 * VVENUE locality property name.
322 */
323 public static final String LOCALITY = "LOCALITY";
325 /**
326 * VVENUE location type property name.
327 */
328 public static final String LOCATION_TYPE = "LOCATION-TYPE";
330 /**
331 * VVENUE name property name.
332 */
333 public static final String NAME = "NAME";
335 /**
336 * VVENUE postal code property name.
337 */
338 public static final String POSTALCODE = "POSTAL-CODE";
340 /**
341 * VVENUE region property name.
342 */
343 public static final String REGION = "REGION";
345 /**
346 * VVENUE street address property name.
347 */
348 public static final String STREET_ADDRESS = "STREET-ADDRESS";
350 /**
351 * VVENUE telephone property name.
352 */
353 public static final String TEL = "TEL";
355 private String name;
357 private ParameterList parameters;
359 private final PropertyFactory factory;
361 /**
362 * Constructor.
363 * @param aName property name
364 * @param factory the factory used to create the property instance
365 */
366 protected Property(final String aName, PropertyFactory factory) {
367 this(aName, new ParameterList(), factory);
368 }
370 /**
371 * Constructor made protected to enforce the use of <code>PropertyFactory</code> for property instantiation.
372 * @param aName property name
373 * @param aList a list of parameters
374 */
375 // protected Property(final String aName, final ParameterList aList) {
376 // this(aName, aList, PropertyFactoryImpl.getInstance());
377 // }
379 /**
380 * @param aName a property identifier
381 * @param aList a list of initial parameters
382 * @param factory the factory used to create the property instance
383 */
384 protected Property(final String aName, final ParameterList aList, PropertyFactory factory) {
385 this.name = aName;
386 this.parameters = aList;
387 this.factory = factory;
388 }
390 /**
391 * Creates a deep copy of the specified property. That is, the name, parameter list, and value are duplicated from
392 * the specified property. This constructor should only be called from sub-classes to ensure type integrity is
393 * maintained.
394 * @param property a property to copy
395 * @throws URISyntaxException where the specified property contains an invalid URI value
396 * @throws ParseException where the specified property has invalid data
397 * @throws IOException where an error occurs reading data from the specified property
398 * @deprecated Use {@link #copy()} instead
399 */
400 protected Property(final Property property) throws IOException,
401 URISyntaxException, ParseException {
402 this(property.getName(), new ParameterList(property.getParameters(), false),
403 property.factory);
404 setValue(property.getValue());
405 }
407 /**
408 * {@inheritDoc}
409 */
410 public final String toString() {
411 final StringBuffer buffer = new StringBuffer();
412 buffer.append(getName());
413 if (getParameters() != null) {
414 buffer.append(getParameters());
415 }
416 buffer.append(':');
417 boolean needsEscape = false;
418 if (this instanceof XProperty) {
419 Value valParam = (Value)getParameter(Parameter.VALUE);
420 if (valParam == null || valParam.equals(Value.TEXT)) {
421 needsEscape = true;
422 }
423 } else if (this instanceof Escapable) {
424 needsEscape = true;
425 }
426 if (needsEscape) {
427 buffer.append(Strings.escape(Strings.valueOf(getValue())));
428 }
429 else {
430 buffer.append(Strings.valueOf(getValue()));
431 }
432 buffer.append(Strings.LINE_SEPARATOR);
434 return buffer.toString();
435 }
437 /**
438 * Indicates whether this property is a calendar property.
439 * @return boolean
440 */
441 public boolean isCalendarProperty() {
443 return PRODID.equalsIgnoreCase(getName())
444 || VERSION.equalsIgnoreCase(getName())
445 || CALSCALE.equalsIgnoreCase(getName())
446 || METHOD.equalsIgnoreCase(getName());
447 }
449 /**
450 * @return Returns the name.
451 */
452 public final String getName() {
453 return name;
454 }
456 /**
457 * @return Returns the parameters.
458 */
459 public final ParameterList getParameters() {
460 return parameters;
461 }
463 /**
464 * Convenience method for retrieving a list of named parameters.
465 * @param name name of parameters to retrieve
466 * @return a parameter list containing only parameters with the specified name
467 */
468 public final ParameterList getParameters(final String name) {
469 return getParameters().getParameters(name);
470 }
472 /**
473 * Convenience method for retrieving a single parameter.
474 * @param name name of the parameter to retrieve
475 * @return the first parameter from the parameter list with the specified name
476 */
477 public final Parameter getParameter(final String name) {
478 return getParameters().getParameter(name);
479 }
481 /**
482 * Sets the current value of the property.
483 * @param aValue a string representation of the property value
484 * @throws IOException possibly thrown by setting the value of certain properties
485 * @throws URISyntaxException possibly thrown by setting the value of certain properties
486 * @throws ParseException possibly thrown by setting the value of certain properties
487 */
488 public abstract void setValue(String aValue) throws IOException,
489 URISyntaxException, ParseException;
491 /**
492 * Perform validation on a property.
493 * @throws ValidationException where the property is not in a valid state
494 */
495 public abstract void validate() throws ValidationException;
497 /**
498 * {@inheritDoc}
499 */
500 public final boolean equals(final Object arg0) {
501 if (arg0 instanceof Property) {
502 final Property p = (Property) arg0;
503 if (getName().equals(p.getName())) {
504 return new EqualsBuilder().append(getValue(), p.getValue())
505 .append(getParameters(), p.getParameters()).isEquals();
506 } else {
507 return false;
508 }
509 }
510 return super.equals(arg0);
511 }
513 /**
514 * {@inheritDoc}
515 */
516 public int hashCode() {
517 // as property name is case-insensitive generate hash for uppercase..
518 return new HashCodeBuilder().append(getName().toUpperCase()).append(
519 getValue()).append(getParameters()).toHashCode();
520 }
522 /**
523 * Create a (deep) copy of this property.
524 * @return the copy of the property
525 * @throws IOException where an error occurs reading property data
526 * @throws URISyntaxException where the property contains an invalid URI value
527 * @throws ParseException where the property contains an invalid date value
528 */
529 public Property copy() throws IOException, URISyntaxException, ParseException {
530 if (factory == null) {
531 throw new UnsupportedOperationException("No factory specified");
532 }
533 // Deep copy parameter list..
534 final ParameterList params = new ParameterList(getParameters(), false);
535 return factory.createProperty(getName(), params, getValue());
536 }
537 }