/// <summary> /// Checks the server for new, updated and deleted items and returns them. /// </summary> /// <returns>A collection with all new, updated and deleted items on serverside.</returns> public AppointmentSyncCollection GetUpdates() { AppointmentSyncCollection returnCollection = new AppointmentSyncCollection(); List <CalDavElement> responseListCalDav = GetAllItemsFromServer(); //Check for new and updated items foreach (var remoteitem in responseListCalDav) { String foundETag = _localStorage.FindEtag(remoteitem.Guid); if (foundETag == null) { returnCollection.AddList.Add(CalDavElementToAppointmentItemConverter.Convert(remoteitem)); _localStorage.WriteEntry(remoteitem.Guid, remoteitem.ETag, remoteitem.Url); } else if (foundETag != remoteitem.ETag) { returnCollection.UpdateList.Add(CalDavElementToAppointmentItemConverter.Convert(remoteitem)); _localStorage.EditETag(remoteitem.Guid, remoteitem.ETag); } } ; //Check for deleted items Boolean deleted; OutlookAppointment deletedAppointment = new OutlookAppointment(); List <String> guidsToDelete = new List <String>(); foreach (var localitem in _localStorage.GetAll()) { deleted = true; foreach (var remoteitem in responseListCalDav) { if (remoteitem.Guid.Equals(localitem.Key)) { deleted = false; } } if (deleted) { deletedAppointment.SyncID = localitem.Key; returnCollection.DeleteList.Add(deletedAppointment); guidsToDelete.Add(localitem.Key); } } foreach (var item in guidsToDelete) { _localStorage.DeleteEntry(item); } return(returnCollection); }
/// <summary> /// Returns an AppointmentSyncCollection of the full calendar /// </summary> /// <returns>AppointmentSyncCollection, with all appointments as "add"</returns> public AppointmentSyncCollection GetInitialSync() { if (_customCalendar == null) { return(null); } AppointmentSyncCollection syncCollection = GetUpdates(DateTime.MinValue); // this is a request for a full inital sync, so there are no "updates" or "delete", but only "adds" syncCollection.AddList.AddRange(syncCollection.UpdateList); syncCollection.UpdateList.Clear(); syncCollection.DeleteList.Clear(); return(syncCollection); }
/// <summary> /// Drops an existing database, creates a new one, fetches all ics elements from server, /// writes their etags, uids and urls to the database, converts the ics to Outlook Appointments /// and returns them. /// </summary> /// <returns>A collection of all appointments on serverside.</returns> public AppointmentSyncCollection GetInitialSync() { _localStorage.RebuildDatabase(); AppointmentSyncCollection responseList = new AppointmentSyncCollection(); List <CalDavElement> responseListCalDav = GetAllItemsFromServer(); responseListCalDav.ForEach(delegate(CalDavElement element) { _localStorage.WriteEntry(element.Guid, element.ETag, element.Url); responseList.AddList.Add(CalDavElementToAppointmentItemConverter.Convert(element)); }); return(responseList); }
/// <summary> /// Applies all the updates to the calendar /// </summary> /// <param name="syncItems"></param> /// <returns>null</returns> public Dictionary <string, string> DoUpdates(AppointmentSyncCollection syncItems) { if (syncItems == null || _customCalendar == null) { return(null); } // add new appointments if (syncItems.AddList != null) { foreach (OutlookAppointment appointment in syncItems.AddList) { CreateAppointment(appointment); } } // update appointments if (syncItems.UpdateList != null) { foreach (OutlookAppointment appointment in syncItems.UpdateList) { UpdateAppointment(appointment); } } // delete appointments if (syncItems.DeleteList != null) { foreach (OutlookAppointment appointment in syncItems.DeleteList) { DeleteAppointment(appointment); } } Debug.WriteLine("CalendarHandler (DoUpdates): Added: " + syncItems.AddList.Count + " | Updated: " + syncItems.UpdateList.Count + " | Deleted: " + syncItems.DeleteList.Count); return(null); }
/// <summary> /// Returns a AppointmentSyncCollection, with all updates since the specified timestamp /// </summary> /// <param name="timestamp"></param> /// <returns></returns> private AppointmentSyncCollection GetUpdates(DateTime timestamp) { if (_customCalendar == null) { return(null); } AppointmentSyncCollection syncCollection = new AppointmentSyncCollection(); // Debug.WriteLine("CalendarHandler: TimeStamp -> " + timestamp); foreach (Outlook.AppointmentItem item in _customCalendar.Items) { Boolean updatedBySync = false; //Debug.WriteLine("CalendarHandler: Item (" + item.Subject + ") LastModificationTime -> " + item.LastModificationTime); // if the date from the SYNC_UPDATE is newer or as the LastModificationTime, the item was not updated by the user if (item.ItemProperties[ITEM_PROPERTY_SYNC_UPDATE] != null && DateTime.Parse(item.ItemProperties[ITEM_PROPERTY_SYNC_UPDATE].Value) >= item.LastModificationTime) { updatedBySync = true; } //Debug.WriteLine("CalendarHandler: Item (" + item.Subject + ") SyncUpdate -> " + syncUpdate); //Debug.WriteLine("CalendarHandler: Item (" + item.Subject + ") wasUpdatedBySync -> " + wasUpdatedBySync); if (item.LastModificationTime >= timestamp && !updatedBySync) { // ADDING // if SyncID does not exist, it is not yet synced and needs to be added to the other calendar if (item.ItemProperties[ITEM_PROPERTY_SYNC_ID] == null) { syncCollection.AddList.Add(new OutlookAppointment(item)); if (item.ItemProperties[ITEM_PROPERTY_GLOBAL_A_ID] == null) { // GAI (GlobalAppointmentID) needs to be added as item property, otherwise it cannot be found later Outlook.ItemProperty newProp = item.ItemProperties.Add(ITEM_PROPERTY_GLOBAL_A_ID, Outlook.OlUserPropertyType.olText); item.Save(); newProp.Value = item.GlobalAppointmentID; item.Save(); } } // UPDATING // if a SyncID exist, it is already synced and needs to be updated in the other calendar else { syncCollection.UpdateList.Add(new OutlookAppointment(item)); } } } // DELETING foreach (String syncID in GetAppointmentsForDeleting()) { OutlookAppointment item = new OutlookAppointment(); item.SyncID = syncID; syncCollection.DeleteList.Add(item); } Debug.WriteLine("CalendarHandler (GetUpdates): Added: " + syncCollection.AddList.Count + " | Updated: " + syncCollection.UpdateList.Count + " | Deleted: " + syncCollection.DeleteList.Count); ResetDeleteStorage(); SetSyncTime(DateTime.Now); return(syncCollection); }
/// <summary> /// Writes the items added, updated and deleted in Outlook back to the server. /// </summary> /// <param name="syncItems">A collection with all new, updated and deleted items on Outlook side.</param> /// <returns>The servers SyncIDs for items newly added in Outlook as dictionary.</returns> public Dictionary <string, string> DoUpdates(AppointmentSyncCollection syncItems) { Dictionary <string, string> newSyncIds = new Dictionary <string, string>(); //Delete items from server foreach (var deleteItem in syncItems.DeleteList) { if (_localStorage.FindUrl(deleteItem.SyncID) != null && !_localStorage.FindUrl(deleteItem.SyncID).Equals("")) { try { this.QueryCaldavServer("DELETE", new WebHeaderCollection(), "", null, _localStorage.FindUrl(deleteItem.SyncID)); } catch (WebException e) { Debug.WriteLine(e.Message); MessageBox.Show("The following error occurred: " + e.Message); } _localStorage.DeleteEntry(deleteItem.SyncID); } } //Update items on server foreach (var updateItem in syncItems.UpdateList) { if (_localStorage.FindUrl(updateItem.SyncID) != null && !_localStorage.FindUrl(updateItem.SyncID).Equals("")) { try { this.QueryCaldavServer("PUT", new WebHeaderCollection(), AppointmentItemXmlParser.Parse(updateItem), "text/calendar", _localStorage.FindUrl(updateItem.SyncID)); } catch (WebException e) { Debug.WriteLine(e.Message); MessageBox.Show("The following error occurred: " + e.Message); } _localStorage.EditETag(updateItem.SyncID, GetSingleItemFromServer(_localStorage.FindUrl(updateItem.SyncID)).ETag); } } //Add items to server foreach (var addItem in syncItems.AddList) { String guid = System.Guid.NewGuid().ToString(); addItem.SyncID = guid; newSyncIds.Add(addItem.GlobalAppointmentID, guid); String url = guid + ".ics"; try { this.QueryCaldavServer("PUT", new WebHeaderCollection(), AppointmentItemXmlParser.Parse(addItem), "text/calendar", url); string url_corrected = CheckSlashAtEnd(new Uri(calendarUrl).PathAndQuery) + url; CalDavElement newElement = GetSingleItemFromServer(url_corrected); _localStorage.WriteEntry(guid, newElement.ETag, newElement.Url); } catch (WebException e) { Debug.WriteLine(e.Message); MessageBox.Show("The following error occurred: " + e.Message); } } //Return the dictionary with the new SyncIDs return(newSyncIds); }
/// <summary> /// Synchronizes both calendars. /// </summary> private void Synchronize() { Debug.WriteLine("----------------------------------"); Debug.WriteLine("SyncService: Started Synchronize(" + DateTime.Now + ")"); // checking if another sync is already running if (!_isRunning) { _isRunning = true; //Get changes since last snyc AppointmentSyncCollection _externalGetUpdates = _syncExternal.GetUpdates(); AppointmentSyncCollection _outlookGetUpdates = _syncOutlook.GetUpdates(); //Find updating conflicts and solve them List <OutlookAppointment> deleteFromOutlookCollection = new List <OutlookAppointment>(); List <OutlookAppointment> deleteFromExternalCollection = new List <OutlookAppointment>(); if (_outlookGetUpdates.UpdateList.Count > 0 && _externalGetUpdates.UpdateList.Count > 0) { foreach (var itemOutlook in _outlookGetUpdates.UpdateList) { foreach (var itemExternal in _externalGetUpdates.UpdateList) { if (itemOutlook.SyncID.Equals(itemExternal.SyncID)) { int comparison = DateTime.Compare(itemOutlook.LastModificationTime, itemExternal.LastModificationTime); //Item was edited in Outlook prior to the external source or at the same time --> external wins if (comparison <= 0) { deleteFromOutlookCollection.Add(itemOutlook); } //Item was edited in Outlook after last modification on external source --> outlook wins else { deleteFromExternalCollection.Add(itemExternal); } } } } foreach (var item in deleteFromExternalCollection) { _externalGetUpdates.UpdateList.Remove(item); } foreach (var item in deleteFromOutlookCollection) { _outlookGetUpdates.UpdateList.Remove(item); } } //Write the changes to the destinations _syncOutlook.DoUpdates(_externalGetUpdates); //Debug.WriteLine("SyncService: Processed _syncOutlook.DoUpdates(_externalGetUpdates)"); _syncOutlook.UpdateSyncIDs(_syncExternal.DoUpdates(_outlookGetUpdates)); //Debug.WriteLine("SyncService: Processed _syncOutlook.UpdateSyncIDs()"); _isRunning = false; } else { Debug.WriteLine("SyncService: Synchronize() not processed, it is already running"); } Debug.WriteLine("SyncService: Finished Synchronize()"); }