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.component;
34 import java.util.HashMap;
35 import java.util.Map;
37 import net.fortuna.ical4j.model.Date;
38 import net.fortuna.ical4j.model.Property;
39 import net.fortuna.ical4j.model.PropertyList;
40 import net.fortuna.ical4j.model.ValidationException;
41 import net.fortuna.ical4j.model.Validator;
42 import net.fortuna.ical4j.model.property.Clazz;
43 import net.fortuna.ical4j.model.property.Created;
44 import net.fortuna.ical4j.model.property.Description;
45 import net.fortuna.ical4j.model.property.DtStamp;
46 import net.fortuna.ical4j.model.property.DtStart;
47 import net.fortuna.ical4j.model.property.LastModified;
48 import net.fortuna.ical4j.model.property.Method;
49 import net.fortuna.ical4j.model.property.Organizer;
50 import net.fortuna.ical4j.model.property.RecurrenceId;
51 import net.fortuna.ical4j.model.property.Sequence;
52 import net.fortuna.ical4j.model.property.Status;
53 import net.fortuna.ical4j.model.property.Summary;
54 import net.fortuna.ical4j.model.property.Uid;
55 import net.fortuna.ical4j.model.property.Url;
56 import net.fortuna.ical4j.util.CompatibilityHints;
57 import net.fortuna.ical4j.util.PropertyValidator;
59 /**
60 * $Id$ [Apr 5, 2004]
61 *
62 * Defines an iCalendar VJOURNAL component.
63 *
64 * <pre>
65 * 4.6.3 Journal Component
66 *
67 * Component Name: VJOURNAL
68 *
69 * Purpose: Provide a grouping of component properties that describe a
70 * journal entry.
71 *
72 * Formal Definition: A "VJOURNAL" calendar component is defined by the
73 * following notation:
74 *
75 * journalc = "BEGIN" ":" "VJOURNAL" CRLF
76 * jourprop
77 * "END" ":" "VJOURNAL" CRLF
78 *
79 * jourprop = *(
80 *
81 * ; the following are optional,
82 * ; but MUST NOT occur more than once
83 *
84 * class / created / description / dtstart / dtstamp /
85 * last-mod / organizer / recurid / seq / status /
86 * summary / uid / url /
87 *
88 * ; the following are optional,
89 * ; and MAY occur more than once
90 *
91 * attach / attendee / categories / comment /
92 * contact / exdate / exrule / related / rdate /
93 * rrule / rstatus / x-prop
94 *
95 * )
96 * </pre>
97 *
98 * Example 1 - Creating a journal associated with an event:
99 *
100 * <pre><code>
101 * DtStart meetingDate = (DtStart) meeting.getProperties().getProperty(
102 * Property.DTSTART);
103 *
104 * VJournal minutes = new VJournal(meetingDate.getTime(),
105 * "Progress Meeting - Minutes");
106 *
107 * // add timezone information..
108 * TzId tzParam = meetingDate.getParameters().getParmaeter(Parameter.TZID);
109 * minutes.getProperties().getProperty(Property.DTSTART).getParameters().add(
110 * tzParam);
111 *
112 * // add description..
113 * minutes.getProperties().add(new Description("1. Agenda.., 2. Action Items.."));
114 * </code></pre>
115 *
116 * @author Ben Fortuna
117 */
118 public class VJournal extends CalendarComponent {
120 private static final long serialVersionUID = -7635140949183238830L;
122 private final Map methodValidators = new HashMap();
123 {
124 methodValidators.put(Method.ADD, new AddValidator());
125 methodValidators.put(Method.CANCEL, new CancelValidator());
126 methodValidators.put(Method.PUBLISH, new PublishValidator());
127 }
129 /**
130 * Default constructor.
131 */
132 public VJournal() {
133 super(VJOURNAL);
134 getProperties().add(new DtStamp());
135 }
137 /**
138 * Constructor.
139 * @param properties a list of properties
140 */
141 public VJournal(final PropertyList properties) {
142 super(VJOURNAL, properties);
143 }
145 /**
146 * Constructs a new VJOURNAL instance associated with the specified time with the specified summary.
147 * @param start the date the journal entry is associated with
148 * @param summary the journal summary
149 */
150 public VJournal(final Date start, final String summary) {
151 this();
152 getProperties().add(new DtStart(start));
153 getProperties().add(new Summary(summary));
154 }
156 /**
157 * {@inheritDoc}
158 */
159 public final void validate(final boolean recurse)
160 throws ValidationException {
162 if (!CompatibilityHints
163 .isHintEnabled(CompatibilityHints.KEY_RELAXED_VALIDATION)) {
165 // From "4.8.4.7 Unique Identifier":
166 // Conformance: The property MUST be specified in the "VEVENT", "VTODO",
167 // "VJOURNAL" or "VFREEBUSY" calendar components.
168 PropertyValidator.getInstance().assertOne(Property.UID,
169 getProperties());
171 // From "4.8.7.2 Date/Time Stamp":
172 // Conformance: This property MUST be included in the "VEVENT", "VTODO",
173 // "VJOURNAL" or "VFREEBUSY" calendar components.
174 PropertyValidator.getInstance().assertOne(Property.DTSTAMP,
175 getProperties());
176 }
178 /*
179 * ; the following are optional, ; but MUST NOT occur more than once class / created / description / dtstart /
180 * dtstamp / last-mod / organizer / recurid / seq / status / summary / uid / url /
181 */
182 PropertyValidator.getInstance().assertOneOrLess(Property.CLASS,
183 getProperties());
184 PropertyValidator.getInstance().assertOneOrLess(Property.CREATED,
185 getProperties());
186 PropertyValidator.getInstance().assertOneOrLess(Property.DESCRIPTION,
187 getProperties());
188 PropertyValidator.getInstance().assertOneOrLess(Property.DTSTART,
189 getProperties());
190 PropertyValidator.getInstance().assertOneOrLess(Property.DTSTAMP,
191 getProperties());
192 PropertyValidator.getInstance().assertOneOrLess(Property.LAST_MODIFIED,
193 getProperties());
194 PropertyValidator.getInstance().assertOneOrLess(Property.ORGANIZER,
195 getProperties());
196 PropertyValidator.getInstance().assertOneOrLess(Property.RECURRENCE_ID,
197 getProperties());
198 PropertyValidator.getInstance().assertOneOrLess(Property.SEQUENCE,
199 getProperties());
200 PropertyValidator.getInstance().assertOneOrLess(Property.STATUS,
201 getProperties());
202 PropertyValidator.getInstance().assertOneOrLess(Property.SUMMARY,
203 getProperties());
204 PropertyValidator.getInstance().assertOneOrLess(Property.UID,
205 getProperties());
206 PropertyValidator.getInstance().assertOneOrLess(Property.URL,
207 getProperties());
209 final Status status = (Status) getProperty(Property.STATUS);
210 if (status != null && !Status.VJOURNAL_DRAFT.getValue().equals(status.getValue())
211 && !Status.VJOURNAL_FINAL.getValue().equals(status.getValue())
212 && !Status.VJOURNAL_CANCELLED.getValue().equals(status.getValue())) {
213 throw new ValidationException("Status property ["
214 + status.toString() + "] may not occur in VJOURNAL");
215 }
217 /*
218 * ; the following are optional, ; and MAY occur more than once attach / attendee / categories / comment /
219 * contact / exdate / exrule / related / rdate / rrule / rstatus / x-prop
220 */
222 if (recurse) {
223 validateProperties();
224 }
225 }
227 /**
228 * {@inheritDoc}
229 */
230 protected Validator getValidator(Method method) {
231 return (Validator) methodValidators.get(method);
232 }
234 /**
235 * <pre>
236 * Component/Property Presence
237 * ------------------- ----------------------------------------------
238 * METHOD 1 MUST be "ADD"
239 * VJOURNAL 1
240 * DESCRIPTION 1 Can be null.
241 * DTSTAMP 1
242 * DTSTART 1
243 * ORGANIZER 1
244 * SEQUENCE 1 MUST be greater than 0
245 * UID 1 MUST match that of the original journal
246 *
247 * ATTACH 0+
248 * CATEGORIES 0 or 1 This property MAY contain a list of values
249 * CLASS 0 or 1
250 * COMMENT 0 or 1
251 * CONTACT 0+
252 * CREATED 0 or 1
253 * EXDATE 0+
254 * EXRULE 0+
255 * LAST-MODIFIED 0 or 1
256 * RDATE 0+
257 * RELATED-TO 0+
258 * RRULE 0+
259 * STATUS 0 or 1 MAY be one of DRAFT/FINAL/CANCELLED
260 * SUMMARY 0 or 1 Can be null
261 * URL 0 or 1
262 * X-PROPERTY 0+
263 *
264 * ATTENDEE 0
265 * RECURRENCE-ID 0
266 *
267 * VALARM 0+
268 * VTIMEZONE 0 or 1 MUST be present if any date/time refers to
269 * a timezone
270 * X-COMPONENT 0+
271 *
272 * VEVENT 0
273 * VFREEBUSY 0
274 * VTODO 0
275 * </pre>
276 *
277 */
278 private class AddValidator implements Validator {
280 private static final long serialVersionUID = 1L;
282 public void validate() throws ValidationException {
283 PropertyValidator.getInstance().assertOne(Property.DESCRIPTION, getProperties());
284 PropertyValidator.getInstance().assertOne(Property.DTSTAMP, getProperties());
285 PropertyValidator.getInstance().assertOne(Property.DTSTART, getProperties());
286 PropertyValidator.getInstance().assertOne(Property.ORGANIZER, getProperties());
287 PropertyValidator.getInstance().assertOne(Property.SEQUENCE, getProperties());
288 PropertyValidator.getInstance().assertOne(Property.UID, getProperties());
290 PropertyValidator.getInstance().assertOneOrLess(Property.CATEGORIES, getProperties());
291 PropertyValidator.getInstance().assertOneOrLess(Property.CLASS, getProperties());
292 PropertyValidator.getInstance().assertOneOrLess(Property.COMMENT, getProperties());
293 PropertyValidator.getInstance().assertOneOrLess(Property.CREATED, getProperties());
294 PropertyValidator.getInstance().assertOneOrLess(Property.LAST_MODIFIED, getProperties());
295 PropertyValidator.getInstance().assertOneOrLess(Property.STATUS, getProperties());
296 PropertyValidator.getInstance().assertOneOrLess(Property.SUMMARY, getProperties());
297 PropertyValidator.getInstance().assertOneOrLess(Property.URL, getProperties());
299 PropertyValidator.getInstance().assertNone(Property.ATTENDEE, getProperties());
300 PropertyValidator.getInstance().assertNone(Property.RECURRENCE_ID, getProperties());
301 }
302 }
304 /**
305 * <pre>
306 * Component/Property Presence
307 * ------------------- ---------------------------------------------
308 * METHOD 1 MUST be "CANCEL"
309 * VJOURNAL 1+ All MUST have the same UID
310 * DTSTAMP 1
311 * ORGANIZER 1
312 * SEQUENCE 1
313 * UID 1 MUST be the UID of the original REQUEST
314 *
315 * ATTACH 0+
316 * ATTENDEE 0+
317 * CATEGORIES 0 or 1 This property MAY contain a list of values
318 * CLASS 0 or 1
319 * COMMENT 0 or 1
320 * CONTACT 0+
321 * CREATED 0 or 1
322 * DESCRIPTION 0 or 1
323 * DTSTART 0 or 1
324 * EXDATE 0+
325 * EXRULE 0+
326 * LAST-MODIFIED 0 or 1
327 * RDATE 0+
328 * RECURRENCE-ID 0 or 1 only if referring to an instance of a
329 * recurring calendar component. Otherwise
330 * it MUST NOT be present.
331 * RELATED-TO 0+
332 * RRULE 0+
333 * STATUS 0 or 1 MAY be present, must be "CANCELLED" if
334 * present
335 * SUMMARY 0 or 1
336 * URL 0 or 1
337 * X-PROPERTY 0+
338 *
339 * REQUEST-STATUS 0
340 *
341 * VTIMEZONE 0+ MUST be present if any date/time refers to
342 * a timezone
343 * X-COMPONENT 0+
344 * VALARM 0
345 * VEVENT 0
346 * VFREEBUSY 0
347 * VTODO 0
348 * </pre>
349 *
350 */
351 private class CancelValidator implements Validator {
353 private static final long serialVersionUID = 1L;
355 public void validate() throws ValidationException {
356 PropertyValidator.getInstance().assertOne(Property.DTSTAMP, getProperties());
357 PropertyValidator.getInstance().assertOne(Property.ORGANIZER, getProperties());
358 PropertyValidator.getInstance().assertOne(Property.SEQUENCE, getProperties());
359 PropertyValidator.getInstance().assertOne(Property.UID, getProperties());
361 PropertyValidator.getInstance().assertOneOrLess(Property.CATEGORIES, getProperties());
362 PropertyValidator.getInstance().assertOneOrLess(Property.CLASS, getProperties());
363 PropertyValidator.getInstance().assertOneOrLess(Property.COMMENT, getProperties());
364 PropertyValidator.getInstance().assertOneOrLess(Property.CREATED, getProperties());
365 PropertyValidator.getInstance().assertOneOrLess(Property.DESCRIPTION, getProperties());
366 PropertyValidator.getInstance().assertOneOrLess(Property.DTSTART, getProperties());
367 PropertyValidator.getInstance().assertOneOrLess(Property.LAST_MODIFIED, getProperties());
368 PropertyValidator.getInstance().assertOneOrLess(Property.RECURRENCE_ID, getProperties());
369 PropertyValidator.getInstance().assertOneOrLess(Property.STATUS, getProperties());
370 PropertyValidator.getInstance().assertOneOrLess(Property.SUMMARY, getProperties());
371 PropertyValidator.getInstance().assertOneOrLess(Property.URL, getProperties());
373 PropertyValidator.getInstance().assertNone(Property.REQUEST_STATUS, getProperties());
374 }
375 }
377 /**
378 * <pre>
379 * Component/Property Presence
380 * ------------------- ----------------------------------------------
381 * METHOD 1 MUST be "PUBLISH"
382 * VJOURNAL 1+
383 * DESCRIPTION 1 Can be null.
384 * DTSTAMP 1
385 * DTSTART 1
386 * ORGANIZER 1
387 * UID 1
388 *
389 * ATTACH 0+
390 * CATEGORIES 0 or 1 This property MAY contain a list of values
391 * CLASS 0 or 1
392 * COMMENT 0 or 1
393 * CONTACT 0+
394 * CREATED 0 or 1
395 * EXDATE 0+
396 * EXRULE 0+
397 * LAST-MODIFIED 0 or 1
398 * RDATE 0+
399 * RECURRENCE-ID 0 or 1 MUST only if referring to an instance of a
400 * recurring calendar component. Otherwise
401 * it MUST NOT be present.
402 * RELATED-TO 0+
403 * RRULE 0+
404 * SEQUENCE 0 or 1 MUST echo the original SEQUENCE number.
405 * MUST be present if non-zero. MAY be
406 * present if zero.
407 * STATUS 0 or 1 MAY be one of DRAFT/FINAL/CANCELLED
408 * SUMMARY 0 or 1 Can be null
409 * URL 0 or 1
410 * X-PROPERTY 0+
411 *
412 * ATTENDEE 0
413 *
414 * VALARM 0+
415 * VTIMEZONE 0+ MUST be present if any date/time refers to
416 * a timezone
417 * X-COMPONENT 0+
418 *
419 * VEVENT 0
420 * VFREEBUSY 0
421 * VTODO 0
422 * </pre>
423 *
424 */
425 private class PublishValidator implements Validator {
427 private static final long serialVersionUID = 1L;
429 public void validate() throws ValidationException {
430 PropertyValidator.getInstance().assertOne(Property.DESCRIPTION, getProperties());
431 PropertyValidator.getInstance().assertOne(Property.DTSTAMP, getProperties());
432 PropertyValidator.getInstance().assertOne(Property.DTSTART, getProperties());
433 PropertyValidator.getInstance().assertOne(Property.ORGANIZER, getProperties());
434 PropertyValidator.getInstance().assertOne(Property.UID, getProperties());
436 PropertyValidator.getInstance().assertOneOrLess(Property.CATEGORIES, getProperties());
437 PropertyValidator.getInstance().assertOneOrLess(Property.CLASS, getProperties());
438 PropertyValidator.getInstance().assertOneOrLess(Property.COMMENT, getProperties());
439 PropertyValidator.getInstance().assertOneOrLess(Property.CREATED, getProperties());
440 PropertyValidator.getInstance().assertOneOrLess(Property.LAST_MODIFIED, getProperties());
441 PropertyValidator.getInstance().assertOneOrLess(Property.RECURRENCE_ID, getProperties());
442 PropertyValidator.getInstance().assertOneOrLess(Property.SEQUENCE, getProperties());
443 PropertyValidator.getInstance().assertOneOrLess(Property.STATUS, getProperties());
444 PropertyValidator.getInstance().assertOneOrLess(Property.SUMMARY, getProperties());
445 PropertyValidator.getInstance().assertOneOrLess(Property.URL, getProperties());
447 PropertyValidator.getInstance().assertNone(Property.ATTENDEE, getProperties());
448 }
449 }
451 /**
452 * @return the optional access classification property for a journal entry
453 */
454 public final Clazz getClassification() {
455 return (Clazz) getProperty(Property.CLASS);
456 }
458 /**
459 * @return the optional creation-time property for a journal entry
460 */
461 public final Created getCreated() {
462 return (Created) getProperty(Property.CREATED);
463 }
465 /**
466 * @return the optional description property for a journal entry
467 */
468 public final Description getDescription() {
469 return (Description) getProperty(Property.DESCRIPTION);
470 }
472 /**
473 * Convenience method to pull the DTSTART out of the property list.
474 * @return The DtStart object representation of the start Date
475 */
476 public final DtStart getStartDate() {
477 return (DtStart) getProperty(Property.DTSTART);
478 }
480 /**
481 * @return the optional last-modified property for a journal entry
482 */
483 public final LastModified getLastModified() {
484 return (LastModified) getProperty(Property.LAST_MODIFIED);
485 }
487 /**
488 * @return the optional organizer property for a journal entry
489 */
490 public final Organizer getOrganizer() {
491 return (Organizer) getProperty(Property.ORGANIZER);
492 }
494 /**
495 * @return the optional date-stamp property
496 */
497 public final DtStamp getDateStamp() {
498 return (DtStamp) getProperty(Property.DTSTAMP);
499 }
501 /**
502 * @return the optional sequence number property for a journal entry
503 */
504 public final Sequence getSequence() {
505 return (Sequence) getProperty(Property.SEQUENCE);
506 }
508 /**
509 * @return the optional status property for a journal entry
510 */
511 public final Status getStatus() {
512 return (Status) getProperty(Property.STATUS);
513 }
515 /**
516 * @return the optional summary property for a journal entry
517 */
518 public final Summary getSummary() {
519 return (Summary) getProperty(Property.SUMMARY);
520 }
522 /**
523 * @return the optional URL property for a journal entry
524 */
525 public final Url getUrl() {
526 return (Url) getProperty(Property.URL);
527 }
529 /**
530 * @return the optional recurrence identifier property for a journal entry
531 */
532 public final RecurrenceId getRecurrenceId() {
533 return (RecurrenceId) getProperty(Property.RECURRENCE_ID);
534 }
536 /**
537 * Returns the UID property of this component if available.
538 * @return a Uid instance, or null if no UID property exists
539 */
540 public final Uid getUid() {
541 return (Uid) getProperty(Property.UID);
542 }
543 }