001package biweekly.parameter; 002 003import java.util.AbstractList; 004import java.util.ArrayList; 005import java.util.Arrays; 006import java.util.Collections; 007import java.util.List; 008import java.util.Map; 009 010import com.github.mangstadt.vinnie.SyntaxStyle; 011import com.github.mangstadt.vinnie.validate.AllowedCharacters; 012import com.github.mangstadt.vinnie.validate.VObjectValidator; 013 014import biweekly.ICalDataType; 015import biweekly.ICalVersion; 016import biweekly.Messages; 017import biweekly.ValidationWarning; 018import biweekly.property.Attendee; 019import biweekly.property.Conference; 020import biweekly.property.FreeBusy; 021import biweekly.property.Image; 022import biweekly.property.Organizer; 023import biweekly.property.RecurrenceId; 024import biweekly.property.RelatedTo; 025import biweekly.property.Trigger; 026import biweekly.util.ListMultimap; 027 028/* 029 Copyright (c) 2013-2017, Michael Angstadt 030 All rights reserved. 031 032 Redistribution and use in source and binary forms, with or without 033 modification, are permitted provided that the following conditions are met: 034 035 1. Redistributions of source code must retain the above copyright notice, this 036 list of conditions and the following disclaimer. 037 2. Redistributions in binary form must reproduce the above copyright notice, 038 this list of conditions and the following disclaimer in the documentation 039 and/or other materials provided with the distribution. 040 041 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 042 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 043 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 044 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 045 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 046 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 047 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 048 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 049 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 050 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 051 */ 052 053/** 054 * Stores the parameters that belong to a property. 055 * @author Michael Angstadt 056 */ 057public class ICalParameters extends ListMultimap<String, String> { 058 /** 059 * Contains a URI that points to additional information about the entity 060 * represented by the property. 061 * @see <a href="http://tools.ietf.org/html/rfc5545#page-14">RFC 5545 062 * p.14-5</a> 063 */ 064 public static final String ALTREP = "ALTREP"; 065 066 /** 067 * Defines the character set that the property value is encoded in (for 068 * example, "UTF-8"). It is only used in the vCal 1.0 standard, and is 069 * typically used when a property value is encoded in quoted-printable 070 * encoding. 071 * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.16</a> 072 */ 073 public static final String CHARSET = "CHARSET"; 074 075 /** 076 * Contains a human-readable, display name of the entity represented by this 077 * property (for example, "John Doe"). It is used by the {@link Attendee} 078 * and {@link Organizer} properties. 079 * @see <a href="http://tools.ietf.org/html/rfc5545#page-15">RFC 5545 080 * p.15-6</a> 081 */ 082 public static final String CN = "CN"; 083 084 /** 085 * Used by the {@link Attendee} property. It defines the type of object that 086 * the attendee is (for example, an "individual" or a "room"). 087 * @see <a href="http://tools.ietf.org/html/rfc5545#page-16">RFC 5545 088 * p.16</a> 089 */ 090 public static final String CUTYPE = "CUTYPE"; 091 092 /** 093 * Used by the {@link Attendee} property. It stores a list of people who 094 * have delegated their responsibility to the attendee. The values must be 095 * URIs. They are typically email URIs (for example, 096 * "mailto:janedoe@example.com"). 097 * @see <a href="http://tools.ietf.org/html/rfc5545#page-17">RFC 5545 098 * p.17</a> 099 */ 100 public static final String DELEGATED_FROM = "DELEGATED-FROM"; 101 102 /** 103 * Used by the {@link Attendee} property. It stores a list of people to 104 * which the attendee has delegated his or her responsibility. The values 105 * must be URIs. They are typically email URIs (for example, 106 * "mailto:janedoe@example.com"). 107 * @see <a href="http://tools.ietf.org/html/rfc5545#page-17">RFC 5545 108 * p.17-8</a> 109 */ 110 public static final String DELEGATED_TO = "DELEGATED-TO"; 111 112 /** 113 * Contains a URI (such as an LDAP URI) which points to additional 114 * information about the person that the property represents. It is used by 115 * the {@link Attendee} and {@link Organizer} properties. 116 * @see <a href="http://tools.ietf.org/html/rfc5545#page-18">RFC 5545 117 * p.18</a> 118 */ 119 public static final String DIR = "DIR"; 120 121 /** 122 * Used by the {@link Image} property. It defines the ways in which the 123 * client application should display the image (for example, as a 124 * thumbnail-sized image). 125 * @see <a href= 126 * "https://tools.ietf.org/html/draft-ietf-calext-extensions-01#page-13" > 127 * draft-ietf-calext-extensions p.13</a> 128 */ 129 public static final String DISPLAY = "DISPLAY"; 130 131 /** 132 * Used by the {@link Attendee} property. Normally, this property's value 133 * contains the email address of the attendee. But if the property value 134 * must hold something else, this parameter can be used to store the 135 * attendee's email address. 136 * @see <a href= 137 * "https://tools.ietf.org/html/draft-ietf-calext-extensions-01#page-14" > 138 * draft-ietf-calext-extensions p.14</a> 139 */ 140 public static final String EMAIL = "EMAIL"; 141 142 /** 143 * Defines how the property value is encoded (for example, "base64" for a 144 * binary value). 145 * @see <a href="http://tools.ietf.org/html/rfc5545#page-18">RFC 5545 146 * p.18-9</a> 147 */ 148 public static final String ENCODING = "ENCODING"; 149 150 /** 151 * Used by the {@link Attendee} property. It defines whether the event 152 * organizer expects the attendee to attend or not. It is only used in the 153 * vCal 1.0 standard. 154 * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.25</a> 155 */ 156 public static final String EXPECT = "EXPECT"; 157 158 /** 159 * Used by the {@link Conference} property. It defines the features that the 160 * conference supports (for example, audio and video). 161 * @see <a href= 162 * "https://tools.ietf.org/html/draft-ietf-calext-extensions-01#page-15" > 163 * draft-ietf-calext-extensions p.15</a> 164 */ 165 public static final String FEATURE = "FEATURE"; 166 167 /** 168 * Defines the content type of the property value (for example, "image/jpg" 169 * if the property value is a JPEG image). 170 * @see <a href="http://tools.ietf.org/html/rfc5545#page-19">RFC 5545 171 * p.19-20</a> 172 */ 173 public static final String FMTTYPE = "FMTTYPE"; 174 175 /** 176 * Used by the {@link FreeBusy} property. It defines whether the person is 177 * "free" or "busy" over the time periods that are specified in the property 178 * value. If this parameter is not set, the user should be considered "busy" 179 * during these times. 180 * @see <a href="http://tools.ietf.org/html/rfc5545#page-20">RFC 5545 181 * p.20</a> 182 */ 183 public static final String FBTYPE = "FBTYPE"; 184 185 /** 186 * Defines a human-readable label for the property. 187 * @see <a href= 188 * "http://tools.ietf.org/html/draft-ietf-calext-extensions-01#page-16"> 189 * draft-ietf-calext-extensions-01 p.16</a> 190 */ 191 public static final String LABEL = "LABEL"; 192 193 /** 194 * Defines the language that the property value is written in (for example, 195 * "en" for English). 196 * @see <a href="http://tools.ietf.org/html/rfc5545#page-21">RFC 5545 197 * p.21</a> 198 */ 199 public static final String LANGUAGE = "LANGUAGE"; 200 201 /** 202 * Used by the {@link Attendee} property. It defines the groups that the 203 * attendee is a member of in the form of URIs. Typically, these are email 204 * URIs (for example, "mailto:mailinglist@example.com"). 205 * @see <a href="http://tools.ietf.org/html/rfc5545#page-21">RFC 5545 206 * p.21-2</a> 207 */ 208 public static final String MEMBER = "MEMBER"; 209 210 /** 211 * Used by the {@link Attendee} property. It defines the participation 212 * status of the attendee (for example, "ACCEPTED"). If none is defined, 213 * then the property should be treated as if this parameter was set to 214 * "NEEDS-ACTION". 215 * @see <a href="http://tools.ietf.org/html/rfc5545#page-22">RFC 5545 216 * p.22</a> 217 */ 218 public static final String PARTSTAT = "PARTSTAT"; 219 220 /** 221 * Used by the {@link RecurrenceId} property. It defines the effective range 222 * of recurrence instances that the property references. 223 * @see <a href="http://tools.ietf.org/html/rfc5545#page-23">RFC 5545 224 * p.23-4</a> 225 */ 226 public static final String RANGE = "RANGE"; 227 228 /** 229 * Used by the {@link Trigger} property. It defines the date-time field that 230 * the property's duration (if specified) is relative to (for example, the 231 * start date or the end date). 232 * @see <a href="http://tools.ietf.org/html/rfc5545#page-24">RFC 5545 233 * p.24</a> 234 */ 235 public static final String RELATED = "RELATED"; 236 237 /** 238 * Used by the {@link RelatedTo} property. It defines the kind of 239 * relationship the property is describing (for example, a "child" 240 * relationship). 241 * @see <a href="http://tools.ietf.org/html/rfc5545#page-25">RFC 5545 242 * p.25</a> 243 */ 244 public static final String RELTYPE = "RELTYPE"; 245 246 /** 247 * Used by the {@link Attendee} property. It defines the attendee's role 248 * and/or whether they must attend or not (for example, "OPT-PARTICIPANT" 249 * for "optional participant"). If none is defined, then the property should 250 * be treated as if this parameter was set to "REQ-PARTICIPANT" (required 251 * participant). 252 * @see <a href="http://tools.ietf.org/html/rfc5545#page-25">RFC 5545 253 * p.25</a> 254 * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.25</a> 255 */ 256 public static final String ROLE = "ROLE"; 257 258 /** 259 * Used by the {@link Attendee} property. It defines whether the event 260 * organizer would like the attendee to reply with his or her intention of 261 * attending ("true" if the organizer would like a reply, "false" if not). 262 * If this parameter is not defined, then the property should be treated as 263 * if this parameter was set to "false". 264 * @see <a href="http://tools.ietf.org/html/rfc5545#page-26">RFC 5545 265 * p.26</a> 266 * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.25</a> 267 */ 268 public static final String RSVP = "RSVP"; 269 270 /** 271 * Defines a URI which represents a person who is acting on behalf of the 272 * person that is defined in the property. Typically, the URI is an email 273 * URI (for example, "mailto:janedoe@example.com"). It is used by the 274 * {@link Attendee} and {@link Organizer} properties. 275 * @see <a href="http://tools.ietf.org/html/rfc5545#page-27">RFC 5545 276 * p.27</a> 277 */ 278 public static final String SENT_BY = "SENT-BY"; 279 280 /** 281 * Used by the {@link Attendee} property. It defines the status of the 282 * person's event invitation (for example, "TENTATIVE" if the person may or 283 * may not attend). It is only used in the vCal 1.0 standard. 284 * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.25</a> 285 */ 286 public static final String STATUS = "STATUS"; 287 288 /** 289 * Defines the content type of the property value (for example, "WAVE" for 290 * an audio file). It is only used in the vCal 1.0 standard. 291 * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.27</a> 292 */ 293 public static final String TYPE = "TYPE"; 294 295 /** 296 * Used by properties that contain date-time values. It defines the timezone 297 * that the property value is formatted in. It either references a timezone 298 * defined in a VTIMEZONE component, or contains an Olson timezone ID. To 299 * use an Olson timezone ID, the parameter value must be prepended with a 300 * "/" (for example, "/America/New_York"). 301 * @see <a href="http://tools.ietf.org/html/rfc5545#page-27">RFC 5545 302 * p.27-8</a> 303 */ 304 public static final String TZID = "TZID"; 305 306 /** 307 * Defines the data type of the property value (for example, "date" if the 308 * property value is a date without a time component). It is used if the 309 * property accepts multiple values that have different data types. 310 * @see <a href="http://tools.ietf.org/html/rfc5545#page-29">RFC 5545 311 * p.29-50</a> 312 */ 313 public static final String VALUE = "VALUE"; 314 315 /** 316 * Creates a parameters list. 317 */ 318 public ICalParameters() { 319 /* 320 * Initialize map size to 0 because most properties don't use any 321 * parameters. 322 */ 323 super(0); 324 } 325 326 /** 327 * Copies an existing parameters list. 328 * @param parameters the list to copy 329 */ 330 public ICalParameters(ICalParameters parameters) { 331 super(parameters); 332 } 333 334 /** 335 * <p> 336 * Creates a parameter list that is backed by the given map. Any changes 337 * made to the given map will effect the parameter list and vice versa. 338 * </p> 339 * <p> 340 * Care must be taken to ensure that the given map's keys are all in 341 * uppercase. 342 * </p> 343 * <p> 344 * To avoid problems, it is highly recommended that the given map NOT be 345 * modified by anything other than this {@link ICalParameters} class after 346 * being passed into this constructor. 347 * </p> 348 * @param map the map 349 */ 350 public ICalParameters(Map<String, List<String>> map) { 351 super(map); 352 } 353 354 /** 355 * <p> 356 * Gets the ALTREP (alternate representation) parameter value. 357 * </p> 358 * <p> 359 * This parameter contains a URI that points to additional information about 360 * the entity represented by the property. 361 * </p> 362 * @return the URI or null if not set 363 * @see <a href="http://tools.ietf.org/html/rfc5545#page-14">RFC 5545 364 * p.14-5</a> 365 */ 366 public String getAltRepresentation() { 367 return first(ALTREP); 368 } 369 370 /** 371 * <p> 372 * Sets the ALTREP (alternate representation) parameter value. 373 * </p> 374 * <p> 375 * This parameter contains a URI that points to additional information about 376 * the entity represented by the property. 377 * </p> 378 * @param uri the URI or null to remove 379 * @see <a href="http://tools.ietf.org/html/rfc5545#page-14">RFC 5545 380 * p.14-5</a> 381 */ 382 public void setAltRepresentation(String uri) { 383 replace(ALTREP, uri); 384 } 385 386 /** 387 * <p> 388 * Gets the CHARSET parameter value. 389 * </p> 390 * <p> 391 * This parameter contains the character set that the property value is 392 * encoded in (for example, "UTF-8"). It is only used in the vCal 1.0 393 * standard, and is typically used when a property value is encoded in 394 * quoted-printable encoding. 395 * </p> 396 * @return the character set or null if not set 397 * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.16</a> 398 */ 399 public String getCharset() { 400 return first(CHARSET); 401 } 402 403 /** 404 * <p> 405 * Sets the CHARSET parameter value. 406 * </p> 407 * <p> 408 * This parameter contains the character set that the property value is 409 * encoded in (for example, "UTF-8"). It is only used in the vCal 1.0 410 * standard, and is typically used when a property value is encoded in 411 * quoted-printable encoding. 412 * </p> 413 * @param charset the character set or null to remove 414 * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.16</a> 415 */ 416 public void setCharset(String charset) { 417 replace(CHARSET, charset); 418 } 419 420 /** 421 * <p> 422 * Gets the CN (common name) parameter value. 423 * </p> 424 * <p> 425 * This parameter contains a human-readable, display name of the entity 426 * represented by this property (for example, "John Doe"). It is used by the 427 * {@link Attendee} and {@link Organizer} properties. 428 * </p> 429 * @return the common name or null if not set 430 * @see <a href="http://tools.ietf.org/html/rfc5545#page-15">RFC 5545 431 * p.15-6</a> 432 */ 433 public String getCommonName() { 434 return first(CN); 435 } 436 437 /** 438 * <p> 439 * Sets the CN (common name) parameter value. 440 * </p> 441 * <p> 442 * This parameter contains a human-readable, display name of the entity 443 * represented by this property (for example, "John Doe"). It is used by the 444 * {@link Attendee} and {@link Organizer} properties. 445 * </p> 446 * @param cn the common name or null to remove 447 * @see <a href="http://tools.ietf.org/html/rfc5545#page-15">RFC 5545 448 * p.15-6</a> 449 */ 450 public void setCommonName(String cn) { 451 replace(CN, cn); 452 } 453 454 /** 455 * <p> 456 * Gets the CUTYPE (calendar user type) parameter value. 457 * </p> 458 * <p> 459 * This parameter is used by the {@link Attendee} property. It defines the 460 * type of object that the attendee is (for example, an "individual" or a 461 * "room"). 462 * </p> 463 * @return the calendar user type or null if not set 464 * @see <a href="http://tools.ietf.org/html/rfc5545#page-16">RFC 5545 465 * p.16</a> 466 */ 467 public CalendarUserType getCalendarUserType() { 468 String value = first(CUTYPE); 469 return (value == null) ? null : CalendarUserType.get(value); 470 } 471 472 /** 473 * <p> 474 * Sets the CUTYPE (calendar user type) parameter value. 475 * </p> 476 * <p> 477 * This parameter is used by the {@link Attendee} property. It defines the 478 * type of object that the attendee is (for example, an "individual" or a 479 * "room"). 480 * </p> 481 * @param calendarUserType the calendar user type or null to remove 482 * @see <a href="http://tools.ietf.org/html/rfc5545#page-16">RFC 5545 483 * p.16</a> 484 */ 485 public void setCalendarUserType(CalendarUserType calendarUserType) { 486 replace(CUTYPE, (calendarUserType == null) ? null : calendarUserType.getValue()); 487 } 488 489 /** 490 * <p> 491 * Gets the DELEGATED-FROM parameter values. 492 * </p> 493 * <p> 494 * This parameter is used by the {@link Attendee} property. It stores a list 495 * of people who have delegated their responsibility to the attendee. The 496 * values must be URIs. They are typically email URIs (for example, 497 * "mailto:janedoe@example.com"). 498 * </p> 499 * <p> 500 * Changes to the returned list will update the {@link ICalParameters} 501 * object, and vice versa. 502 * </p> 503 * @return the URIs or an empty list if none are set 504 * @see <a href="http://tools.ietf.org/html/rfc5545#page-17">RFC 5545 505 * p.17</a> 506 */ 507 public List<String> getDelegatedFrom() { 508 return get(DELEGATED_FROM); 509 } 510 511 /** 512 * <p> 513 * Gets the DELEGATED-TO parameter values. 514 * </p> 515 * <p> 516 * This parameter is used by the {@link Attendee} property. It stores a list 517 * of people to which the attendee has delegated his or her responsibility. 518 * The values must be URIs. They are typically email URIs (for example, 519 * "mailto:janedoe@example.com"). 520 * </p> 521 * <p> 522 * Changes to the returned list will update the {@link ICalParameters} 523 * object, and vice versa. 524 * </p> 525 * @return the URIs or an empty list if none are set 526 * @see <a href="http://tools.ietf.org/html/rfc5545#page-17">RFC 5545 527 * p.17-8</a> 528 */ 529 public List<String> getDelegatedTo() { 530 return get(DELEGATED_TO); 531 } 532 533 /** 534 * <p> 535 * Gets the DIR (directory entry) parameter value. 536 * </p> 537 * <p> 538 * This parameter contains a URI (such as an LDAP URI) which points to 539 * additional information about the person that the property represents. It 540 * is used by the {@link Attendee} and {@link Organizer} properties. 541 * </p> 542 * @return the URI or null if not set 543 * @see <a href="http://tools.ietf.org/html/rfc5545#page-18">RFC 5545 544 * p.18</a> 545 */ 546 public String getDirectoryEntry() { 547 return first(DIR); 548 } 549 550 /** 551 * <p> 552 * Sets the DIR (directory entry) parameter value. 553 * </p> 554 * <p> 555 * This parameter contains a URI (such as an LDAP URI) which points to 556 * additional information about the person that the property represents. It 557 * is used by the {@link Attendee} and {@link Organizer} properties. 558 * </p> 559 * @param uri the URI or null to remove 560 * @see <a href="http://tools.ietf.org/html/rfc5545#page-18">RFC 5545 561 * p.18</a> 562 */ 563 public void setDirectoryEntry(String uri) { 564 replace(DIR, uri); 565 } 566 567 /** 568 * <p> 569 * Gets the DISPLAY parameter values. 570 * </p> 571 * <p> 572 * This parameter is used by the {@link Image} property. It defines the ways 573 * in which the client application should display the image (for example, as 574 * a thumbnail-sized image). 575 * </p> 576 * <p> 577 * Changes to the returned list will update the {@link ICalParameters} 578 * object, and vice versa. 579 * </p> 580 * @return the display suggestions or empty list if none are defined 581 * @see <a href= 582 * "https://tools.ietf.org/html/draft-ietf-calext-extensions-01#page-13" > 583 * draft-ietf-calext-extensions p.13</a> 584 */ 585 public List<Display> getDisplays() { 586 return new EnumParameterList<Display>(DISPLAY) { 587 @Override 588 protected Display _asObject(String value) { 589 return Display.get(value); 590 } 591 }; 592 } 593 594 /** 595 * <p> 596 * Gets the EMAIL parameter value. 597 * </p> 598 * <p> 599 * This parameter is used by the {@link Attendee} property. Normally, this 600 * property's value contains the email address of the attendee. But if the 601 * property value must hold something else, this parameter can be used to 602 * store the attendee's email address. 603 * </p> 604 * @return the email or null if not set 605 * @see <a href= 606 * "https://tools.ietf.org/html/draft-ietf-calext-extensions-01#page-14" > 607 * draft-ietf-calext-extensions p.14</a> 608 */ 609 public String getEmail() { 610 return first(EMAIL); 611 } 612 613 /** 614 * <p> 615 * Sets the EMAIL parameter value. 616 * </p> 617 * <p> 618 * This parameter is used by the {@link Attendee} property. Normally, this 619 * property's value contains the email address of the attendee. But if the 620 * property value must hold something else, this parameter can be used to 621 * store the attendee's email address. 622 * </p> 623 * @param email the email or null to remove 624 * @see <a href= 625 * "https://tools.ietf.org/html/draft-ietf-calext-extensions-01#page-14" > 626 * draft-ietf-calext-extensions p.14</a> 627 */ 628 public void setEmail(String email) { 629 replace(EMAIL, email); 630 } 631 632 /** 633 * <p> 634 * Gets the ENCODING parameter value. 635 * </p> 636 * <p> 637 * This parameter defines how the property value is encoded (for example, 638 * "base64" for a binary value). 639 * </p> 640 * @return the encoding or null if not set 641 * @see <a href="http://tools.ietf.org/html/rfc5545#page-18">RFC 5545 642 * p.18-9</a> 643 */ 644 public Encoding getEncoding() { 645 String value = first(ENCODING); 646 return (value == null) ? null : Encoding.get(value); 647 } 648 649 /** 650 * <p> 651 * Sets the ENCODING parameter value. 652 * </p> 653 * <p> 654 * This parameter defines how the property value is encoded (for example, 655 * "base64" for a binary value). 656 * </p> 657 * @param encoding the encoding or null to remove 658 * @see <a href="http://tools.ietf.org/html/rfc5545#page-18">RFC 5545 659 * p.18-9</a> 660 */ 661 public void setEncoding(Encoding encoding) { 662 replace(ENCODING, (encoding == null) ? null : encoding.getValue()); 663 } 664 665 /** 666 * <p> 667 * Gets the EXPECT parameter value. 668 * </p> 669 * <p> 670 * This parameter is used by the {@link Attendee} property. It defines 671 * whether the event organizer expects the attendee to attend or not. It is 672 * only used in the vCal 1.0 standard. 673 * </p> 674 * @return the attendance expectation or null if not set 675 * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.25</a> 676 */ 677 public String getExpect() { 678 return first(EXPECT); 679 } 680 681 /** 682 * <p> 683 * Sets the EXPECT parameter value. 684 * </p> 685 * <p> 686 * This parameter is used by the {@link Attendee} property. It defines 687 * whether the event organizer expects the attendee to attend or not. It is 688 * only used in the vCal 1.0 standard. 689 * </p> 690 * @param expect the attendance expectation or null if not set 691 * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.25</a> 692 */ 693 public void setExpect(String expect) { 694 replace(EXPECT, expect); 695 } 696 697 /** 698 * <p> 699 * Gets the FEATURE parameter values. 700 * </p> 701 * <p> 702 * This parameter is used by the {@link Conference} property. It defines the 703 * features that the conference supports (for example, audio and video). 704 * </p> 705 * <p> 706 * Changes to the returned list will update the {@link ICalParameters} 707 * object, and vice versa. 708 * </p> 709 * @return the features or empty list if none are set 710 * @see <a href= 711 * "https://tools.ietf.org/html/draft-ietf-calext-extensions-01#page-15" > 712 * draft-ietf-calext-extensions p.15</a> 713 */ 714 public List<Feature> getFeatures() { 715 return new EnumParameterList<Feature>(FEATURE) { 716 @Override 717 protected Feature _asObject(String value) { 718 return Feature.get(value); 719 } 720 }; 721 } 722 723 /** 724 * <p> 725 * Gets the FMTTYPE (format type) parameter value. 726 * </p> 727 * <p> 728 * This parameter defines the content type of the property value (for 729 * example, "image/jpg" if the property value is a JPEG image). 730 * </p> 731 * @return the format type or null if not set 732 * @see <a href="http://tools.ietf.org/html/rfc5545#page-19">RFC 5545 733 * p.19-20</a> 734 */ 735 public String getFormatType() { 736 return first(FMTTYPE); 737 } 738 739 /** 740 * <p> 741 * Sets the FMTTYPE (format type) parameter value. 742 * </p> 743 * <p> 744 * This parameter defines the content type of the property value (for 745 * example, "image/jpg" if the property value is a JPEG image). 746 * </p> 747 * @param formatType the format type or null to remove 748 * @see <a href="http://tools.ietf.org/html/rfc5545#page-19">RFC 5545 749 * p.19-20</a> 750 */ 751 public void setFormatType(String formatType) { 752 replace(FMTTYPE, formatType); 753 } 754 755 /** 756 * <p> 757 * Gets the FBTYPE (free busy type) parameter value. 758 * </p> 759 * <p> 760 * This parameter is used by the {@link FreeBusy} property. It defines 761 * whether the person is "free" or "busy" over the time periods that are 762 * specified in the property value. If this parameter is not set, the user 763 * should be considered "busy" during these times. 764 * </p> 765 * @return the free busy type or null if not set 766 * @see <a href="http://tools.ietf.org/html/rfc5545#page-20">RFC 5545 767 * p.20</a> 768 */ 769 public FreeBusyType getFreeBusyType() { 770 String value = first(FBTYPE); 771 return (value == null) ? null : FreeBusyType.get(value); 772 } 773 774 /** 775 * <p> 776 * Sets the FBTYPE (free busy type) parameter value. 777 * </p> 778 * <p> 779 * This parameter is used by the {@link FreeBusy} property. It defines 780 * whether the person is "free" or "busy" over the time periods that are 781 * specified in the property value. If this parameter is not set, the user 782 * should be considered "busy" during these times. 783 * </p> 784 * @param freeBusyType the free busy type or null to remove 785 * @see <a href="http://tools.ietf.org/html/rfc5545#page-20">RFC 5545 786 * p.20</a> 787 */ 788 public void setFreeBusyType(FreeBusyType freeBusyType) { 789 replace(FBTYPE, (freeBusyType == null) ? null : freeBusyType.getValue()); 790 } 791 792 /** 793 * <p> 794 * Gets the LABEL parameter value. 795 * </p> 796 * <p> 797 * This parameter defines a human-readable label for the property. 798 * </p> 799 * @return the label or null if not set 800 * @see <a href= 801 * "http://tools.ietf.org/html/draft-ietf-calext-extensions-01#page-16"> 802 * draft-ietf-calext-extensions-01 p.16</a> 803 */ 804 public String getLabel() { 805 return first(LABEL); 806 } 807 808 /** 809 * <p> 810 * Sets the LABEL parameter value. 811 * </p> 812 * <p> 813 * This parameter defines a human-readable label for the property. 814 * </p> 815 * @param label the label or null to remove 816 * @see <a href= 817 * "http://tools.ietf.org/html/draft-ietf-calext-extensions-01#page-16"> 818 * draft-ietf-calext-extensions-01 p.16</a> 819 */ 820 public void setLabel(String label) { 821 replace(LABEL, label); 822 } 823 824 /** 825 * <p> 826 * Gets the LANGUAGE parameter value. 827 * </p> 828 * <p> 829 * This parameter defines the language that the property value is written in 830 * (for example, "en" for English). 831 * </p> 832 * @return the language or null if not set 833 * @see <a href="http://tools.ietf.org/html/rfc5545#page-21">RFC 5545 834 * p.21</a> 835 */ 836 public String getLanguage() { 837 return first(LANGUAGE); 838 } 839 840 /** 841 * <p> 842 * Sets the LANGUAGE parameter value. 843 * </p> 844 * <p> 845 * This parameter defines the language that the property value is written in 846 * (for example, "en" for English). 847 * </p> 848 * @param language the language or null to remove 849 * @see <a href="http://tools.ietf.org/html/rfc5545#page-21">RFC 5545 850 * p.21</a> 851 */ 852 public void setLanguage(String language) { 853 replace(LANGUAGE, language); 854 } 855 856 /** 857 * <p> 858 * Gets the MEMBER property values. 859 * </p> 860 * <p> 861 * This parameter is used by the {@link Attendee} property. It defines the 862 * groups that the attendee is a member of in the form of URIs. Typically, 863 * these are email URIs (for example, "mailto:mailinglist@example.com"). 864 * </p> 865 * <p> 866 * Changes to the returned list will update the {@link ICalParameters} 867 * object, and vice versa. 868 * </p> 869 * @return the groups or empty list if none are set 870 * @see <a href="http://tools.ietf.org/html/rfc5545#page-21">RFC 5545 871 * p.21-2</a> 872 */ 873 public List<String> getMembers() { 874 return get(MEMBER); 875 } 876 877 /** 878 * <p> 879 * Gets the PARTSTAT (participation status) parameter value. 880 * </p> 881 * <p> 882 * This parameter is used by the {@link Attendee} property. It defines the 883 * participation status of the attendee (for example, "ACCEPTED"). If none 884 * is defined, then the property should be treated as if this parameter was 885 * set to "NEEDS-ACTION". 886 * </p> 887 * @return the participation status or null if not set 888 * @see <a href="http://tools.ietf.org/html/rfc5545#page-22">RFC 5545 889 * p.22</a> 890 */ 891 public String getParticipationStatus() { 892 return first(PARTSTAT); 893 } 894 895 /** 896 * <p> 897 * Gets the PARTSTAT (participation status) parameter value. 898 * </p> 899 * <p> 900 * This parameter is used by the {@link Attendee} property. It defines the 901 * participation status of the attendee (for example, "ACCEPTED"). If none 902 * is defined, then the property should be treated as if this parameter was 903 * set to "NEEDS-ACTION". 904 * </p> 905 * @param participationStatus the participation status or null to remove 906 * @see <a href="http://tools.ietf.org/html/rfc5545#page-22">RFC 5545 907 * p.22</a> 908 */ 909 public void setParticipationStatus(String participationStatus) { 910 replace(PARTSTAT, participationStatus); 911 } 912 913 /** 914 * <p> 915 * Gets the RANGE parameter value. 916 * </p> 917 * <p> 918 * This parameter is used by the {@link RecurrenceId} property. It defines 919 * the effective range of recurrence instances that the property references. 920 * </p> 921 * @return the range or null if not set 922 * @see <a href="http://tools.ietf.org/html/rfc5545#page-23">RFC 5545 923 * p.23-4</a> 924 */ 925 public Range getRange() { 926 String value = first(RANGE); 927 return (value == null) ? null : Range.get(value); 928 } 929 930 /** 931 * <p> 932 * Sets the RANGE parameter value. 933 * </p> 934 * <p> 935 * This parameter is used by the {@link RecurrenceId} property. It defines 936 * the effective range of recurrence instances that the property references. 937 * </p> 938 * @param range the range or null to remove 939 * @see <a href="http://tools.ietf.org/html/rfc5545#page-23">RFC 5545 940 * p.23-4</a> 941 */ 942 public void setRange(Range range) { 943 replace(RANGE, (range == null) ? null : range.getValue()); 944 } 945 946 /** 947 * <p> 948 * Gets the RELATED parameter value. 949 * </p> 950 * <p> 951 * This parameter is used by the {@link Trigger} property. It defines the 952 * date-time field that the property's duration (if specified) is relative 953 * to (for example, the start date or the end date). 954 * </p> 955 * @return the related field or null if not set 956 * @see <a href="http://tools.ietf.org/html/rfc5545#page-24">RFC 5545 957 * p.24</a> 958 */ 959 public Related getRelated() { 960 String value = first(RELATED); 961 return (value == null) ? null : Related.get(value); 962 } 963 964 /** 965 * <p> 966 * Sets the RELATED parameter value. 967 * </p> 968 * <p> 969 * This parameter is used by the {@link Trigger} property. It defines the 970 * date-time field that the property's duration (if specified) is relative 971 * to (for example, the start date or the end date). 972 * </p> 973 * @param related the related field or null to remove 974 * @see <a href="http://tools.ietf.org/html/rfc5545#page-24">RFC 5545 975 * p.24</a> 976 */ 977 public void setRelated(Related related) { 978 replace(RELATED, (related == null) ? null : related.getValue()); 979 } 980 981 /** 982 * <p> 983 * Gets the RELTYPE (relationship type) parameter value. 984 * </p> 985 * <p> 986 * This parameter is used by the {@link RelatedTo} property. It defines the 987 * kind of relationship the property is describing (for example, a "child" 988 * relationship). 989 * </p> 990 * @return the relationship type or null if not set 991 * @see <a href="http://tools.ietf.org/html/rfc5545#page-25">RFC 5545 992 * p.25</a> 993 */ 994 public RelationshipType getRelationshipType() { 995 String value = first(RELTYPE); 996 return (value == null) ? null : RelationshipType.get(value); 997 } 998 999 /** 1000 * <p> 1001 * Sets the RELTYPE (relationship type) parameter value. 1002 * </p> 1003 * <p> 1004 * This parameter is used by the {@link RelatedTo} property. It defines the 1005 * kind of relationship the property is describing (for example, a "child" 1006 * relationship). 1007 * </p> 1008 * @param relationshipType the relationship type or null to remove 1009 * @see <a href="http://tools.ietf.org/html/rfc5545#page-25">RFC 5545 1010 * p.25</a> 1011 */ 1012 public void setRelationshipType(RelationshipType relationshipType) { 1013 replace(RELTYPE, (relationshipType == null) ? null : relationshipType.getValue()); 1014 } 1015 1016 /** 1017 * <p> 1018 * Gets the ROLE parameter value. 1019 * </p> 1020 * <p> 1021 * This parameter is used by the {@link Attendee} property. It defines the 1022 * attendee's role and/or whether they must attend or not (for example, 1023 * "OPT-PARTICIPANT" for "optional participant"). If none is defined, then 1024 * the property should be treated as if this parameter was set to 1025 * "REQ-PARTICIPANT" (required participant). 1026 * </p> 1027 * @return the role or null if not set 1028 * @see <a href="http://tools.ietf.org/html/rfc5545#page-25">RFC 5545 1029 * p.25</a> 1030 * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.25</a> 1031 */ 1032 public String getRole() { 1033 /* 1034 * Note: The acceptable values for this parameter differs in vCal 1.0, 1035 * which is why this method does not return an enum. 1036 */ 1037 return first(ROLE); 1038 } 1039 1040 /** 1041 * <p> 1042 * Sets the ROLE parameter value. 1043 * </p> 1044 * <p> 1045 * This parameter is used by the {@link Attendee} property. It defines the 1046 * attendee's role and/or whether they must attend or not (for example, 1047 * "OPT-PARTICIPANT" for "optional participant"). If none is defined, then 1048 * the property should be treated as if this parameter was set to 1049 * "REQ-PARTICIPANT" (required participant). 1050 * </p> 1051 * @param role the role or null to remove 1052 * @see <a href="http://tools.ietf.org/html/rfc5545#page-25">RFC 5545 1053 * p.25</a> 1054 * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.25</a> 1055 */ 1056 public void setRole(String role) { 1057 replace(ROLE, role); 1058 } 1059 1060 /** 1061 * <p> 1062 * Gets the RSVP parameter value. 1063 * </p> 1064 * <p> 1065 * This parameter is used by the {@link Attendee} property. It defines 1066 * whether the event organizer would like the attendee to reply with his or 1067 * her intention of attending ("true" if the organizer would like a reply, 1068 * "false" if not). If this parameter is not defined, then the property 1069 * should be treated as if this parameter was set to "false". 1070 * </p> 1071 * @return the value or null if not set 1072 * @see <a href="http://tools.ietf.org/html/rfc5545#page-26">RFC 5545 1073 * p.26</a> 1074 * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.25</a> 1075 */ 1076 public String getRsvp() { 1077 /* 1078 * Note: The acceptable values for this parameter differs in vCal 1.0, 1079 * which is why this method does not return a boolean. 1080 */ 1081 return first(RSVP); 1082 } 1083 1084 /** 1085 * <p> 1086 * Sets the RSVP parameter value. 1087 * </p> 1088 * <p> 1089 * This parameter is used by the {@link Attendee} property. It defines 1090 * whether the event organizer would like the attendee to reply with his or 1091 * her intention of attending ("true" if the organizer would like a reply, 1092 * "false" if not). If this parameter is not defined, then the property 1093 * should be treated as if this parameter was set to "false". 1094 * </p> 1095 * @param rsvp the value or null to remove 1096 * @see <a href="http://tools.ietf.org/html/rfc5545#page-26">RFC 5545 1097 * p.26</a> 1098 * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.25</a> 1099 */ 1100 public void setRsvp(String rsvp) { 1101 replace(RSVP, rsvp); 1102 } 1103 1104 /** 1105 * <p> 1106 * Gets the SENT-BY parameter value. 1107 * </p> 1108 * <p> 1109 * This parameter defines a URI which represents a person who is acting on 1110 * behalf of the person that is defined in the property. Typically, the URI 1111 * is an email URI (for example, "mailto:janedoe@example.com"). It is used 1112 * by the {@link Attendee} and {@link Organizer} properties. 1113 * </p> 1114 * @return the URI or null if not set 1115 * @see <a href="http://tools.ietf.org/html/rfc5545#page-27">RFC 5545 1116 * p.27</a> 1117 */ 1118 public String getSentBy() { 1119 return first(SENT_BY); 1120 } 1121 1122 /** 1123 * <p> 1124 * Sets the SENT-BY parameter value. 1125 * </p> 1126 * <p> 1127 * This parameter defines a URI which represents a person who is acting on 1128 * behalf of the person that is defined in the property. Typically, the URI 1129 * is an email URI (for example, "mailto:janedoe@example.com"). It is used 1130 * by the {@link Attendee} and {@link Organizer} properties. 1131 * </p> 1132 * @param uri the URI or null to remove 1133 * @see <a href="http://tools.ietf.org/html/rfc5545#page-27">RFC 5545 1134 * p.27</a> 1135 */ 1136 public void setSentBy(String uri) { 1137 replace(SENT_BY, uri); 1138 } 1139 1140 /** 1141 * <p> 1142 * Gets the STATUS parameter value. 1143 * </p> 1144 * <p> 1145 * This parameter is used by the {@link Attendee} property. It defines the 1146 * status of the person's event invitation (for example, "TENTATIVE" if the 1147 * person may or may not attend). It is only used in the vCal 1.0 standard. 1148 * </p> 1149 * @return the status or null if not set 1150 * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.25</a> 1151 */ 1152 public String getStatus() { 1153 return first(STATUS); 1154 } 1155 1156 /** 1157 * <p> 1158 * Sets the STATUS parameter value. 1159 * </p> 1160 * <p> 1161 * This parameter is used by the {@link Attendee} property. It defines the 1162 * status of the person's event invitation (for example, "TENTATIVE" if the 1163 * person may or may not attend). It is only used in the vCal 1.0 standard. 1164 * </p> 1165 * @param status the status or null to remove 1166 * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.25</a> 1167 */ 1168 public void setStatus(String status) { 1169 replace(STATUS, status); 1170 } 1171 1172 /** 1173 * <p> 1174 * Gets the TZID (timezone ID) parameter value. 1175 * </p> 1176 * <p> 1177 * This parameter is used by properties that contain date-time values. It 1178 * defines the timezone that the property value is formatted in. It either 1179 * references a timezone defined in a VTIMEZONE component, or contains an 1180 * Olson timezone ID. To use an Olson timezone ID, the parameter value must 1181 * be prepended with a "/" (for example, "/America/New_York"). 1182 * </p> 1183 * @return the timezone ID or null if not set 1184 * @see <a href="http://tools.ietf.org/html/rfc5545#page-27">RFC 5545 1185 * p.27-8</a> 1186 */ 1187 public String getTimezoneId() { 1188 return first(TZID); 1189 } 1190 1191 /** 1192 * <p> 1193 * Sets the TZID (timezone ID) parameter value. 1194 * </p> 1195 * <p> 1196 * This parameter is used by properties that contain date-time values. It 1197 * defines the timezone that the property value is formatted in. It either 1198 * references a timezone defined in a VTIMEZONE component, or contains an 1199 * Olson timezone ID. To use an Olson timezone ID, the parameter value must 1200 * be prepended with a "/" (for example, "/America/New_York"). 1201 * </p> 1202 * @param timezoneId the timezone ID or null to remove 1203 * @see <a href="http://tools.ietf.org/html/rfc5545#page-27">RFC 5545 1204 * p.27-8</a> 1205 */ 1206 public void setTimezoneId(String timezoneId) { 1207 replace(TZID, timezoneId); 1208 } 1209 1210 /** 1211 * <p> 1212 * Gets the TYPE parameter value. 1213 * </p> 1214 * <p> 1215 * This parameter defines the content type of the property value (for 1216 * example, "WAVE" for an audio file). It is only used in the vCal 1.0 1217 * standard. 1218 * </p> 1219 * @return the type or null if not set 1220 * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.27</a> 1221 */ 1222 public String getType() { 1223 return first(TYPE); 1224 } 1225 1226 /** 1227 * <p> 1228 * Sets the TYPE parameter value. 1229 * </p> 1230 * <p> 1231 * This parameter defines the content type of the property value (for 1232 * example, "WAVE" for an audio file). It is only used in the vCal 1.0 1233 * standard. 1234 * </p> 1235 * @param type the type or null to remove 1236 * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.27</a> 1237 */ 1238 public void setType(String type) { 1239 replace(TYPE, type); 1240 } 1241 1242 /** 1243 * <p> 1244 * Gets the VALUE parameter value. 1245 * </p> 1246 * <p> 1247 * This parameter defines the data type of the property value (for example, 1248 * "date" if the property value is a date without a time component). It is 1249 * used if the property accepts multiple values that have different data 1250 * types. 1251 * </p> 1252 * @return the data type or null if not set 1253 * @see <a href="http://tools.ietf.org/html/rfc5545#page-29">RFC 5545 1254 * p.29-50</a> 1255 */ 1256 public ICalDataType getValue() { 1257 String value = first(VALUE); 1258 return (value == null) ? null : ICalDataType.get(value); 1259 } 1260 1261 /** 1262 * <p> 1263 * Sets the VALUE parameter value. 1264 * </p> 1265 * <p> 1266 * This parameter defines the data type of the property value (for example, 1267 * "date" if the property value is a date without a time component). It is 1268 * used if the property accepts multiple values that have different data 1269 * types. 1270 * </p> 1271 * @param dataType the data type or null to remove 1272 * @see <a href="http://tools.ietf.org/html/rfc5545#page-29">RFC 5545 1273 * p.29-50</a> 1274 */ 1275 public void setValue(ICalDataType dataType) { 1276 replace(VALUE, (dataType == null) ? null : dataType.getName()); 1277 } 1278 1279 /** 1280 * <p> 1281 * Checks the parameters for data consistency problems or deviations from 1282 * the specification. 1283 * </p> 1284 * <p> 1285 * These problems will not prevent the iCalendar object from being written 1286 * to a data stream*, but may prevent it from being parsed correctly by the 1287 * consuming application. 1288 * </p> 1289 * <p> 1290 * *With a few exceptions: One thing this method does is check for illegal 1291 * characters. There are certain characters that will break the iCalendar 1292 * syntax if written (such as a newline character in a parameter name). If 1293 * one of these characters is present, it WILL prevent the iCalendar object 1294 * from being written. 1295 * </p> 1296 * @param version the version to validate against 1297 * @return a list of warnings or an empty list if no problems were found 1298 */ 1299 public List<ValidationWarning> validate(ICalVersion version) { 1300 List<ValidationWarning> warnings = new ArrayList<ValidationWarning>(0); 1301 1302 SyntaxStyle syntax; 1303 switch (version) { 1304 case V1_0: 1305 syntax = SyntaxStyle.OLD; 1306 break; 1307 default: 1308 syntax = SyntaxStyle.NEW; 1309 break; 1310 } 1311 1312 /* 1313 * Check for invalid characters in names and values. 1314 */ 1315 for (Map.Entry<String, List<String>> entry : this) { 1316 String name = entry.getKey(); 1317 1318 //check the parameter name 1319 if (!VObjectValidator.validateParameterName(name, syntax, true)) { 1320 if (syntax == SyntaxStyle.OLD) { 1321 AllowedCharacters notAllowed = VObjectValidator.allowedCharactersParameterName(syntax, true).flip(); 1322 warnings.add(new ValidationWarning(57, name, notAllowed.toString(true))); 1323 } else { 1324 warnings.add(new ValidationWarning(54, name)); 1325 } 1326 } 1327 1328 //check the parameter value(s) 1329 List<String> values = entry.getValue(); 1330 for (String value : values) { 1331 if (!VObjectValidator.validateParameterValue(value, syntax, false, true)) { 1332 AllowedCharacters notAllowed = VObjectValidator.allowedCharactersParameterValue(syntax, false, true).flip(); 1333 int code = (syntax == SyntaxStyle.OLD) ? 58 : 53; 1334 warnings.add(new ValidationWarning(code, name, value, notAllowed.toString(true))); 1335 } 1336 } 1337 } 1338 1339 final int nonStandardCode = 1, deprecated = 47; 1340 1341 String value = first(RSVP); 1342 if (value != null) { 1343 value = value.toLowerCase(); 1344 List<String> validValues = Arrays.asList("true", "false", "yes", "no"); 1345 if (!validValues.contains(value)) { 1346 warnings.add(new ValidationWarning(nonStandardCode, RSVP, value, validValues)); 1347 } 1348 } 1349 1350 value = first(CUTYPE); 1351 if (value != null && CalendarUserType.find(value) == null) { 1352 warnings.add(new ValidationWarning(nonStandardCode, CUTYPE, value, CalendarUserType.all())); 1353 } 1354 1355 value = first(ENCODING); 1356 if (value != null && Encoding.find(value) == null) { 1357 warnings.add(new ValidationWarning(nonStandardCode, ENCODING, value, Encoding.all())); 1358 } 1359 1360 value = first(FBTYPE); 1361 if (value != null && FreeBusyType.find(value) == null) { 1362 warnings.add(new ValidationWarning(nonStandardCode, FBTYPE, value, FreeBusyType.all())); 1363 } 1364 1365 value = first(PARTSTAT); 1366 if (value != null && ParticipationStatus.find(value) == null) { 1367 warnings.add(new ValidationWarning(nonStandardCode, PARTSTAT, value, ParticipationStatus.all())); 1368 } 1369 1370 value = first(RANGE); 1371 if (value != null) { 1372 Range range = Range.find(value); 1373 1374 if (range == null) { 1375 warnings.add(new ValidationWarning(nonStandardCode, RANGE, value, Range.all())); 1376 } 1377 1378 if (range == Range.THIS_AND_PRIOR && version == ICalVersion.V2_0) { 1379 warnings.add(new ValidationWarning(deprecated, RANGE, value)); 1380 } 1381 } 1382 1383 value = first(RELATED); 1384 if (value != null && Related.find(value) == null) { 1385 warnings.add(new ValidationWarning(nonStandardCode, RELATED, value, Related.all())); 1386 } 1387 1388 value = first(RELTYPE); 1389 if (value != null && RelationshipType.find(value) == null) { 1390 warnings.add(new ValidationWarning(nonStandardCode, RELTYPE, value, RelationshipType.all())); 1391 } 1392 1393 value = first(ROLE); 1394 if (value != null && Role.find(value) == null) { 1395 warnings.add(new ValidationWarning(nonStandardCode, ROLE, value, Role.all())); 1396 } 1397 1398 value = first(VALUE); 1399 if (value != null && ICalDataType.find(value) == null) { 1400 warnings.add(new ValidationWarning(nonStandardCode, VALUE, value, ICalDataType.all())); 1401 } 1402 1403 return warnings; 1404 } 1405 1406 @Override 1407 protected String sanitizeKey(String key) { 1408 return (key == null) ? null : key.toUpperCase(); 1409 } 1410 1411 @Override 1412 public int hashCode() { 1413 /* 1414 * Remember: Keys are case-insensitive, key order does not matter, and 1415 * value order does not matter 1416 */ 1417 final int prime = 31; 1418 int result = 1; 1419 1420 for (Map.Entry<String, List<String>> entry : this) { 1421 String key = entry.getKey(); 1422 List<String> value = entry.getValue(); 1423 1424 int valueHash = 1; 1425 for (String v : value) { 1426 valueHash += v.toLowerCase().hashCode(); 1427 } 1428 1429 int entryHash = 1; 1430 entryHash += prime * entryHash + ((key == null) ? 0 : key.toLowerCase().hashCode()); 1431 entryHash += prime * entryHash + valueHash; 1432 1433 result += entryHash; 1434 } 1435 1436 return result; 1437 } 1438 1439 /** 1440 * <p> 1441 * Determines whether the given object is logically equivalent to this list 1442 * of parameters. 1443 * </p> 1444 * <p> 1445 * Note that iCalendar parameter names are case-insensitive. Also, note that 1446 * the order in which they are defined does not matter. 1447 * </p> 1448 * @param obj the object to compare to 1449 * @return true if the objects are equal, false if not 1450 */ 1451 @Override 1452 public boolean equals(Object obj) { 1453 /* 1454 * Remember: Keys are case-insensitive, key order does not matter, and 1455 * value order does not matter 1456 */ 1457 if (this == obj) return true; 1458 if (obj == null) return false; 1459 if (getClass() != obj.getClass()) return false; 1460 1461 ICalParameters other = (ICalParameters) obj; 1462 if (size() != other.size()) return false; 1463 1464 for (Map.Entry<String, List<String>> entry : this) { 1465 String key = entry.getKey(); 1466 List<String> value = entry.getValue(); 1467 List<String> otherValue = other.get(key); 1468 1469 if (value.size() != otherValue.size()) { 1470 return false; 1471 } 1472 1473 List<String> valueLower = new ArrayList<String>(value.size()); 1474 for (String v : value) { 1475 valueLower.add(v.toLowerCase()); 1476 } 1477 Collections.sort(valueLower); 1478 1479 List<String> otherValueLower = new ArrayList<String>(otherValue.size()); 1480 for (String v : otherValue) { 1481 otherValueLower.add(v.toLowerCase()); 1482 } 1483 Collections.sort(otherValueLower); 1484 1485 if (!valueLower.equals(otherValueLower)) { 1486 return false; 1487 } 1488 } 1489 1490 return true; 1491 } 1492 1493 /** 1494 * <p> 1495 * A list that converts the raw string values of a parameter to the 1496 * appropriate {@link EnumParameterValue} object that some parameters use. 1497 * </p> 1498 * <p> 1499 * This list is backed by the {@link ICalParameters} object. Any changes 1500 * made to the list will affect the {@link ICalParameters} object and vice 1501 * versa. 1502 * </p> 1503 * @param <T> the enum parameter class 1504 */ 1505 public abstract class EnumParameterList<T extends EnumParameterValue> extends ICalParameterList<T> { 1506 public EnumParameterList(String parameterName) { 1507 super(parameterName); 1508 } 1509 1510 @Override 1511 protected String _asString(T value) { 1512 return value.getValue(); 1513 } 1514 } 1515 1516 /** 1517 * <p> 1518 * A list that converts the raw string values of a parameter to another kind 1519 * of value (for example, Integers). 1520 * </p> 1521 * <p> 1522 * This list is backed by the {@link ICalParameters} object. Any changes 1523 * made to the list will affect the {@link ICalParameters} object and vice 1524 * versa. 1525 * </p> 1526 * <p> 1527 * If a String value cannot be converted to the appropriate data type, an 1528 * {@link IllegalStateException} is thrown. 1529 * </p> 1530 */ 1531 public abstract class ICalParameterList<T> extends AbstractList<T> { 1532 protected final String parameterName; 1533 protected final List<String> parameterValues; 1534 1535 /** 1536 * @param parameterName the name of the parameter (case insensitive) 1537 */ 1538 public ICalParameterList(String parameterName) { 1539 this.parameterName = parameterName; 1540 parameterValues = ICalParameters.this.get(parameterName); 1541 } 1542 1543 @Override 1544 public void add(int index, T value) { 1545 String valueStr = _asString(value); 1546 parameterValues.add(index, valueStr); 1547 } 1548 1549 @Override 1550 public T remove(int index) { 1551 String removed = parameterValues.remove(index); 1552 return asObject(removed); 1553 } 1554 1555 @Override 1556 public T get(int index) { 1557 String value = parameterValues.get(index); 1558 return asObject(value); 1559 } 1560 1561 @Override 1562 public T set(int index, T value) { 1563 String valueStr = _asString(value); 1564 String replaced = parameterValues.set(index, valueStr); 1565 return asObject(replaced); 1566 } 1567 1568 @Override 1569 public int size() { 1570 return parameterValues.size(); 1571 } 1572 1573 private T asObject(String value) { 1574 try { 1575 return _asObject(value); 1576 } catch (Exception e) { 1577 throw new IllegalStateException(Messages.INSTANCE.getExceptionMessage(26, parameterName), e); 1578 } 1579 } 1580 1581 /** 1582 * Converts the object to a String value for storing in the 1583 * {@link ICalParameters} object. 1584 * @param value the value 1585 * @return the string value 1586 */ 1587 protected abstract String _asString(T value); 1588 1589 /** 1590 * Converts a String value to its object form. 1591 * @param value the string value 1592 * @return the object 1593 * @throws Exception if there is a problem parsing the string 1594 */ 1595 protected abstract T _asObject(String value) throws Exception; 1596 } 1597}