001/* 002 * The MIT License 003 * Copyright (c) 2012 Microsoft Corporation 004 * 005 * Permission is hereby granted, free of charge, to any person obtaining a copy 006 * of this software and associated documentation files (the "Software"), to deal 007 * in the Software without restriction, including without limitation the rights 008 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 009 * copies of the Software, and to permit persons to whom the Software is 010 * furnished to do so, subject to the following conditions: 011 * 012 * The above copyright notice and this permission notice shall be included in 013 * all copies or substantial portions of the Software. 014 * 015 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 016 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 017 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 018 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 019 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 020 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 021 * THE SOFTWARE. 022 */ 023 024package microsoft.exchange.webservices.data.property.complex.recurrence.pattern; 025 026import microsoft.exchange.webservices.data.attribute.EditorBrowsable; 027import microsoft.exchange.webservices.data.core.EwsServiceXmlReader; 028import microsoft.exchange.webservices.data.core.EwsServiceXmlWriter; 029import microsoft.exchange.webservices.data.core.EwsUtilities; 030import microsoft.exchange.webservices.data.core.ExchangeService; 031import microsoft.exchange.webservices.data.core.XmlElementNames; 032import microsoft.exchange.webservices.data.core.enumeration.property.time.DayOfTheWeek; 033import microsoft.exchange.webservices.data.core.enumeration.property.time.DayOfTheWeekIndex; 034import microsoft.exchange.webservices.data.core.enumeration.attribute.EditorBrowsableState; 035import microsoft.exchange.webservices.data.core.enumeration.misc.ExchangeVersion; 036import microsoft.exchange.webservices.data.core.enumeration.property.time.Month; 037import microsoft.exchange.webservices.data.core.enumeration.misc.XmlNamespace; 038import microsoft.exchange.webservices.data.core.exception.misc.ArgumentException; 039import microsoft.exchange.webservices.data.core.exception.misc.ArgumentOutOfRangeException; 040import microsoft.exchange.webservices.data.core.exception.service.local.ServiceValidationException; 041import microsoft.exchange.webservices.data.property.complex.ComplexProperty; 042import microsoft.exchange.webservices.data.property.complex.IComplexPropertyChangedDelegate; 043import microsoft.exchange.webservices.data.property.complex.recurrence.DayOfTheWeekCollection; 044import microsoft.exchange.webservices.data.property.complex.recurrence.range.EndDateRecurrenceRange; 045import microsoft.exchange.webservices.data.property.complex.recurrence.range.NoEndRecurrenceRange; 046import microsoft.exchange.webservices.data.property.complex.recurrence.range.NumberedRecurrenceRange; 047import microsoft.exchange.webservices.data.property.complex.recurrence.range.RecurrenceRange; 048 049import java.util.ArrayList; 050import java.util.Arrays; 051import java.util.Calendar; 052import java.util.Date; 053import java.util.Iterator; 054 055/** 056 * Represents a recurrence pattern, as used by Appointment and Task item. 057 */ 058public abstract class Recurrence extends ComplexProperty { 059 060 /** 061 * The start date. 062 */ 063 private Date startDate; 064 065 /** 066 * The number of occurrences. 067 */ 068 private Integer numberOfOccurrences; 069 070 /** 071 * The end date. 072 */ 073 private Date endDate; 074 075 /** 076 * Initializes a new instance. 077 */ 078 public Recurrence() { 079 super(); 080 } 081 082 /** 083 * Initializes a new instance. 084 * 085 * @param startDate the start date 086 */ 087 public Recurrence(Date startDate) { 088 this(); 089 this.startDate = startDate; 090 } 091 092 /** 093 * Gets the name of the XML element. 094 * 095 * @return the xml element name 096 */ 097 public abstract String getXmlElementName(); 098 099 /** 100 * Gets a value indicating whether this instance is regeneration pattern. 101 * 102 * @return true, if is regeneration pattern 103 */ 104 public boolean isRegenerationPattern() { 105 return false; 106 } 107 108 /** 109 * Write property to XML. 110 * 111 * @param writer the writer 112 * @throws Exception the exception 113 */ 114 public void internalWritePropertiesToXml(EwsServiceXmlWriter writer) throws Exception { 115 } 116 117 /** 118 * Writes elements to XML. 119 * 120 * @param writer the writer 121 * @throws Exception the exception 122 */ 123 @Override 124 public final void writeElementsToXml(EwsServiceXmlWriter writer) 125 throws Exception { 126 writer.writeStartElement(XmlNamespace.Types, this.getXmlElementName()); 127 this.internalWritePropertiesToXml(writer); 128 writer.writeEndElement(); 129 130 RecurrenceRange range = null; 131 132 if (!this.hasEnd()) { 133 range = new NoEndRecurrenceRange(this.getStartDate()); 134 } else if (this.getNumberOfOccurrences() != null) { 135 range = new NumberedRecurrenceRange(this.startDate, 136 this.numberOfOccurrences); 137 } else { 138 if (this.getEndDate() != null) { 139 range = new EndDateRecurrenceRange(this.getStartDate(), this 140 .getEndDate()); 141 } 142 } 143 if (range != null) { 144 range.writeToXml(writer, range.getXmlElementName()); 145 } 146 147 } 148 149 /** 150 * Gets a property value or throw if null. * 151 * 152 * @param <T> the generic type 153 * @param cls the cls 154 * @param value the value 155 * @param name the name 156 * @return Property value 157 * @throws ServiceValidationException the service validation exception 158 */ 159 public <T> T getFieldValueOrThrowIfNull(Class<T> cls, Object value, 160 String name) throws ServiceValidationException { 161 if (value != null) { 162 return (T) value; 163 } else { 164 throw new ServiceValidationException(String.format( 165 "The recurrence pattern's %s property must be specified.", 166 name)); 167 } 168 } 169 170 /** 171 * Gets the date and time when the recurrence start. 172 * 173 * @return Date 174 * @throws ServiceValidationException the service validation exception 175 */ 176 public Date getStartDate() throws ServiceValidationException { 177 return this.getFieldValueOrThrowIfNull(Date.class, this.startDate, 178 "StartDate"); 179 180 } 181 182 /** 183 * sets the date and time when the recurrence start. 184 * 185 * @param value the new start date 186 */ 187 public void setStartDate(Date value) { 188 this.startDate = value; 189 } 190 191 /** 192 * Gets a value indicating whether the pattern has a fixed number of 193 * occurrences or an end date. 194 * 195 * @return boolean 196 */ 197 public boolean hasEnd() { 198 199 return ((this.numberOfOccurrences != null) || (this.endDate != null)); 200 } 201 202 /** 203 * Sets up this recurrence so that it never ends. Calling NeverEnds is 204 * equivalent to setting both NumberOfOccurrences and EndDate to null. 205 */ 206 public void neverEnds() { 207 this.numberOfOccurrences = null; 208 this.endDate = null; 209 this.changed(); 210 } 211 212 /** 213 * Validates this instance. 214 * 215 * @throws Exception 216 */ 217 @Override 218 public void internalValidate() throws Exception { 219 super.internalValidate(); 220 221 if (this.startDate == null) { 222 throw new ServiceValidationException("The recurrence pattern's StartDate property must be specified."); 223 } 224 } 225 226 /** 227 * Gets the number of occurrences after which the recurrence ends. 228 * Setting NumberOfOccurrences resets EndDate. 229 * 230 * @return the number of occurrences 231 */ 232 public Integer getNumberOfOccurrences() { 233 return this.numberOfOccurrences; 234 235 } 236 237 /** 238 * Gets the number of occurrences after which the recurrence ends. 239 * Setting NumberOfOccurrences resets EndDate. 240 * 241 * @param value the new number of occurrences 242 * @throws ArgumentException the argument exception 243 */ 244 public void setNumberOfOccurrences(Integer value) throws ArgumentException { 245 if (value < 1) { 246 throw new ArgumentException("NumberOfOccurrences must be greater than 0."); 247 } 248 249 if (this.canSetFieldValue(this.numberOfOccurrences, value)) { 250 numberOfOccurrences = value; 251 this.changed(); 252 } 253 254 this.endDate = null; 255 256 } 257 258 /** 259 * Gets the date after which the recurrence ends. Setting EndDate resets 260 * NumberOfOccurrences. 261 * 262 * @return the end date 263 */ 264 public Date getEndDate() { 265 266 return this.endDate; 267 } 268 269 /** 270 * sets the date after which the recurrence ends. Setting EndDate resets 271 * NumberOfOccurrences. 272 * 273 * @param value the new end date 274 */ 275 public void setEndDate(Date value) { 276 277 if (this.canSetFieldValue(this.endDate, value)) { 278 this.endDate = value; 279 this.changed(); 280 } 281 282 this.numberOfOccurrences = null; 283 284 } 285 286 /** 287 * Represents a recurrence pattern where each occurrence happens a specific 288 * number of days after the previous one. 289 */ 290 public final static class DailyPattern extends IntervalPattern { 291 292 /** 293 * Gets the name of the XML element. 294 * 295 * @return the xml element name 296 */ 297 @Override 298 public String getXmlElementName() { 299 return XmlElementNames.DailyRecurrence; 300 } 301 302 /** 303 * Initializes a new instance of the DailyPattern class. 304 */ 305 306 public DailyPattern() { 307 super(); 308 } 309 310 /** 311 * Initializes a new instance of the DailyPattern class. 312 * 313 * @param startDate The date and time when the recurrence starts. 314 * @param interval The number of days between each occurrence. 315 * @throws ArgumentOutOfRangeException the argument out of range exception 316 */ 317 public DailyPattern(Date startDate, int interval) 318 throws ArgumentOutOfRangeException { 319 super(startDate, interval); 320 } 321 322 } 323 324 325 /** 326 * Represents a regeneration pattern, as used with recurring tasks, where 327 * each occurrence happens a specified number of days after the previous one 328 * is completed. 329 */ 330 331 public final static class DailyRegenerationPattern extends IntervalPattern { 332 333 /** 334 * Initializes a new instance of the DailyRegenerationPattern class. 335 */ 336 public DailyRegenerationPattern() { 337 super(); 338 } 339 340 /** 341 * Initializes a new instance of the DailyRegenerationPattern class. 342 * 343 * @param startDate The date and time when the recurrence starts. 344 * @param interval The number of days between each occurrence. 345 * @throws ArgumentOutOfRangeException the argument out of range exception 346 */ 347 public DailyRegenerationPattern(Date startDate, int interval) 348 throws ArgumentOutOfRangeException { 349 super(startDate, interval); 350 351 } 352 353 /** 354 * Gets the name of the XML element. 355 * 356 * @return the xml element name 357 */ 358 public String getXmlElementName() { 359 return XmlElementNames.DailyRegeneration; 360 } 361 362 /** 363 * Gets a value indicating whether this instance is a regeneration 364 * pattern. 365 * 366 * @return true, if is regeneration pattern 367 */ 368 public boolean isRegenerationPattern() { 369 return true; 370 } 371 372 } 373 374 375 /** 376 * Represents a recurrence pattern where each occurrence happens at a 377 * specific interval after the previous one. 378 * [EditorBrowsable(EditorBrowsableState.Never)] 379 */ 380 @EditorBrowsable(state = EditorBrowsableState.Never) 381 public abstract static class IntervalPattern extends Recurrence { 382 383 /** 384 * The interval. 385 */ 386 private int interval = 1; 387 388 /** 389 * Initializes a new instance of the IntervalPattern class. 390 */ 391 public IntervalPattern() { 392 super(); 393 } 394 395 /** 396 * Initializes a new instance of the IntervalPattern class. 397 * 398 * @param startDate The date and time when the recurrence starts. 399 * @param interval The number of days between each occurrence. 400 * @throws ArgumentOutOfRangeException the argument out of range exception 401 */ 402 public IntervalPattern(Date startDate, int interval) 403 throws ArgumentOutOfRangeException { 404 405 super(startDate); 406 if (interval < 1) { 407 throw new ArgumentOutOfRangeException("interval", "The interval must be greater than or equal to 1."); 408 } 409 410 this.setInterval(interval); 411 } 412 413 /** 414 * Write property to XML. 415 * 416 * @param writer the writer 417 * @throws Exception the exception 418 */ 419 @Override 420 public void internalWritePropertiesToXml(EwsServiceXmlWriter writer) throws Exception { 421 super.internalWritePropertiesToXml(writer); 422 423 writer.writeElementValue(XmlNamespace.Types, 424 XmlElementNames.Interval, this.getInterval()); 425 } 426 427 /** 428 * Tries to read element from XML. 429 * 430 * @param reader the reader 431 * @return true, if successful 432 * @throws Exception the exception 433 */ 434 @Override 435 public boolean tryReadElementFromXml(EwsServiceXmlReader reader) 436 throws Exception { 437 if (super.tryReadElementFromXml(reader)) { 438 return true; 439 } else { 440 441 if (reader.getLocalName().equals(XmlElementNames.Interval)) { 442 this.interval = reader.readElementValue(Integer.class); 443 return true; 444 } else { 445 return false; 446 } 447 } 448 } 449 450 /** 451 * Gets the interval between occurrences. 452 * 453 * @return the interval 454 */ 455 public int getInterval() { 456 return this.interval; 457 } 458 459 /** 460 * Sets the interval. 461 * 462 * @param value the new interval 463 * @throws ArgumentOutOfRangeException the argument out of range exception 464 */ 465 public void setInterval(int value) throws ArgumentOutOfRangeException { 466 467 if (value < 1) { 468 throw new ArgumentOutOfRangeException("value", "The interval must be greater than or equal to 1."); 469 } 470 471 if (this.canSetFieldValue(this.interval, value)) { 472 this.interval = value; 473 this.changed(); 474 } 475 476 } 477 478 } 479 480 481 /** 482 * Represents a recurrence pattern where each occurrence happens on a 483 * specific day a specific number of months after the previous one. 484 */ 485 486 public final static class MonthlyPattern extends IntervalPattern { 487 488 /** 489 * The day of month. 490 */ 491 private Integer dayOfMonth; 492 493 /** 494 * Initializes a new instance of the MonthlyPattern class. 495 */ 496 public MonthlyPattern() { 497 super(); 498 499 } 500 501 /** 502 * Initializes a new instance of the MonthlyPattern class. 503 * 504 * @param startDate the start date 505 * @param interval the interval 506 * @param dayOfMonth the day of month 507 * @throws ArgumentOutOfRangeException the argument out of range exception 508 */ 509 public MonthlyPattern(Date startDate, int interval, int dayOfMonth) 510 throws ArgumentOutOfRangeException { 511 super(startDate, interval); 512 513 this.setDayOfMonth(dayOfMonth); 514 } 515 516 // / Gets the name of the XML element. 517 518 /* 519 * (non-Javadoc) 520 * 521 * @see microsoft.exchange.webservices.Recurrence#getXmlElementName() 522 */ 523 @Override 524 public String getXmlElementName() { 525 return XmlElementNames.AbsoluteMonthlyRecurrence; 526 } 527 528 /** 529 * Write property to XML. 530 * 531 * @param writer the writer 532 * @throws Exception the exception 533 */ 534 @Override 535 public void internalWritePropertiesToXml(EwsServiceXmlWriter writer) 536 throws Exception { 537 super.internalWritePropertiesToXml(writer); 538 539 writer.writeElementValue(XmlNamespace.Types, 540 XmlElementNames.DayOfMonth, this.getDayOfMonth()); 541 } 542 543 /** 544 * Tries to read element from XML. 545 * 546 * @param reader the reader 547 * @return True if appropriate element was read. 548 * @throws Exception the exception 549 */ 550 @Override 551 public boolean tryReadElementFromXml(EwsServiceXmlReader reader) 552 throws Exception { 553 if (super.tryReadElementFromXml(reader)) { 554 return true; 555 } else { 556 if (reader.getLocalName().equals(XmlElementNames.DayOfMonth)) { 557 this.dayOfMonth = reader.readElementValue(Integer.class); 558 return true; 559 } else { 560 return false; 561 } 562 } 563 } 564 565 /** 566 * Validates this instance. 567 * 568 * @throws Exception 569 */ 570 @Override 571 public void internalValidate() throws Exception { 572 super.internalValidate(); 573 574 if (this.dayOfMonth == null) { 575 throw new ServiceValidationException("DayOfMonth must be between 1 and 31."); 576 } 577 } 578 579 /** 580 * Gets the day of month. 581 * 582 * @return the day of month 583 * @throws ServiceValidationException the service validation exception 584 */ 585 public int getDayOfMonth() throws ServiceValidationException { 586 return this.getFieldValueOrThrowIfNull(Integer.class, this.dayOfMonth, 587 "DayOfMonth"); 588 589 } 590 591 /** 592 * Sets the day of month. 593 * 594 * @param value the new day of month 595 * @throws ArgumentOutOfRangeException the argument out of range exception 596 */ 597 public void setDayOfMonth(int value) 598 throws ArgumentOutOfRangeException { 599 if (value < 1 || value > 31) { 600 throw new ArgumentOutOfRangeException("DayOfMonth", "DayOfMonth must be between 1 and 31."); 601 } 602 603 if (this.canSetFieldValue(this.dayOfMonth, value)) { 604 this.dayOfMonth = value; 605 this.changed(); 606 } 607 } 608 } 609 610 611 /** 612 * Represents a regeneration pattern, as used with recurring tasks, where 613 * each occurrence happens a specified number of months after the previous 614 * one is completed. 615 */ 616 public final static class MonthlyRegenerationPattern extends 617 IntervalPattern { 618 619 /** 620 * Instantiates a new monthly regeneration pattern. 621 */ 622 public MonthlyRegenerationPattern() { 623 super(); 624 625 } 626 627 /** 628 * Instantiates a new monthly regeneration pattern. 629 * 630 * @param startDate the start date 631 * @param interval the interval 632 * @throws ArgumentOutOfRangeException the argument out of range exception 633 */ 634 public MonthlyRegenerationPattern(Date startDate, int interval) 635 throws ArgumentOutOfRangeException { 636 super(startDate, interval); 637 638 } 639 640 /** 641 * Gets the name of the XML element. <value>The name of the XML 642 * element.</value> 643 * 644 * @return the xml element name 645 */ 646 @Override 647 public String getXmlElementName() { 648 return XmlElementNames.MonthlyRegeneration; 649 } 650 651 /** 652 * Gets a value indicating whether this instance is regeneration 653 * pattern. <value> <c>true</c> if this instance is regeneration 654 * pattern; otherwise, <c>false</c>. </value> 655 * 656 * @return true, if is regeneration pattern 657 */ 658 public boolean isRegenerationPattern() { 659 return true; 660 } 661 } 662 663 664 /** 665 * Represents a recurrence pattern where each occurrence happens on a 666 * relative day a specific number of months after the previous one. 667 */ 668 public final static class RelativeMonthlyPattern extends IntervalPattern { 669 670 /** 671 * The day of the week. 672 */ 673 private DayOfTheWeek dayOfTheWeek; 674 675 /** 676 * The day of the week index. 677 */ 678 private DayOfTheWeekIndex dayOfTheWeekIndex; 679 680 // / Initializes a new instance of the <see 681 // cref="RelativeMonthlyPattern"/> class. 682 683 /** 684 * Instantiates a new relative monthly pattern. 685 */ 686 public RelativeMonthlyPattern() { 687 super(); 688 } 689 690 /** 691 * Instantiates a new relative monthly pattern. 692 * 693 * @param startDate the start date 694 * @param interval the interval 695 * @param dayOfTheWeek the day of the week 696 * @param dayOfTheWeekIndex the day of the week index 697 * @throws ArgumentOutOfRangeException the argument out of range exception 698 */ 699 public RelativeMonthlyPattern(Date startDate, int interval, 700 DayOfTheWeek dayOfTheWeek, DayOfTheWeekIndex dayOfTheWeekIndex) 701 throws ArgumentOutOfRangeException { 702 super(startDate, interval); 703 704 this.setDayOfTheWeek(dayOfTheWeek); 705 this.setDayOfTheWeekIndex(dayOfTheWeekIndex); 706 } 707 708 /** 709 * Gets the name of the XML element. 710 * 711 * @return the xml element name 712 */ 713 @Override 714 public String getXmlElementName() { 715 return XmlElementNames.RelativeMonthlyRecurrence; 716 } 717 718 /** 719 * Write property to XML. 720 * 721 * @param writer the writer 722 * @throws Exception the exception 723 */ 724 @Override 725 public void internalWritePropertiesToXml(EwsServiceXmlWriter writer) 726 throws Exception { 727 super.internalWritePropertiesToXml(writer); 728 729 writer.writeElementValue(XmlNamespace.Types, 730 XmlElementNames.DaysOfWeek, this.getDayOfTheWeek()); 731 732 writer 733 .writeElementValue(XmlNamespace.Types, 734 XmlElementNames.DayOfWeekIndex, this 735 .getDayOfTheWeekIndex()); 736 } 737 738 /** 739 * Tries to read element from XML. 740 * 741 * @param reader the reader 742 * @return True if appropriate element was read. 743 * @throws Exception the exception 744 */ 745 @Override 746 public boolean tryReadElementFromXml(EwsServiceXmlReader reader) 747 throws Exception { 748 if (super.tryReadElementFromXml(reader)) { 749 return true; 750 } else { 751 if (reader.getLocalName().equals(XmlElementNames.DaysOfWeek)) { 752 753 this.dayOfTheWeek = reader 754 .readElementValue(DayOfTheWeek.class); 755 return true; 756 } else if (reader.getLocalName().equals( 757 XmlElementNames.DayOfWeekIndex)) { 758 759 this.dayOfTheWeekIndex = reader 760 .readElementValue(DayOfTheWeekIndex.class); 761 return true; 762 } else { 763 764 return false; 765 } 766 } 767 } 768 769 /** 770 * Validates this instance. 771 * 772 * @throws Exception 773 */ 774 @Override 775 public void internalValidate() throws Exception { 776 super.internalValidate(); 777 778 if (this.dayOfTheWeek == null) { 779 throw new ServiceValidationException( 780 "The recurrence pattern's property DayOfTheWeek must be specified."); 781 } 782 783 if (this.dayOfTheWeekIndex == null) { 784 throw new ServiceValidationException( 785 "The recurrence pattern's DayOfWeekIndex property must be specified."); 786 } 787 } 788 789 /** 790 * Day of the week index. 791 * 792 * @return the day of the week index 793 * @throws ServiceValidationException the service validation exception 794 */ 795 public DayOfTheWeekIndex getDayOfTheWeekIndex() 796 throws ServiceValidationException { 797 return this.getFieldValueOrThrowIfNull(DayOfTheWeekIndex.class, 798 this.dayOfTheWeekIndex, "DayOfTheWeekIndex"); 799 } 800 801 /** 802 * Day of the week index. 803 * 804 * @param value the value 805 */ 806 public void setDayOfTheWeekIndex(DayOfTheWeekIndex value) { 807 if (this.canSetFieldValue(this.dayOfTheWeekIndex, value)) { 808 this.dayOfTheWeekIndex = value; 809 this.changed(); 810 } 811 812 } 813 814 /** 815 * Gets the day of the week. 816 * 817 * @return the day of the week 818 * @throws ServiceValidationException the service validation exception 819 */ 820 public DayOfTheWeek getDayOfTheWeek() 821 throws ServiceValidationException { 822 return this.getFieldValueOrThrowIfNull(DayOfTheWeek.class, 823 this.dayOfTheWeek, "DayOfTheWeek"); 824 825 } 826 827 /** 828 * Sets the day of the week. 829 * 830 * @param value the new day of the week 831 */ 832 public void setDayOfTheWeek(DayOfTheWeek value) { 833 834 if (this.canSetFieldValue(this.dayOfTheWeek, value)) { 835 this.dayOfTheWeek = value; 836 this.changed(); 837 } 838 } 839 } 840 841 842 /** 843 * The Class RelativeYearlyPattern. 844 */ 845 public final static class RelativeYearlyPattern extends Recurrence { 846 847 /** 848 * The day of the week. 849 */ 850 private DayOfTheWeek dayOfTheWeek; 851 852 /** 853 * The day of the week index. 854 */ 855 private DayOfTheWeekIndex dayOfTheWeekIndex; 856 857 /** 858 * The month. 859 */ 860 private Month month; 861 862 /** 863 * Gets the name of the XML element. <value>The name of the XML 864 * element.</value> 865 * 866 * @return the xml element name 867 */ 868 @Override 869 public String getXmlElementName() { 870 return XmlElementNames.RelativeYearlyRecurrence; 871 } 872 873 /** 874 * Write property to XML. 875 * 876 * @param writer the writer 877 * @throws Exception the exception 878 */ 879 @Override 880 public void internalWritePropertiesToXml(EwsServiceXmlWriter writer) 881 throws Exception { 882 super.internalWritePropertiesToXml(writer); 883 884 writer.writeElementValue(XmlNamespace.Types, 885 XmlElementNames.DaysOfWeek, this.dayOfTheWeek); 886 887 writer.writeElementValue(XmlNamespace.Types, 888 XmlElementNames.DayOfWeekIndex, this.dayOfTheWeekIndex); 889 890 writer.writeElementValue(XmlNamespace.Types, XmlElementNames.Month, 891 this.month); 892 } 893 894 /** 895 * Tries to read element from XML. 896 * 897 * @param reader the reader 898 * @return True if element was read. 899 * @throws Exception the exception 900 */ 901 @Override 902 public boolean tryReadElementFromXml(EwsServiceXmlReader reader) 903 throws Exception { 904 if (super.tryReadElementFromXml(reader)) { 905 return true; 906 } else { 907 if (reader.getLocalName().equals(XmlElementNames.DaysOfWeek)) { 908 909 this.dayOfTheWeek = reader 910 .readElementValue(DayOfTheWeek.class); 911 return true; 912 } else if (reader.getLocalName().equals( 913 XmlElementNames.DayOfWeekIndex)) { 914 915 this.dayOfTheWeekIndex = reader 916 .readElementValue(DayOfTheWeekIndex.class); 917 return true; 918 } else if (reader.getLocalName().equals(XmlElementNames.Month)) { 919 920 this.month = reader.readElementValue(Month.class); 921 return true; 922 } else { 923 924 return false; 925 } 926 } 927 } 928 929 /** 930 * Instantiates a new relative yearly pattern. 931 */ 932 public RelativeYearlyPattern() { 933 super(); 934 935 } 936 937 /** 938 * Instantiates a new relative yearly pattern. 939 * 940 * @param startDate the start date 941 * @param month the month 942 * @param dayOfTheWeek the day of the week 943 * @param dayOfTheWeekIndex the day of the week index 944 */ 945 public RelativeYearlyPattern(Date startDate, Month month, 946 DayOfTheWeek dayOfTheWeek, 947 DayOfTheWeekIndex dayOfTheWeekIndex) { 948 super(startDate); 949 950 this.month = month; 951 this.dayOfTheWeek = dayOfTheWeek; 952 this.dayOfTheWeekIndex = dayOfTheWeekIndex; 953 } 954 955 /** 956 * Validates this instance. 957 * 958 * @throws Exception 959 */ 960 @Override 961 public void internalValidate() throws Exception { 962 super.internalValidate(); 963 964 if (this.dayOfTheWeekIndex == null) { 965 throw new ServiceValidationException( 966 "The recurrence pattern's DayOfWeekIndex property must be specified."); 967 } 968 969 if (this.dayOfTheWeek == null) { 970 throw new ServiceValidationException( 971 "The recurrence pattern's property DayOfTheWeek must be specified."); 972 } 973 974 if (this.month == null) { 975 throw new ServiceValidationException("The recurrence pattern's Month property must be specified."); 976 } 977 } 978 979 /** 980 * Gets the relative position of the day specified in DayOfTheWeek 981 * within the month. 982 * 983 * @return the day of the week index 984 * @throws ServiceValidationException the service validation exception 985 */ 986 public DayOfTheWeekIndex getDayOfTheWeekIndex() 987 throws ServiceValidationException { 988 989 return this.getFieldValueOrThrowIfNull(DayOfTheWeekIndex.class, 990 this.dayOfTheWeekIndex, "DayOfTheWeekIndex"); 991 } 992 993 /** 994 * Sets the relative position of the day specified in DayOfTheWeek 995 * within the month. 996 * 997 * @param value the new day of the week index 998 */ 999 public void setDayOfTheWeekIndex(DayOfTheWeekIndex value) { 1000 1001 if (this.canSetFieldValue(this.dayOfTheWeekIndex, value)) { 1002 this.dayOfTheWeekIndex = value; 1003 this.changed(); 1004 } 1005 } 1006 1007 /** 1008 * Gets the day of the week. 1009 * 1010 * @return the day of the week 1011 * @throws ServiceValidationException the service validation exception 1012 */ 1013 public DayOfTheWeek getDayOfTheWeek() 1014 throws ServiceValidationException { 1015 1016 return this.getFieldValueOrThrowIfNull(DayOfTheWeek.class, 1017 this.dayOfTheWeek, "DayOfTheWeek"); 1018 } 1019 1020 /** 1021 * Sets the day of the week. 1022 * 1023 * @param value the new day of the week 1024 */ 1025 public void setDayOfTheWeek(DayOfTheWeek value) { 1026 1027 if (this.canSetFieldValue(this.dayOfTheWeek, value)) { 1028 this.dayOfTheWeek = value; 1029 this.changed(); 1030 } 1031 } 1032 1033 /** 1034 * Gets the month. 1035 * 1036 * @return the month 1037 * @throws ServiceValidationException the service validation exception 1038 */ 1039 public Month getMonth() throws ServiceValidationException { 1040 1041 return this.getFieldValueOrThrowIfNull(Month.class, this.month, 1042 "Month"); 1043 1044 } 1045 1046 /** 1047 * Sets the month. 1048 * 1049 * @param value the new month 1050 */ 1051 public void setMonth(Month value) { 1052 1053 if (this.canSetFieldValue(this.month, value)) { 1054 this.month = value; 1055 this.changed(); 1056 } 1057 } 1058 } 1059 1060 1061 /** 1062 * Represents a recurrence pattern where each occurrence happens on specific 1063 * days a specific number of weeks after the previous one. 1064 */ 1065 public final static class WeeklyPattern extends IntervalPattern implements IComplexPropertyChangedDelegate { 1066 1067 /** 1068 * The days of the week. 1069 */ 1070 private DayOfTheWeekCollection daysOfTheWeek = 1071 new DayOfTheWeekCollection(); 1072 1073 private Calendar firstDayOfWeek; 1074 1075 /** 1076 * Initializes a new instance of the WeeklyPattern class. specific days 1077 * a specific number of weeks after the previous one. 1078 */ 1079 public WeeklyPattern() { 1080 super(); 1081 1082 this.daysOfTheWeek.addOnChangeEvent(this); 1083 } 1084 1085 /** 1086 * Initializes a new instance of the WeeklyPattern class. 1087 * 1088 * @param startDate the start date 1089 * @param interval the interval 1090 * @param daysOfTheWeek the days of the week 1091 * @throws ArgumentOutOfRangeException the argument out of range exception 1092 */ 1093 public WeeklyPattern(Date startDate, int interval, 1094 DayOfTheWeek... daysOfTheWeek) 1095 throws ArgumentOutOfRangeException { 1096 super(startDate, interval); 1097 1098 ArrayList<DayOfTheWeek> toProcess = new ArrayList<DayOfTheWeek>( 1099 Arrays.asList(daysOfTheWeek)); 1100 Iterator<DayOfTheWeek> idaysOfTheWeek = toProcess.iterator(); 1101 this.daysOfTheWeek.addRange(idaysOfTheWeek); 1102 } 1103 1104 /** 1105 * Change event handler. 1106 * 1107 * @param complexProperty the complex property 1108 */ 1109 private void daysOfTheWeekChanged(ComplexProperty complexProperty) { 1110 this.changed(); 1111 } 1112 1113 /** 1114 * Gets the name of the XML element. <value>The name of the XML 1115 * element.</value> 1116 * 1117 * @return the xml element name 1118 */ 1119 @Override 1120 public String getXmlElementName() { 1121 return XmlElementNames.WeeklyRecurrence; 1122 } 1123 1124 /** 1125 * Write property to XML. 1126 * 1127 * @param writer the writer 1128 * @throws Exception the exception 1129 */ 1130 @Override 1131 public void internalWritePropertiesToXml(EwsServiceXmlWriter writer) 1132 throws Exception { 1133 super.internalWritePropertiesToXml(writer); 1134 1135 this.getDaysOfTheWeek().writeToXml(writer, 1136 XmlElementNames.DaysOfWeek); 1137 if (this.firstDayOfWeek != null) { 1138 1139 EwsUtilities 1140 .validatePropertyVersion((ExchangeService) writer.getService(), ExchangeVersion.Exchange2010_SP1, 1141 "FirstDayOfWeek"); 1142 1143 writer.writeElementValue( 1144 XmlNamespace.Types, 1145 XmlElementNames.FirstDayOfWeek, 1146 this.firstDayOfWeek); 1147 } 1148 1149 } 1150 1151 /** 1152 * Tries to read element from XML. 1153 * 1154 * @param reader the reader 1155 * @return True if appropriate element was read. 1156 * @throws Exception the exception 1157 */ 1158 @Override 1159 public boolean tryReadElementFromXml(EwsServiceXmlReader reader) 1160 throws Exception { 1161 if (super.tryReadElementFromXml(reader)) { 1162 return true; 1163 } else { 1164 if (reader.getLocalName().equals(XmlElementNames.DaysOfWeek)) { 1165 1166 this.getDaysOfTheWeek().loadFromXml(reader, 1167 reader.getLocalName()); 1168 return true; 1169 } else if (reader.getLocalName().equals(XmlElementNames.FirstDayOfWeek)) { 1170 this.firstDayOfWeek = reader. 1171 readElementValue(Calendar.class, 1172 XmlNamespace.Types, 1173 XmlElementNames.FirstDayOfWeek); 1174 return true; 1175 } else { 1176 1177 return false; 1178 } 1179 } 1180 } 1181 1182 /** 1183 * Validates this instance. 1184 * 1185 * @throws Exception 1186 */ 1187 @Override 1188 public void internalValidate() throws Exception { 1189 super.internalValidate(); 1190 1191 if (this.getDaysOfTheWeek().getCount() == 0) { 1192 throw new ServiceValidationException( 1193 "The recurrence pattern's property DaysOfTheWeek must contain at least one day of the week."); 1194 } 1195 } 1196 1197 /** 1198 * Gets the list of the days of the week when occurrences happen. 1199 * 1200 * @return the days of the week 1201 */ 1202 public DayOfTheWeekCollection getDaysOfTheWeek() { 1203 return this.daysOfTheWeek; 1204 } 1205 1206 public Calendar getFirstDayOfWeek() throws ServiceValidationException { 1207 return this.getFieldValueOrThrowIfNull(Calendar.class, 1208 this.firstDayOfWeek, "FirstDayOfWeek"); 1209 } 1210 1211 public void setFirstDayOfWeek(Calendar value) { 1212 if (this.canSetFieldValue(this.firstDayOfWeek, value)) { 1213 this.firstDayOfWeek = value; 1214 this.changed(); 1215 } 1216 } 1217 1218 /* 1219 * (non-Javadoc) 1220 * 1221 * @see 1222 * microsoft.exchange.webservices. 1223 * ComplexPropertyChangedDelegateInterface# 1224 * complexPropertyChanged(microsoft.exchange.webservices.ComplexProperty 1225 * ) 1226 */ 1227 @Override 1228 public void complexPropertyChanged(ComplexProperty complexProperty) { 1229 this.daysOfTheWeekChanged(complexProperty); 1230 } 1231 1232 } 1233 1234 1235 /** 1236 * Represents a regeneration pattern, as used with recurring tasks, where 1237 * each occurrence happens a specified number of weeks after the previous 1238 * one is completed. 1239 */ 1240 public final static class WeeklyRegenerationPattern extends 1241 IntervalPattern { 1242 1243 /** 1244 * Initializes a new instance of the WeeklyRegenerationPattern class. 1245 */ 1246 public WeeklyRegenerationPattern() { 1247 1248 super(); 1249 } 1250 1251 /** 1252 * Initializes a new instance of the WeeklyRegenerationPattern class. 1253 * 1254 * @param startDate the start date 1255 * @param interval the interval 1256 * @throws ArgumentOutOfRangeException the argument out of range exception 1257 */ 1258 public WeeklyRegenerationPattern(Date startDate, int interval) 1259 throws ArgumentOutOfRangeException { 1260 super(startDate, interval); 1261 1262 } 1263 1264 /** 1265 * Gets the name of the XML element. <value>The name of the XML 1266 * element.</value> 1267 * 1268 * @return the xml element name 1269 */ 1270 @Override 1271 public String getXmlElementName() { 1272 return XmlElementNames.WeeklyRegeneration; 1273 } 1274 1275 /** 1276 * Gets a value indicating whether this instance is regeneration 1277 * pattern. <value> <c>true</c> if this instance is regeneration 1278 * pattern; otherwise, <c>false</c>. </value> 1279 * 1280 * @return true, if is regeneration pattern 1281 */ 1282 public boolean isRegenerationPattern() { 1283 return true; 1284 } 1285 } 1286 1287 1288 /** 1289 * Represents a recurrence pattern where each occurrence happens on a 1290 * specific day every year. 1291 */ 1292 public final static class YearlyPattern extends Recurrence { 1293 1294 /** 1295 * The month. 1296 */ 1297 private Month month; 1298 1299 /** 1300 * The day of month. 1301 */ 1302 private Integer dayOfMonth; 1303 1304 /** 1305 * Initializes a new instance of the YearlyPattern class. 1306 */ 1307 public YearlyPattern() { 1308 super(); 1309 1310 } 1311 1312 /** 1313 * Initializes a new instance of the YearlyPattern class. 1314 * 1315 * @param startDate the start date 1316 * @param month the month 1317 * @param dayOfMonth the day of month 1318 */ 1319 public YearlyPattern(Date startDate, Month month, int dayOfMonth) { 1320 super(startDate); 1321 1322 this.month = month; 1323 this.dayOfMonth = dayOfMonth; 1324 } 1325 1326 /** 1327 * Gets the name of the XML element. <value>The name of the XML 1328 * element.</value> 1329 * 1330 * @return the xml element name 1331 */ 1332 @Override 1333 public String getXmlElementName() { 1334 return XmlElementNames.AbsoluteYearlyRecurrence; 1335 } 1336 1337 /** 1338 * Write property to XML. 1339 * 1340 * @param writer the writer 1341 * @throws Exception the exception 1342 */ 1343 @Override 1344 public void internalWritePropertiesToXml(EwsServiceXmlWriter writer) 1345 throws Exception { 1346 super.internalWritePropertiesToXml(writer); 1347 1348 writer.writeElementValue(XmlNamespace.Types, 1349 XmlElementNames.DayOfMonth, this.getDayOfMonth()); 1350 1351 writer.writeElementValue(XmlNamespace.Types, XmlElementNames.Month, 1352 this.getMonth()); 1353 } 1354 1355 /** 1356 * Tries to read element from XML. 1357 * 1358 * @param reader the reader 1359 * @return True if element was read 1360 * @throws Exception the exception 1361 */ 1362 @Override 1363 public boolean tryReadElementFromXml(EwsServiceXmlReader reader) 1364 throws Exception { 1365 if (super.tryReadElementFromXml(reader)) { 1366 return true; 1367 } else { 1368 if (reader.getLocalName().equals(XmlElementNames.DayOfMonth)) { 1369 1370 this.dayOfMonth = reader.readElementValue(Integer.class); 1371 return true; 1372 } else if (reader.getLocalName().equals(XmlElementNames.Month)) { 1373 1374 this.month = reader.readElementValue(Month.class); 1375 return true; 1376 } else { 1377 1378 return false; 1379 } 1380 } 1381 } 1382 1383 /** 1384 * Validates this instance. 1385 * 1386 * @throws Exception 1387 */ 1388 @Override 1389 public void internalValidate() throws Exception { 1390 super.internalValidate(); 1391 1392 if (this.month == null) { 1393 throw new ServiceValidationException("The recurrence pattern's Month property must be specified."); 1394 } 1395 1396 if (this.dayOfMonth == null) { 1397 throw new ServiceValidationException( 1398 "The recurrence pattern's DayOfMonth property must be specified."); 1399 } 1400 } 1401 1402 /** 1403 * Gets the month of the year when each occurrence happens. 1404 * 1405 * @return the month 1406 * @throws ServiceValidationException the service validation exception 1407 */ 1408 public Month getMonth() throws ServiceValidationException { 1409 return this.getFieldValueOrThrowIfNull(Month.class, this.month, 1410 "Month"); 1411 } 1412 1413 /** 1414 * Sets the month. 1415 * 1416 * @param value the new month 1417 */ 1418 public void setMonth(Month value) { 1419 1420 if (this.canSetFieldValue(this.month, value)) { 1421 this.month = value; 1422 this.changed(); 1423 } 1424 } 1425 1426 /** 1427 * Gets the day of the month when each occurrence happens. DayOfMonth 1428 * must be between 1 and 31. 1429 * 1430 * @return the day of month 1431 * @throws ServiceValidationException the service validation exception 1432 */ 1433 public int getDayOfMonth() throws ServiceValidationException { 1434 1435 return this.getFieldValueOrThrowIfNull(Integer.class, this.dayOfMonth, 1436 "DayOfMonth"); 1437 1438 } 1439 1440 /** 1441 * Sets the day of the month when each occurrence happens. DayOfMonth 1442 * must be between 1 and 31. 1443 * 1444 * @param value the new day of month 1445 * @throws ArgumentOutOfRangeException the argument out of range exception 1446 */ 1447 public void setDayOfMonth(int value) 1448 throws ArgumentOutOfRangeException { 1449 1450 if (value < 1 || value > 31) { 1451 throw new ArgumentOutOfRangeException("DayOfMonth", "DayOfMonth must be between 1 and 31."); 1452 } 1453 1454 if (this.canSetFieldValue(this.dayOfMonth, value)) { 1455 this.dayOfMonth = value; 1456 this.changed(); 1457 } 1458 } 1459 } 1460 1461 1462 /** 1463 * Represents a regeneration pattern, as used with recurring tasks, where 1464 * each occurrence happens a specified number of years after the previous 1465 * one is completed. 1466 */ 1467 public final static class YearlyRegenerationPattern extends 1468 IntervalPattern { 1469 1470 /** 1471 * Gets the name of the XML element. <value>The name of the XML 1472 * element.</value> 1473 * 1474 * @return the xml element name 1475 */ 1476 @Override 1477 public String getXmlElementName() { 1478 return XmlElementNames.YearlyRegeneration; 1479 } 1480 1481 /** 1482 * Gets a value indicating whether this instance is regeneration 1483 * pattern. 1484 * 1485 * @return true, if is regeneration pattern 1486 */ 1487 public boolean isRegenerationPattern() { 1488 return true; 1489 } 1490 1491 /** 1492 * Initializes a new instance of the YearlyRegenerationPattern class. 1493 */ 1494 public YearlyRegenerationPattern() { 1495 super(); 1496 1497 } 1498 1499 /** 1500 * Initializes a new instance of the YearlyRegenerationPattern class. 1501 * 1502 * @param startDate the start date 1503 * @param interval the interval 1504 * @throws ArgumentOutOfRangeException the argument out of range exception 1505 */ 1506 public YearlyRegenerationPattern(Date startDate, int interval) 1507 throws ArgumentOutOfRangeException { 1508 super(startDate, interval); 1509 1510 } 1511 } 1512}