Tue, 10 Feb 2015 19:58:00 +0100
Upgrade the upgraded ical4j component to use org.apache.commons.lang3.
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.CREATED, getProperties());
293 PropertyValidator.getInstance().assertOneOrLess(Property.LAST_MODIFIED, getProperties());
294 PropertyValidator.getInstance().assertOneOrLess(Property.STATUS, getProperties());
295 PropertyValidator.getInstance().assertOneOrLess(Property.SUMMARY, getProperties());
296 PropertyValidator.getInstance().assertOneOrLess(Property.URL, getProperties());
298 PropertyValidator.getInstance().assertNone(Property.ATTENDEE, getProperties());
299 PropertyValidator.getInstance().assertNone(Property.RECURRENCE_ID, getProperties());
300 }
301 }
303 /**
304 * <pre>
305 * Component/Property Presence
306 * ------------------- ---------------------------------------------
307 * METHOD 1 MUST be "CANCEL"
308 * VJOURNAL 1+ All MUST have the same UID
309 * DTSTAMP 1
310 * ORGANIZER 1
311 * SEQUENCE 1
312 * UID 1 MUST be the UID of the original REQUEST
313 *
314 * ATTACH 0+
315 * ATTENDEE 0+
316 * CATEGORIES 0 or 1 This property MAY contain a list of values
317 * CLASS 0 or 1
318 * COMMENT 0 or 1
319 * CONTACT 0+
320 * CREATED 0 or 1
321 * DESCRIPTION 0 or 1
322 * DTSTART 0 or 1
323 * EXDATE 0+
324 * EXRULE 0+
325 * LAST-MODIFIED 0 or 1
326 * RDATE 0+
327 * RECURRENCE-ID 0 or 1 only if referring to an instance of a
328 * recurring calendar component. Otherwise
329 * it MUST NOT be present.
330 * RELATED-TO 0+
331 * RRULE 0+
332 * STATUS 0 or 1 MAY be present, must be "CANCELLED" if
333 * present
334 * SUMMARY 0 or 1
335 * URL 0 or 1
336 * X-PROPERTY 0+
337 *
338 * REQUEST-STATUS 0
339 *
340 * VTIMEZONE 0+ MUST be present if any date/time refers to
341 * a timezone
342 * X-COMPONENT 0+
343 * VALARM 0
344 * VEVENT 0
345 * VFREEBUSY 0
346 * VTODO 0
347 * </pre>
348 *
349 */
350 private class CancelValidator implements Validator {
352 private static final long serialVersionUID = 1L;
354 public void validate() throws ValidationException {
355 PropertyValidator.getInstance().assertOne(Property.DTSTAMP, getProperties());
356 PropertyValidator.getInstance().assertOne(Property.ORGANIZER, getProperties());
357 PropertyValidator.getInstance().assertOne(Property.SEQUENCE, getProperties());
358 PropertyValidator.getInstance().assertOne(Property.UID, getProperties());
360 PropertyValidator.getInstance().assertOneOrLess(Property.CATEGORIES, getProperties());
361 PropertyValidator.getInstance().assertOneOrLess(Property.CLASS, getProperties());
362 PropertyValidator.getInstance().assertOneOrLess(Property.CREATED, getProperties());
363 PropertyValidator.getInstance().assertOneOrLess(Property.DESCRIPTION, getProperties());
364 PropertyValidator.getInstance().assertOneOrLess(Property.DTSTART, getProperties());
365 PropertyValidator.getInstance().assertOneOrLess(Property.LAST_MODIFIED, getProperties());
366 PropertyValidator.getInstance().assertOneOrLess(Property.RECURRENCE_ID, getProperties());
367 PropertyValidator.getInstance().assertOneOrLess(Property.STATUS, getProperties());
368 PropertyValidator.getInstance().assertOneOrLess(Property.SUMMARY, getProperties());
369 PropertyValidator.getInstance().assertOneOrLess(Property.URL, getProperties());
371 PropertyValidator.getInstance().assertNone(Property.REQUEST_STATUS, getProperties());
372 }
373 }
375 /**
376 * <pre>
377 * Component/Property Presence
378 * ------------------- ----------------------------------------------
379 * METHOD 1 MUST be "PUBLISH"
380 * VJOURNAL 1+
381 * DESCRIPTION 1 Can be null.
382 * DTSTAMP 1
383 * DTSTART 1
384 * ORGANIZER 1
385 * UID 1
386 *
387 * ATTACH 0+
388 * CATEGORIES 0 or 1 This property MAY contain a list of values
389 * CLASS 0 or 1
390 * COMMENT 0 or 1
391 * CONTACT 0+
392 * CREATED 0 or 1
393 * EXDATE 0+
394 * EXRULE 0+
395 * LAST-MODIFIED 0 or 1
396 * RDATE 0+
397 * RECURRENCE-ID 0 or 1 MUST only if referring to an instance of a
398 * recurring calendar component. Otherwise
399 * it MUST NOT be present.
400 * RELATED-TO 0+
401 * RRULE 0+
402 * SEQUENCE 0 or 1 MUST echo the original SEQUENCE number.
403 * MUST be present if non-zero. MAY be
404 * present if zero.
405 * STATUS 0 or 1 MAY be one of DRAFT/FINAL/CANCELLED
406 * SUMMARY 0 or 1 Can be null
407 * URL 0 or 1
408 * X-PROPERTY 0+
409 *
410 * ATTENDEE 0
411 *
412 * VALARM 0+
413 * VTIMEZONE 0+ MUST be present if any date/time refers to
414 * a timezone
415 * X-COMPONENT 0+
416 *
417 * VEVENT 0
418 * VFREEBUSY 0
419 * VTODO 0
420 * </pre>
421 *
422 */
423 private class PublishValidator implements Validator {
425 private static final long serialVersionUID = 1L;
427 public void validate() throws ValidationException {
428 PropertyValidator.getInstance().assertOne(Property.DESCRIPTION, getProperties());
429 PropertyValidator.getInstance().assertOne(Property.DTSTAMP, getProperties());
430 PropertyValidator.getInstance().assertOne(Property.DTSTART, getProperties());
431 PropertyValidator.getInstance().assertOne(Property.ORGANIZER, getProperties());
432 PropertyValidator.getInstance().assertOne(Property.UID, getProperties());
434 PropertyValidator.getInstance().assertOneOrLess(Property.CATEGORIES, getProperties());
435 PropertyValidator.getInstance().assertOneOrLess(Property.CLASS, getProperties());
436 PropertyValidator.getInstance().assertOneOrLess(Property.CREATED, getProperties());
437 PropertyValidator.getInstance().assertOneOrLess(Property.LAST_MODIFIED, getProperties());
438 PropertyValidator.getInstance().assertOneOrLess(Property.RECURRENCE_ID, getProperties());
439 PropertyValidator.getInstance().assertOneOrLess(Property.SEQUENCE, getProperties());
440 PropertyValidator.getInstance().assertOneOrLess(Property.STATUS, getProperties());
441 PropertyValidator.getInstance().assertOneOrLess(Property.SUMMARY, getProperties());
442 PropertyValidator.getInstance().assertOneOrLess(Property.URL, getProperties());
444 PropertyValidator.getInstance().assertNone(Property.ATTENDEE, getProperties());
445 }
446 }
448 /**
449 * @return the optional access classification property for a journal entry
450 */
451 public final Clazz getClassification() {
452 return (Clazz) getProperty(Property.CLASS);
453 }
455 /**
456 * @return the optional creation-time property for a journal entry
457 */
458 public final Created getCreated() {
459 return (Created) getProperty(Property.CREATED);
460 }
462 /**
463 * @return the optional description property for a journal entry
464 */
465 public final Description getDescription() {
466 return (Description) getProperty(Property.DESCRIPTION);
467 }
469 /**
470 * Convenience method to pull the DTSTART out of the property list.
471 * @return The DtStart object representation of the start Date
472 */
473 public final DtStart getStartDate() {
474 return (DtStart) getProperty(Property.DTSTART);
475 }
477 /**
478 * @return the optional last-modified property for a journal entry
479 */
480 public final LastModified getLastModified() {
481 return (LastModified) getProperty(Property.LAST_MODIFIED);
482 }
484 /**
485 * @return the optional organizer property for a journal entry
486 */
487 public final Organizer getOrganizer() {
488 return (Organizer) getProperty(Property.ORGANIZER);
489 }
491 /**
492 * @return the optional date-stamp property
493 */
494 public final DtStamp getDateStamp() {
495 return (DtStamp) getProperty(Property.DTSTAMP);
496 }
498 /**
499 * @return the optional sequence number property for a journal entry
500 */
501 public final Sequence getSequence() {
502 return (Sequence) getProperty(Property.SEQUENCE);
503 }
505 /**
506 * @return the optional status property for a journal entry
507 */
508 public final Status getStatus() {
509 return (Status) getProperty(Property.STATUS);
510 }
512 /**
513 * @return the optional summary property for a journal entry
514 */
515 public final Summary getSummary() {
516 return (Summary) getProperty(Property.SUMMARY);
517 }
519 /**
520 * @return the optional URL property for a journal entry
521 */
522 public final Url getUrl() {
523 return (Url) getProperty(Property.URL);
524 }
526 /**
527 * @return the optional recurrence identifier property for a journal entry
528 */
529 public final RecurrenceId getRecurrenceId() {
530 return (RecurrenceId) getProperty(Property.RECURRENCE_ID);
531 }
533 /**
534 * Returns the UID property of this component if available.
535 * @return a Uid instance, or null if no UID property exists
536 */
537 public final Uid getUid() {
538 return (Uid) getProperty(Property.UID);
539 }
540 }