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. 642 * 643 * @return the xml element name 644 */ 645 @Override 646 public String getXmlElementName() { 647 return XmlElementNames.MonthlyRegeneration; 648 } 649 650 /** 651 * Gets a value indicating whether this instance is regeneration 652 * pattern. <em>true</em> if this instance is regeneration 653 * pattern; otherwise, <em>false</em>. 654 * 655 * @return true, if is regeneration pattern 656 */ 657 public boolean isRegenerationPattern() { 658 return true; 659 } 660 } 661 662 663 /** 664 * Represents a recurrence pattern where each occurrence happens on a 665 * relative day a specific number of months after the previous one. 666 */ 667 public final static class RelativeMonthlyPattern extends IntervalPattern { 668 669 /** 670 * The day of the week. 671 */ 672 private DayOfTheWeek dayOfTheWeek; 673 674 /** 675 * The day of the week index. 676 */ 677 private DayOfTheWeekIndex dayOfTheWeekIndex; 678 679 // / Initializes a new instance of the <see 680 // cref="RelativeMonthlyPattern"/> class. 681 682 /** 683 * Instantiates a new relative monthly pattern. 684 */ 685 public RelativeMonthlyPattern() { 686 super(); 687 } 688 689 /** 690 * Instantiates a new relative monthly pattern. 691 * 692 * @param startDate the start date 693 * @param interval the interval 694 * @param dayOfTheWeek the day of the week 695 * @param dayOfTheWeekIndex the day of the week index 696 * @throws ArgumentOutOfRangeException the argument out of range exception 697 */ 698 public RelativeMonthlyPattern(Date startDate, int interval, 699 DayOfTheWeek dayOfTheWeek, DayOfTheWeekIndex dayOfTheWeekIndex) 700 throws ArgumentOutOfRangeException { 701 super(startDate, interval); 702 703 this.setDayOfTheWeek(dayOfTheWeek); 704 this.setDayOfTheWeekIndex(dayOfTheWeekIndex); 705 } 706 707 /** 708 * Gets the name of the XML element. 709 * 710 * @return the xml element name 711 */ 712 @Override 713 public String getXmlElementName() { 714 return XmlElementNames.RelativeMonthlyRecurrence; 715 } 716 717 /** 718 * Write property to XML. 719 * 720 * @param writer the writer 721 * @throws Exception the exception 722 */ 723 @Override 724 public void internalWritePropertiesToXml(EwsServiceXmlWriter writer) 725 throws Exception { 726 super.internalWritePropertiesToXml(writer); 727 728 writer.writeElementValue(XmlNamespace.Types, 729 XmlElementNames.DaysOfWeek, this.getDayOfTheWeek()); 730 731 writer 732 .writeElementValue(XmlNamespace.Types, 733 XmlElementNames.DayOfWeekIndex, this 734 .getDayOfTheWeekIndex()); 735 } 736 737 /** 738 * Tries to read element from XML. 739 * 740 * @param reader the reader 741 * @return True if appropriate element was read. 742 * @throws Exception the exception 743 */ 744 @Override 745 public boolean tryReadElementFromXml(EwsServiceXmlReader reader) 746 throws Exception { 747 if (super.tryReadElementFromXml(reader)) { 748 return true; 749 } else { 750 if (reader.getLocalName().equals(XmlElementNames.DaysOfWeek)) { 751 752 this.dayOfTheWeek = reader 753 .readElementValue(DayOfTheWeek.class); 754 return true; 755 } else if (reader.getLocalName().equals( 756 XmlElementNames.DayOfWeekIndex)) { 757 758 this.dayOfTheWeekIndex = reader 759 .readElementValue(DayOfTheWeekIndex.class); 760 return true; 761 } else { 762 763 return false; 764 } 765 } 766 } 767 768 /** 769 * Validates this instance. 770 * 771 * @throws Exception 772 */ 773 @Override 774 public void internalValidate() throws Exception { 775 super.internalValidate(); 776 777 if (this.dayOfTheWeek == null) { 778 throw new ServiceValidationException( 779 "The recurrence pattern's property DayOfTheWeek must be specified."); 780 } 781 782 if (this.dayOfTheWeekIndex == null) { 783 throw new ServiceValidationException( 784 "The recurrence pattern's DayOfWeekIndex property must be specified."); 785 } 786 } 787 788 /** 789 * Day of the week index. 790 * 791 * @return the day of the week index 792 * @throws ServiceValidationException the service validation exception 793 */ 794 public DayOfTheWeekIndex getDayOfTheWeekIndex() 795 throws ServiceValidationException { 796 return this.getFieldValueOrThrowIfNull(DayOfTheWeekIndex.class, 797 this.dayOfTheWeekIndex, "DayOfTheWeekIndex"); 798 } 799 800 /** 801 * Day of the week index. 802 * 803 * @param value the value 804 */ 805 public void setDayOfTheWeekIndex(DayOfTheWeekIndex value) { 806 if (this.canSetFieldValue(this.dayOfTheWeekIndex, value)) { 807 this.dayOfTheWeekIndex = value; 808 this.changed(); 809 } 810 811 } 812 813 /** 814 * Gets the day of the week. 815 * 816 * @return the day of the week 817 * @throws ServiceValidationException the service validation exception 818 */ 819 public DayOfTheWeek getDayOfTheWeek() 820 throws ServiceValidationException { 821 return this.getFieldValueOrThrowIfNull(DayOfTheWeek.class, 822 this.dayOfTheWeek, "DayOfTheWeek"); 823 824 } 825 826 /** 827 * Sets the day of the week. 828 * 829 * @param value the new day of the week 830 */ 831 public void setDayOfTheWeek(DayOfTheWeek value) { 832 833 if (this.canSetFieldValue(this.dayOfTheWeek, value)) { 834 this.dayOfTheWeek = value; 835 this.changed(); 836 } 837 } 838 } 839 840 841 /** 842 * The Class RelativeYearlyPattern. 843 */ 844 public final static class RelativeYearlyPattern extends Recurrence { 845 846 /** 847 * The day of the week. 848 */ 849 private DayOfTheWeek dayOfTheWeek; 850 851 /** 852 * The day of the week index. 853 */ 854 private DayOfTheWeekIndex dayOfTheWeekIndex; 855 856 /** 857 * The month. 858 */ 859 private Month month; 860 861 /** 862 * Gets the name of the XML element. 863 * 864 * @return the xml element name 865 */ 866 @Override 867 public String getXmlElementName() { 868 return XmlElementNames.RelativeYearlyRecurrence; 869 } 870 871 /** 872 * Write property to XML. 873 * 874 * @param writer the writer 875 * @throws Exception the exception 876 */ 877 @Override 878 public void internalWritePropertiesToXml(EwsServiceXmlWriter writer) 879 throws Exception { 880 super.internalWritePropertiesToXml(writer); 881 882 writer.writeElementValue(XmlNamespace.Types, 883 XmlElementNames.DaysOfWeek, this.dayOfTheWeek); 884 885 writer.writeElementValue(XmlNamespace.Types, 886 XmlElementNames.DayOfWeekIndex, this.dayOfTheWeekIndex); 887 888 writer.writeElementValue(XmlNamespace.Types, XmlElementNames.Month, 889 this.month); 890 } 891 892 /** 893 * Tries to read element from XML. 894 * 895 * @param reader the reader 896 * @return True if element was read. 897 * @throws Exception the exception 898 */ 899 @Override 900 public boolean tryReadElementFromXml(EwsServiceXmlReader reader) 901 throws Exception { 902 if (super.tryReadElementFromXml(reader)) { 903 return true; 904 } else { 905 if (reader.getLocalName().equals(XmlElementNames.DaysOfWeek)) { 906 907 this.dayOfTheWeek = reader 908 .readElementValue(DayOfTheWeek.class); 909 return true; 910 } else if (reader.getLocalName().equals( 911 XmlElementNames.DayOfWeekIndex)) { 912 913 this.dayOfTheWeekIndex = reader 914 .readElementValue(DayOfTheWeekIndex.class); 915 return true; 916 } else if (reader.getLocalName().equals(XmlElementNames.Month)) { 917 918 this.month = reader.readElementValue(Month.class); 919 return true; 920 } else { 921 922 return false; 923 } 924 } 925 } 926 927 /** 928 * Instantiates a new relative yearly pattern. 929 */ 930 public RelativeYearlyPattern() { 931 super(); 932 933 } 934 935 /** 936 * Instantiates a new relative yearly pattern. 937 * 938 * @param startDate the start date 939 * @param month the month 940 * @param dayOfTheWeek the day of the week 941 * @param dayOfTheWeekIndex the day of the week index 942 */ 943 public RelativeYearlyPattern(Date startDate, Month month, 944 DayOfTheWeek dayOfTheWeek, 945 DayOfTheWeekIndex dayOfTheWeekIndex) { 946 super(startDate); 947 948 this.month = month; 949 this.dayOfTheWeek = dayOfTheWeek; 950 this.dayOfTheWeekIndex = dayOfTheWeekIndex; 951 } 952 953 /** 954 * Validates this instance. 955 * 956 * @throws Exception 957 */ 958 @Override 959 public void internalValidate() throws Exception { 960 super.internalValidate(); 961 962 if (this.dayOfTheWeekIndex == null) { 963 throw new ServiceValidationException( 964 "The recurrence pattern's DayOfWeekIndex property must be specified."); 965 } 966 967 if (this.dayOfTheWeek == null) { 968 throw new ServiceValidationException( 969 "The recurrence pattern's property DayOfTheWeek must be specified."); 970 } 971 972 if (this.month == null) { 973 throw new ServiceValidationException("The recurrence pattern's Month property must be specified."); 974 } 975 } 976 977 /** 978 * Gets the relative position of the day specified in DayOfTheWeek 979 * within the month. 980 * 981 * @return the day of the week index 982 * @throws ServiceValidationException the service validation exception 983 */ 984 public DayOfTheWeekIndex getDayOfTheWeekIndex() 985 throws ServiceValidationException { 986 987 return this.getFieldValueOrThrowIfNull(DayOfTheWeekIndex.class, 988 this.dayOfTheWeekIndex, "DayOfTheWeekIndex"); 989 } 990 991 /** 992 * Sets the relative position of the day specified in DayOfTheWeek 993 * within the month. 994 * 995 * @param value the new day of the week index 996 */ 997 public void setDayOfTheWeekIndex(DayOfTheWeekIndex value) { 998 999 if (this.canSetFieldValue(this.dayOfTheWeekIndex, value)) { 1000 this.dayOfTheWeekIndex = value; 1001 this.changed(); 1002 } 1003 } 1004 1005 /** 1006 * Gets the day of the week. 1007 * 1008 * @return the day of the week 1009 * @throws ServiceValidationException the service validation exception 1010 */ 1011 public DayOfTheWeek getDayOfTheWeek() 1012 throws ServiceValidationException { 1013 1014 return this.getFieldValueOrThrowIfNull(DayOfTheWeek.class, 1015 this.dayOfTheWeek, "DayOfTheWeek"); 1016 } 1017 1018 /** 1019 * Sets the day of the week. 1020 * 1021 * @param value the new day of the week 1022 */ 1023 public void setDayOfTheWeek(DayOfTheWeek value) { 1024 1025 if (this.canSetFieldValue(this.dayOfTheWeek, value)) { 1026 this.dayOfTheWeek = value; 1027 this.changed(); 1028 } 1029 } 1030 1031 /** 1032 * Gets the month. 1033 * 1034 * @return the month 1035 * @throws ServiceValidationException the service validation exception 1036 */ 1037 public Month getMonth() throws ServiceValidationException { 1038 1039 return this.getFieldValueOrThrowIfNull(Month.class, this.month, 1040 "Month"); 1041 1042 } 1043 1044 /** 1045 * Sets the month. 1046 * 1047 * @param value the new month 1048 */ 1049 public void setMonth(Month value) { 1050 1051 if (this.canSetFieldValue(this.month, value)) { 1052 this.month = value; 1053 this.changed(); 1054 } 1055 } 1056 } 1057 1058 1059 /** 1060 * Represents a recurrence pattern where each occurrence happens on specific 1061 * days a specific number of weeks after the previous one. 1062 */ 1063 public final static class WeeklyPattern extends IntervalPattern implements IComplexPropertyChangedDelegate { 1064 1065 /** 1066 * The days of the week. 1067 */ 1068 private DayOfTheWeekCollection daysOfTheWeek = 1069 new DayOfTheWeekCollection(); 1070 1071 private Calendar firstDayOfWeek; 1072 1073 /** 1074 * Initializes a new instance of the WeeklyPattern class. specific days 1075 * a specific number of weeks after the previous one. 1076 */ 1077 public WeeklyPattern() { 1078 super(); 1079 1080 this.daysOfTheWeek.addOnChangeEvent(this); 1081 } 1082 1083 /** 1084 * Initializes a new instance of the WeeklyPattern class. 1085 * 1086 * @param startDate the start date 1087 * @param interval the interval 1088 * @param daysOfTheWeek the days of the week 1089 * @throws ArgumentOutOfRangeException the argument out of range exception 1090 */ 1091 public WeeklyPattern(Date startDate, int interval, 1092 DayOfTheWeek... daysOfTheWeek) 1093 throws ArgumentOutOfRangeException { 1094 super(startDate, interval); 1095 1096 ArrayList<DayOfTheWeek> toProcess = new ArrayList<DayOfTheWeek>( 1097 Arrays.asList(daysOfTheWeek)); 1098 Iterator<DayOfTheWeek> idaysOfTheWeek = toProcess.iterator(); 1099 this.daysOfTheWeek.addRange(idaysOfTheWeek); 1100 } 1101 1102 /** 1103 * Change event handler. 1104 * 1105 * @param complexProperty the complex property 1106 */ 1107 private void daysOfTheWeekChanged(ComplexProperty complexProperty) { 1108 this.changed(); 1109 } 1110 1111 /** 1112 * Gets the name of the XML element. 1113 * 1114 * @return the xml element name 1115 */ 1116 @Override 1117 public String getXmlElementName() { 1118 return XmlElementNames.WeeklyRecurrence; 1119 } 1120 1121 /** 1122 * Write property to XML. 1123 * 1124 * @param writer the writer 1125 * @throws Exception the exception 1126 */ 1127 @Override 1128 public void internalWritePropertiesToXml(EwsServiceXmlWriter writer) 1129 throws Exception { 1130 super.internalWritePropertiesToXml(writer); 1131 1132 this.getDaysOfTheWeek().writeToXml(writer, 1133 XmlElementNames.DaysOfWeek); 1134 if (this.firstDayOfWeek != null) { 1135 1136 EwsUtilities 1137 .validatePropertyVersion((ExchangeService) writer.getService(), ExchangeVersion.Exchange2010_SP1, 1138 "FirstDayOfWeek"); 1139 1140 writer.writeElementValue( 1141 XmlNamespace.Types, 1142 XmlElementNames.FirstDayOfWeek, 1143 this.firstDayOfWeek); 1144 } 1145 1146 } 1147 1148 /** 1149 * Tries to read element from XML. 1150 * 1151 * @param reader the reader 1152 * @return True if appropriate element was read. 1153 * @throws Exception the exception 1154 */ 1155 @Override 1156 public boolean tryReadElementFromXml(EwsServiceXmlReader reader) 1157 throws Exception { 1158 if (super.tryReadElementFromXml(reader)) { 1159 return true; 1160 } else { 1161 if (reader.getLocalName().equals(XmlElementNames.DaysOfWeek)) { 1162 1163 this.getDaysOfTheWeek().loadFromXml(reader, 1164 reader.getLocalName()); 1165 return true; 1166 } else if (reader.getLocalName().equals(XmlElementNames.FirstDayOfWeek)) { 1167 this.firstDayOfWeek = reader. 1168 readElementValue(Calendar.class, 1169 XmlNamespace.Types, 1170 XmlElementNames.FirstDayOfWeek); 1171 return true; 1172 } else { 1173 1174 return false; 1175 } 1176 } 1177 } 1178 1179 /** 1180 * Validates this instance. 1181 * 1182 * @throws Exception 1183 */ 1184 @Override 1185 public void internalValidate() throws Exception { 1186 super.internalValidate(); 1187 1188 if (this.getDaysOfTheWeek().getCount() == 0) { 1189 throw new ServiceValidationException( 1190 "The recurrence pattern's property DaysOfTheWeek must contain at least one day of the week."); 1191 } 1192 } 1193 1194 /** 1195 * Gets the list of the days of the week when occurrences happen. 1196 * 1197 * @return the days of the week 1198 */ 1199 public DayOfTheWeekCollection getDaysOfTheWeek() { 1200 return this.daysOfTheWeek; 1201 } 1202 1203 public Calendar getFirstDayOfWeek() throws ServiceValidationException { 1204 return this.getFieldValueOrThrowIfNull(Calendar.class, 1205 this.firstDayOfWeek, "FirstDayOfWeek"); 1206 } 1207 1208 public void setFirstDayOfWeek(Calendar value) { 1209 if (this.canSetFieldValue(this.firstDayOfWeek, value)) { 1210 this.firstDayOfWeek = value; 1211 this.changed(); 1212 } 1213 } 1214 1215 /* 1216 * (non-Javadoc) 1217 * 1218 * @see 1219 * microsoft.exchange.webservices. 1220 * ComplexPropertyChangedDelegateInterface# 1221 * complexPropertyChanged(microsoft.exchange.webservices.ComplexProperty 1222 * ) 1223 */ 1224 @Override 1225 public void complexPropertyChanged(ComplexProperty complexProperty) { 1226 this.daysOfTheWeekChanged(complexProperty); 1227 } 1228 1229 } 1230 1231 1232 /** 1233 * Represents a regeneration pattern, as used with recurring tasks, where 1234 * each occurrence happens a specified number of weeks after the previous 1235 * one is completed. 1236 */ 1237 public final static class WeeklyRegenerationPattern extends 1238 IntervalPattern { 1239 1240 /** 1241 * Initializes a new instance of the WeeklyRegenerationPattern class. 1242 */ 1243 public WeeklyRegenerationPattern() { 1244 1245 super(); 1246 } 1247 1248 /** 1249 * Initializes a new instance of the WeeklyRegenerationPattern class. 1250 * 1251 * @param startDate the start date 1252 * @param interval the interval 1253 * @throws ArgumentOutOfRangeException the argument out of range exception 1254 */ 1255 public WeeklyRegenerationPattern(Date startDate, int interval) 1256 throws ArgumentOutOfRangeException { 1257 super(startDate, interval); 1258 1259 } 1260 1261 /** 1262 * Gets the name of the XML element. 1263 * 1264 * @return the xml element name 1265 */ 1266 @Override 1267 public String getXmlElementName() { 1268 return XmlElementNames.WeeklyRegeneration; 1269 } 1270 1271 /** 1272 * Gets a value indicating whether this instance is regeneration 1273 * pattern. <em>true</em> if this instance is regeneration 1274 * pattern; otherwise, <em>false</em>. 1275 * 1276 * @return true, if is regeneration pattern 1277 */ 1278 public boolean isRegenerationPattern() { 1279 return true; 1280 } 1281 } 1282 1283 1284 /** 1285 * Represents a recurrence pattern where each occurrence happens on a 1286 * specific day every year. 1287 */ 1288 public final static class YearlyPattern extends Recurrence { 1289 1290 /** 1291 * The month. 1292 */ 1293 private Month month; 1294 1295 /** 1296 * The day of month. 1297 */ 1298 private Integer dayOfMonth; 1299 1300 /** 1301 * Initializes a new instance of the YearlyPattern class. 1302 */ 1303 public YearlyPattern() { 1304 super(); 1305 1306 } 1307 1308 /** 1309 * Initializes a new instance of the YearlyPattern class. 1310 * 1311 * @param startDate the start date 1312 * @param month the month 1313 * @param dayOfMonth the day of month 1314 */ 1315 public YearlyPattern(Date startDate, Month month, int dayOfMonth) { 1316 super(startDate); 1317 1318 this.month = month; 1319 this.dayOfMonth = dayOfMonth; 1320 } 1321 1322 /** 1323 * Gets the name of the XML element. 1324 * 1325 * @return the xml element name 1326 */ 1327 @Override 1328 public String getXmlElementName() { 1329 return XmlElementNames.AbsoluteYearlyRecurrence; 1330 } 1331 1332 /** 1333 * Write property to XML. 1334 * 1335 * @param writer the writer 1336 * @throws Exception the exception 1337 */ 1338 @Override 1339 public void internalWritePropertiesToXml(EwsServiceXmlWriter writer) 1340 throws Exception { 1341 super.internalWritePropertiesToXml(writer); 1342 1343 writer.writeElementValue(XmlNamespace.Types, 1344 XmlElementNames.DayOfMonth, this.getDayOfMonth()); 1345 1346 writer.writeElementValue(XmlNamespace.Types, XmlElementNames.Month, 1347 this.getMonth()); 1348 } 1349 1350 /** 1351 * Tries to read element from XML. 1352 * 1353 * @param reader the reader 1354 * @return True if element was read 1355 * @throws Exception the exception 1356 */ 1357 @Override 1358 public boolean tryReadElementFromXml(EwsServiceXmlReader reader) 1359 throws Exception { 1360 if (super.tryReadElementFromXml(reader)) { 1361 return true; 1362 } else { 1363 if (reader.getLocalName().equals(XmlElementNames.DayOfMonth)) { 1364 1365 this.dayOfMonth = reader.readElementValue(Integer.class); 1366 return true; 1367 } else if (reader.getLocalName().equals(XmlElementNames.Month)) { 1368 1369 this.month = reader.readElementValue(Month.class); 1370 return true; 1371 } else { 1372 1373 return false; 1374 } 1375 } 1376 } 1377 1378 /** 1379 * Validates this instance. 1380 * 1381 * @throws Exception 1382 */ 1383 @Override 1384 public void internalValidate() throws Exception { 1385 super.internalValidate(); 1386 1387 if (this.month == null) { 1388 throw new ServiceValidationException("The recurrence pattern's Month property must be specified."); 1389 } 1390 1391 if (this.dayOfMonth == null) { 1392 throw new ServiceValidationException( 1393 "The recurrence pattern's DayOfMonth property must be specified."); 1394 } 1395 } 1396 1397 /** 1398 * Gets the month of the year when each occurrence happens. 1399 * 1400 * @return the month 1401 * @throws ServiceValidationException the service validation exception 1402 */ 1403 public Month getMonth() throws ServiceValidationException { 1404 return this.getFieldValueOrThrowIfNull(Month.class, this.month, 1405 "Month"); 1406 } 1407 1408 /** 1409 * Sets the month. 1410 * 1411 * @param value the new month 1412 */ 1413 public void setMonth(Month value) { 1414 1415 if (this.canSetFieldValue(this.month, value)) { 1416 this.month = value; 1417 this.changed(); 1418 } 1419 } 1420 1421 /** 1422 * Gets the day of the month when each occurrence happens. DayOfMonth 1423 * must be between 1 and 31. 1424 * 1425 * @return the day of month 1426 * @throws ServiceValidationException the service validation exception 1427 */ 1428 public int getDayOfMonth() throws ServiceValidationException { 1429 1430 return this.getFieldValueOrThrowIfNull(Integer.class, this.dayOfMonth, 1431 "DayOfMonth"); 1432 1433 } 1434 1435 /** 1436 * Sets the day of the month when each occurrence happens. DayOfMonth 1437 * must be between 1 and 31. 1438 * 1439 * @param value the new day of month 1440 * @throws ArgumentOutOfRangeException the argument out of range exception 1441 */ 1442 public void setDayOfMonth(int value) 1443 throws ArgumentOutOfRangeException { 1444 1445 if (value < 1 || value > 31) { 1446 throw new ArgumentOutOfRangeException("DayOfMonth", "DayOfMonth must be between 1 and 31."); 1447 } 1448 1449 if (this.canSetFieldValue(this.dayOfMonth, value)) { 1450 this.dayOfMonth = value; 1451 this.changed(); 1452 } 1453 } 1454 } 1455 1456 1457 /** 1458 * Represents a regeneration pattern, as used with recurring tasks, where 1459 * each occurrence happens a specified number of years after the previous 1460 * one is completed. 1461 */ 1462 public final static class YearlyRegenerationPattern extends 1463 IntervalPattern { 1464 1465 /** 1466 * Gets the name of the XML element. 1467 * 1468 * @return the xml element name 1469 */ 1470 @Override 1471 public String getXmlElementName() { 1472 return XmlElementNames.YearlyRegeneration; 1473 } 1474 1475 /** 1476 * Gets a value indicating whether this instance is regeneration 1477 * pattern. 1478 * 1479 * @return true, if is regeneration pattern 1480 */ 1481 public boolean isRegenerationPattern() { 1482 return true; 1483 } 1484 1485 /** 1486 * Initializes a new instance of the YearlyRegenerationPattern class. 1487 */ 1488 public YearlyRegenerationPattern() { 1489 super(); 1490 1491 } 1492 1493 /** 1494 * Initializes a new instance of the YearlyRegenerationPattern class. 1495 * 1496 * @param startDate the start date 1497 * @param interval the interval 1498 * @throws ArgumentOutOfRangeException the argument out of range exception 1499 */ 1500 public YearlyRegenerationPattern(Date startDate, int interval) 1501 throws ArgumentOutOfRangeException { 1502 super(startDate, interval); 1503 1504 } 1505 } 1506}