/// <summary> /// Merges a users appointment schedule from with appointments generated from a /// GoogleApps feed /// </summary> /// <param name="user">User to update with Google Apps information</param> /// <param name="googleAppsFeed">Source feed to generate appointment information</param> /// <param name="exchangeGateway">Gateway to sync Appointments with</param> /// <param name="window">DateRange to sync for</param> public void SyncUser( ExchangeUser user, EventFeed googleAppsFeed, ExchangeService exchangeGateway, DateTimeRange window) { exchangeGateway.GetCalendarInfoForUser(user, window); if (!user.HaveAppointmentDetail) { // Cannot sync if there is no appointment detail log.InfoFormat("Skipped Sync of {0} due to missing appointment lookup failure", user.Email); return; } List <Appointment> toUpdate = new List <Appointment>(); List <Appointment> toDelete = new List <Appointment>(); List <Appointment> toCreate = new List <Appointment>(); OlsonTimeZone feedTimeZone = OlsonUtil.GetTimeZone(googleAppsFeed.TimeZone.Value); IntervalTree <Appointment> gcalApptTree = CreateAppointments(user, feedTimeZone, googleAppsFeed); /* Iterate through each Free/Busy time block for the user */ foreach (FreeBusyTimeBlock fbtb in user.BusyTimes.Values) { /* Iterate through each appointment for the Free/Busy time block */ foreach (Appointment appt in fbtb.Appointments) { log.Debug(String.Format("Exchange @ '{0} {1}'", appt.Range, ValidateOwnership(appt))); /* Validate that this is a GCalender appoint */ if (ValidateOwnership(appt)) { /* If the GCalender appointments do not contain an * appointment for this period, add it for deletion */ if (gcalApptTree.FindExact(appt.Range) == null) { toDelete.Add(appt); } } } } /* Iterate through each Google Apps appointment */ AppointmentCollection appointments = user.BusyTimes.Appointments; List <Appointment> gcalApptList = gcalApptTree.GetNodeList(); foreach (Appointment newAppt in gcalApptList) { // If the meeting was cancelled log.DebugFormat("Looking @ {0} {1}", newAppt.Range, newAppt.Range.Start.Kind); if (newAppt.MeetingStatus == MeetingStatus.Cancelled) { // Check if there is an existing appointment that matches List <Appointment> matches = appointments.Get(newAppt.Range); foreach (Appointment a in matches) { if (ValidateOwnership(a)) { toDelete.Add(a); } } // Work is done for this appointment, continue to next entry continue; } bool updatedAppointment = false; List <Appointment> apptList = appointments.Get(newAppt.Range); log.DebugFormat("Looking up preexisting event: {0} {1}", newAppt.Range, newAppt.Range.Start.Kind); log.DebugFormat("Found {0} matching items", apptList.Count); // Check that there is a free busy block that correlates with this appointment foreach (Appointment existingAppt in apptList) { if (ValidateOwnership(existingAppt) && !updatedAppointment) { UpdateAppointmentInfo(existingAppt, newAppt); toUpdate.Add(existingAppt); updatedAppointment = true; } } if (!updatedAppointment) { toCreate.Add(newAppt); log.DebugFormat("ADDING '{0}' - Not an update", newAppt.Range); } } if (log.IsInfoEnabled) { log.InfoFormat( "AppointmentWriter for '{0}'. [{1} deleted, {2} updated, {3} new]", user.Email, toDelete.Count, toUpdate.Count, toCreate.Count); } exchangeGateway.Appointments.DeleteAppointments(user, toDelete); // TODO: Updates are not currently published // exchangeGateway.Appointments.UpdateAppointments( user, updateAppointments ); exchangeGateway.Appointments.WriteAppointments(user, toCreate); }
/// <summary> /// Create a new Free Busy Collection /// </summary> public FreeBusyCollection() : base() { this.appointments = new AppointmentCollection(); }