public void MSOXWSMTGS_S01_TC03_CreateRecurringMeetingAndDecline()
        {
            #region Organizer creates a recurring meeting with CalendarItemCreateOrDeleteOperationType value set to SendOnlyToAll
            #region Define a recurring meeting
            int timeInterval = this.TimeInterval;
            DateTime startTime = DateTime.Now.AddHours(timeInterval);

            DailyRecurrencePatternType pattern = new DailyRecurrencePatternType();
            pattern.Interval = this.PatternInterval;

            NumberedRecurrenceRangeType range = new NumberedRecurrenceRangeType();
            range.NumberOfOccurrences = this.NumberOfOccurrences;
            range.StartDate = startTime;

            CalendarItemType meetingItem = new CalendarItemType();
            meetingItem.UID = Guid.NewGuid().ToString();
            meetingItem.Subject = this.Subject;
            meetingItem.Start = startTime;

            // Indicates the Start property is serialized in the SOAP message.
            meetingItem.StartSpecified = true;
            timeInterval++;
            meetingItem.End = startTime.AddHours(timeInterval);
            meetingItem.EndSpecified = true;
            meetingItem.Location = this.Location;
            meetingItem.Recurrence = new RecurrenceType();
            meetingItem.Recurrence.Item = pattern;
            meetingItem.Recurrence.Item1 = range;
            meetingItem.RequiredAttendees = new AttendeeType[] { GetAttendeeOrResource(this.AttendeeEmailAddress) };
            meetingItem.OptionalAttendees = new AttendeeType[] { GetAttendeeOrResource(this.OrganizerEmailAddress) };
            meetingItem.Resources = new AttendeeType[] { GetAttendeeOrResource(this.RoomEmailAddress) };

            if (Common.IsRequirementEnabled(715, this.Site))
            {
                meetingItem.MeetingTimeZone = new TimeZoneType();
                meetingItem.MeetingTimeZone.BaseOffset = "PT7H";
                meetingItem.MeetingTimeZone.Standard = new TimeChangeType();
                meetingItem.MeetingTimeZone.Standard.Offset = "PT0H";
                meetingItem.MeetingTimeZone.Standard.Time = DateTime.Now;
                RelativeYearlyRecurrencePatternType yearlyRecurrence = new RelativeYearlyRecurrencePatternType();
                yearlyRecurrence.DaysOfWeek = "Sunday";
                yearlyRecurrence.DayOfWeekIndex = DayOfWeekIndexType.First;
                yearlyRecurrence.Month = MonthNamesType.November;
                meetingItem.MeetingTimeZone.Standard.Item = yearlyRecurrence;
                meetingItem.MeetingTimeZone.Daylight = new TimeChangeType();
                meetingItem.MeetingTimeZone.Daylight.Offset = "-PT1H";
                yearlyRecurrence = new RelativeYearlyRecurrencePatternType();
                yearlyRecurrence.DaysOfWeek = "Sunday";
                yearlyRecurrence.DayOfWeekIndex = DayOfWeekIndexType.Second;
                yearlyRecurrence.Month = MonthNamesType.March;
                meetingItem.MeetingTimeZone.Daylight.Item = yearlyRecurrence;
                meetingItem.MeetingTimeZone.Daylight.Time = DateTime.Now;
                meetingItem.MeetingTimeZone.TimeZoneName = "Time Zone";
            }
            #endregion

            // Create the recurring meeting
            ItemInfoResponseMessageType item = this.CreateSingleCalendarItem(Role.Organizer, meetingItem, CalendarItemCreateOrDeleteOperationType.SendOnlyToAll);
            Site.Assert.IsNotNull(item, "Server should return success for creating a recurring meeting.");
            ItemIdType meetingId = item.Items.Items[0].ItemId;

            #region Verify FirstOccurrence and LastOccurrence in the CalendarItemType
            ItemInfoResponseMessageType getItem = this.GetSingleCalendarItem(Role.Organizer, meetingId);
            Site.Assert.IsNotNull(getItem, "The calendar item to be deleted should exist.");

            if (Common.IsRequirementEnabled(715, this.Site))
            {
                CalendarItemType calendar = (CalendarItemType)getItem.Items.Items[0];

                // Add the debug information
                this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXWSMTGS_R715");

                // Verify MS-OXWSMTGS requirement: MS-OXWSMTGS_R715
                this.Site.CaptureRequirementIfIsNotNull(
                    calendar.MeetingTimeZone,
                    715,
                    @"[In Appendix C: Product Behavior] Implementation does support complex type ""MeetingTimeZone"" with type ""t:TimeZoneType (section 2.2.4.40)"" which does specify the time zone of the location where the meeting is hosted. (<28> Section 2.2.4.9: Only Exchange 2007 supports the MeetingTimeZone element.)");
                
                if (Common.IsRequirementEnabled(654, this.Site))
                {
                    // Add the debug information
                    this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXWSMTGS_R654");

                    // Verify MS-OXWSMTGS requirement: MS-OXWSMTGS_R654
                    this.Site.CaptureRequirementIfIsNotNull(
                        calendar.MeetingTimeZone,
                        654,
                        @"[In Appendix C: Product Behavior] Implementation does support the TimeZoneType complex type. (<17> Section 2.2.4: Only Exchange 2007 supports the TimeZoneType complex type.)");
                }

                // Add the debug information
                this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXWSMTGS_R1053");

                // Verify MS-OXWSMTGS requirement: MS-OXWSMTGS_R1053
                this.Site.CaptureRequirementIfIsNotNull(
                    calendar.MeetingTimeZone,
                    1053,
                    @"[In t:CalendarItemType Complex Type] This element [MeetingTimeZone] is returned only if the value of the CalendarItemType element is RecurringMaster.");

                TimeZoneType timeZone = calendar.MeetingTimeZone;

                // Add the debug information
                this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXWSMTGS_R407");

                // Verify MS-OXWSMTGS requirement: MS-OXWSMTGS_R407
                this.Site.CaptureRequirementIfIsNotNull(
                    timeZone.BaseOffset,
                    407,
                    @"[In t:TimeZoneType Complex Type] BaseOffset: Specifies the hourly offset from Coordinated Universal Time (UTC) for the current time zone.");

                // Add the debug information
                this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXWSMTGS_R409");

                // Verify MS-OXWSMTGS requirement: MS-OXWSMTGS_R409
                this.Site.CaptureRequirementIfIsNotNull(
                    timeZone.Standard,
                    409,
                    @"[In t:TimeZoneType Complex Type] Standard: Specifies the date and time when the time changes from daylight saving time to standard time.");

                // Add the debug information
                this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXWSMTGS_R411");

                // Verify MS-OXWSMTGS requirement: MS-OXWSMTGS_R411
                this.Site.CaptureRequirementIfIsNotNull(
                    timeZone.Daylight,
                    411,
                    @"[In t:TimeZoneType Complex Type] Daylight: Specifies the date and time when the time changes from standard time to daylight saving time.");

                // Add the debug information
                this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXWSMTGS_R585");

                // Verify MS-OXWSMTGS requirement: MS-OXWSMTGS_R585
                this.Site.CaptureRequirementIfIsNotNull(
                    timeZone.TimeZoneName,
                    585,
                    @"[In t:TimeZoneType Complex Type] TimeZoneName: Specifies the time zone name.");

                TimeChangeType timeChange = timeZone.Standard;

                // Add the debug information
                this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXWSMTGS_R399");

                // Verify MS-OXWSMTGS requirement: MS-OXWSMTGS_R399
                this.Site.CaptureRequirementIfIsNotNull(
                    timeChange.Offset,
                    399,
                    @"[In t:TimeChangeType Complex Type] Offset: Specifies the offset from the duration specified by the BaseOffset element (section 2.2.4.24).");

                // Add the debug information
                this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXWSMTGS_R401");

                // Verify MS-OXWSMTGS requirement: MS-OXWSMTGS_R401
                this.Site.CaptureRequirementIfIsNotNull(
                    timeChange.Time,
                    401,
                    @"[In t:TimeChangeType Complex Type] Time: Specifies the time when the time changes between standard time and daylight saving time.");

                // Add the debug information
                this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXWSMTGS_R403");

                // Verify MS-OXWSMTGS requirement: MS-OXWSMTGS_R403
                this.Site.CaptureRequirementIfIsNotNull(
                    timeChange.TimeZoneName,
                    403,
                    @"[In t:TimeChangeType Complex Type] TimeZoneName: Specifies the time zone name.");
            }

            string actualFirstOccurrenceId = ((CalendarItemType)getItem.Items.Items[0]).FirstOccurrence.ItemId.Id;
            string actualLastOccurrenceId = ((CalendarItemType)getItem.Items.Items[0]).LastOccurrence.ItemId.Id;

            // Get the first occurrence by item id
            OccurrenceItemIdType firstOccurrenceId = new OccurrenceItemIdType();
            firstOccurrenceId.ChangeKey = meetingId.ChangeKey;
            firstOccurrenceId.RecurringMasterId = meetingId.Id;
            firstOccurrenceId.InstanceIndex = 1;

            getItem = this.GetSingleCalendarItem(Role.Organizer, firstOccurrenceId);
            Site.Assert.IsNotNull(getItem, "The first occurrence should be found.");
            CalendarItemType firstOccurrence = getItem.Items.Items[0] as CalendarItemType;

            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXWSMTGS_R213");

            // Verify MS-OXWSMTGS requirement: MS-OXWSMTGS_R213
            this.Site.CaptureRequirementIfAreEqual<string>(
                firstOccurrence.ItemId.Id,
                actualFirstOccurrenceId,
                213,
                "[In t:CalendarItemType Complex Type]FirstOccurrence: Specifies the first occurrence of a recurring calendar item.");

            // Get the last occurrence by item id
            OccurrenceItemIdType lastOccurrenceId = new OccurrenceItemIdType();
            lastOccurrenceId.ChangeKey = meetingId.ChangeKey;
            lastOccurrenceId.RecurringMasterId = meetingId.Id;
            lastOccurrenceId.InstanceIndex = this.NumberOfOccurrences;

            getItem = this.GetSingleCalendarItem(Role.Organizer, lastOccurrenceId);
            Site.Assert.IsNotNull(getItem, "The last occurrence should be found.");
            CalendarItemType lastOccurrence = getItem.Items.Items[0] as CalendarItemType;

            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXWSMTGS_R215");

            // Verify MS-OXWSMTGS requirement: MS-OXWSMTGS_R215
            this.Site.CaptureRequirementIfAreEqual<string>(
                lastOccurrence.ItemId.Id,
                actualLastOccurrenceId,
                215,
                "[In t:CalendarItemType Complex Type]LastOccurrence: Specifies the last occurrence of a recurring calendar item.");
            #endregion
            #endregion

            #region Organizer deletes an occurrence of the recurring calendar item with CalendarItemCreateOrDeleteOperationType value set to SendOnlyToAll
            OccurrenceItemIdType occurrenceItemId = new OccurrenceItemIdType();
            occurrenceItemId.ChangeKey = meetingId.ChangeKey;
            occurrenceItemId.RecurringMasterId = meetingId.Id;
            occurrenceItemId.InstanceIndex = this.InstanceIndex;

            getItem = this.GetSingleCalendarItem(Role.Organizer, occurrenceItemId);
            Site.Assert.IsNotNull(getItem, "The calendar item to be deleted should exist.");

            ResponseMessageType deletedItem = this.DeleteSingleCalendarItem(Role.Organizer, occurrenceItemId, CalendarItemCreateOrDeleteOperationType.SendOnlyToAll);
            Site.Assert.IsNotNull(deletedItem, "The occurrence of the recurring calendar item should be deleted.");
            #endregion

            #region Attendee calls CreateItem to decline the meeting request with CalendarItemCreateOrDeleteOperationType value set to SendOnlyToAll
            MeetingRequestMessageType request = this.SearchSingleItem(Role.Attendee, DistinguishedFolderIdNameType.inbox, "IPM.Schedule.Meeting.Request", meetingItem.UID) as MeetingRequestMessageType;
            Site.Assert.IsNotNull(request, "Attendee should receive the meeting request message in the Inbox folder after organizer calls CreateItem with CalendarItemCreateOrDeleteOperationType set to SendOnlyToAll.");

            bool isFirstOccurrence = (firstOccurrence.Start == request.FirstOccurrence.Start) && (firstOccurrence.End == request.FirstOccurrence.End);

            if (Common.IsRequirementEnabled(715, this.Site)
                && Common.IsRequirementEnabled(706, this.Site))
            {
                // Add the debug information
                this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXWSMTGS_R706");

                // Verify MS-OXWSMTGS requirement: MS-OXWSMTGS_R706
                this.Site.CaptureRequirementIfIsNotNull(
                    request.MeetingTimeZone,
                    706,
                    @"[In Appendix C: Product Behavior] Implementation does support the complex type ""MeetingTimeZone"" with type ""t:TimeZoneType (section 2.2.4.24)"" which does specify the time zone of the location where the meeting is hosted. (<52> Section 2.2.4.22:  Only Exchange 2007 supports the MeetingTimeZone element.)");

                // Add the debug information
                this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXWSMTGS_R1090");

                // Verify MS-OXWSMTGS requirement: MS-OXWSMTGS_R1090
                this.Site.CaptureRequirementIfIsNotNull(
                    request.MeetingTimeZone,
                    1090,
                    @"[In t:MeetingRequestMessageType Complex Type] This element [MeetingTimeZone] is returned only if the value of the CalendarItemType element is RecurringMaster.");
            }

            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXWSMTGS_R341, expected value of Start of first occurrence is {0} and actual value is {1}; expected value of End of first occurrence is {2} and actual value is {3}", firstOccurrence.Start, request.FirstOccurrence.Start, firstOccurrence.End, request.FirstOccurrence.End);

            // Verify MS-OXWSMTGS requirement: MS-OXWSMTGS_R341
            this.Site.CaptureRequirementIfIsTrue(
                isFirstOccurrence,
                341,
                "[In t:MeetingRequestMessageType Complex Type] FirstOccurrence: Represents the first occurrence of a recurring meeting item.");

            bool isLastOccurrence = (lastOccurrence.Start == request.LastOccurrence.Start) && (lastOccurrence.End == request.LastOccurrence.End);

            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXWSMTGS_R343, expected value of Start of last occurrence is {0} and actual value is {1}; expected value of End of last occurrence is {2} and actual value is {3}", lastOccurrence.Start, request.LastOccurrence.Start, lastOccurrence.End, request.LastOccurrence.End);

            // Verify MS-OXWSMTGS requirement: MS-OXWSMTGS_R343
            this.Site.CaptureRequirementIfIsTrue(
                isLastOccurrence,
                343,
                "[In t:MeetingRequestMessageType Complex Type] LastOccurrence: Represents the last occurrence of a recurring meeting item.");

            DeclineItemType declinedItem = new DeclineItemType();
            declinedItem.ReferenceItemId = new ItemIdType();
            declinedItem.ReferenceItemId.Id = request.ItemId.Id;

            item = this.CreateSingleCalendarItem(Role.Attendee, declinedItem, CalendarItemCreateOrDeleteOperationType.SendOnlyToAll);
            Site.Assert.IsNotNull(item, "Decline meeting request should be successful.");
            #endregion

            #region Organizer calls CreateItem with MeetingCancellationMessageType to cancel the created meeting with CalendarItemCreateOrDeleteOperationType value set to SendOnlyToAll
            MeetingResponseMessageType response = this.SearchSingleItem(Role.Organizer, DistinguishedFolderIdNameType.inbox, "IPM.Schedule.Meeting.Resp", meetingItem.UID) as MeetingResponseMessageType;
            Site.Assert.IsNotNull(response, "The decline response should be in the Inbox folder.");
            CancelCalendarItemType cancelCalendarItem = new CancelCalendarItemType();
            cancelCalendarItem.ReferenceItemId = response.AssociatedCalendarItemId;

            item = this.CreateSingleCalendarItem(Role.Organizer, cancelCalendarItem, CalendarItemCreateOrDeleteOperationType.SendOnlyToAll);
            Site.Assert.IsNotNull(item, "Cancel the meeting through CancelCalendarItemType using CreateItem should be successful.");
            #endregion

            #region Attendee finds the meeting cancellation message from his Inbox folder
            MeetingCancellationMessageType canceledMeeting = this.SearchSingleItem(Role.Attendee, DistinguishedFolderIdNameType.inbox, "IPM.Schedule.Meeting.Canceled", meetingItem.UID) as MeetingCancellationMessageType;
            Site.Assert.IsNotNull(canceledMeeting, "The canceled meeting should be in the Inbox folder.");
            #endregion

            #region Clean up organizer's inbox, sentitems and deleteditems folders, and attendee's inbox, sentitems and deleteditems folders.
            this.CleanupFoldersByRole(Role.Organizer, new List<DistinguishedFolderIdNameType>() { DistinguishedFolderIdNameType.inbox, DistinguishedFolderIdNameType.sentitems, DistinguishedFolderIdNameType.deleteditems });
            this.CleanupFoldersByRole(Role.Attendee, new List<DistinguishedFolderIdNameType>() { DistinguishedFolderIdNameType.inbox, DistinguishedFolderIdNameType.sentitems, DistinguishedFolderIdNameType.deleteditems });
            #endregion
        }
 public void MSOXWSMTGS_S01_TC15_ModifyOccurrenceWithRelativeYearlyPatternAndNoEndRange()
 {
     // Verify RelativeYearlyRecurrencePatternType and NoEndRecurrenceRangeType.
     RelativeYearlyRecurrencePatternType relativeYearly = new RelativeYearlyRecurrencePatternType();
     relativeYearly.DaysOfWeek = "Wednesday";
     relativeYearly.DayOfWeekIndex = DayOfWeekIndexType.First;
     relativeYearly.Month = MonthNamesType.January;
     NoEndRecurrenceRangeType nonEndRange = new NoEndRecurrenceRangeType();
     this.VerifyModifiedOccurrences(relativeYearly, nonEndRange);
 }