public ConflictResolution Resolve(ContactMatch match, bool isNewMatch) { string name = match.ToString(); if (isNewMatch) { _form.messageLabel.Text = "This is the first time these Outlook and Google Contacts \"" + name + "\" are synced. Choose which you would like to keep."; _form.skip.Text = "Keep both"; } else { _form.messageLabel.Text = "Both the Outlook Contact and the Google Contact \"" + name + "\" have been changed. Choose which you would like to keep."; } _form.OutlookItemTextBox.Text = string.Empty; _form.GoogleItemTextBox.Text = string.Empty; if (match.OutlookContact != null) { Microsoft.Office.Interop.Outlook.ContactItem item = match.OutlookContact.GetOriginalItemFromOutlook(); try { _form.OutlookItemTextBox.Text = ContactMatch.GetSummary(item); } finally { if (item != null) { System.Runtime.InteropServices.Marshal.ReleaseComObject(item); item = null; } } } if (match.GoogleContact != null) _form.GoogleItemTextBox.Text = ContactMatch.GetSummary(match.GoogleContact); return Resolve(); }
public static void SyncContact(ContactMatch match, Synchronizer sync) { Outlook.ContactItem outlookContactItem = match.OutlookContact != null ? match.OutlookContact.GetOriginalItemFromOutlook() : null; try { if (match.GoogleContact == null && match.OutlookContact != null) { //no google contact string googleContactId = match.OutlookContact.UserProperties.GoogleContactId; if (!string.IsNullOrEmpty(googleContactId)) { //Redundant check if exist, but in case an error occurred in MatchContacts Contact matchingGoogleContact = sync.GetGoogleContactById(googleContactId); if (matchingGoogleContact == null) { if (sync.SyncOption == SyncOption.OutlookToGoogleOnly || !sync.SyncDelete) return; else if (!sync.PromptDelete) sync.DeleteOutlookResolution = DeleteResolution.DeleteOutlookAlways; else if (sync.DeleteOutlookResolution != DeleteResolution.DeleteOutlookAlways && sync.DeleteOutlookResolution != DeleteResolution.KeepOutlookAlways) { var r = new ConflictResolver(); sync.DeleteOutlookResolution = r.ResolveDelete(match.OutlookContact); } switch (sync.DeleteOutlookResolution) { case DeleteResolution.KeepOutlook: case DeleteResolution.KeepOutlookAlways: ContactPropertiesUtils.ResetOutlookGoogleContactId(sync, outlookContactItem); break; case DeleteResolution.DeleteOutlook: case DeleteResolution.DeleteOutlookAlways: //Avoid recreating a GoogleContact already existing //==> Delete this outlookContact instead if previous match existed but no match exists anymore return; default: throw new ApplicationException("Cancelled"); } } } if (sync.SyncOption == SyncOption.GoogleToOutlookOnly) { sync.SkippedCount++; Logger.Log(string.Format("Outlook Contact not added to Google, because of SyncOption " + sync.SyncOption.ToString() + ": {0}", match.OutlookContact.FileAs), EventType.Information); return; } //create a Google contact from Outlook contact match.GoogleContact = new Contact(); sync.UpdateContact(outlookContactItem, match.GoogleContact); } else if (match.OutlookContact == null && match.GoogleContact != null) { // no outlook contact string outlookId = ContactPropertiesUtils.GetGoogleOutlookContactId(sync.SyncProfile, match.GoogleContact); if (outlookId != null) { if (sync.SyncOption == SyncOption.GoogleToOutlookOnly || !sync.SyncDelete) return; else if (!sync.PromptDelete) sync.DeleteGoogleResolution = DeleteResolution.DeleteGoogleAlways; else if (sync.DeleteGoogleResolution != DeleteResolution.DeleteGoogleAlways && sync.DeleteGoogleResolution != DeleteResolution.KeepGoogleAlways) { var r = new ConflictResolver(); sync.DeleteGoogleResolution = r.ResolveDelete(match.GoogleContact); } switch (sync.DeleteGoogleResolution) { case DeleteResolution.KeepGoogle: case DeleteResolution.KeepGoogleAlways: ContactPropertiesUtils.ResetGoogleOutlookContactId(sync.SyncProfile, match.GoogleContact); break; case DeleteResolution.DeleteGoogle: case DeleteResolution.DeleteGoogleAlways: //Avoid recreating a OutlookContact already existing //==> Delete this googleContact instead if previous match existed but no match exists anymore return; default: throw new ApplicationException("Cancelled"); } } if (sync.SyncOption == SyncOption.OutlookToGoogleOnly) { sync.SkippedCount++; Logger.Log(string.Format("Google Contact not added to Outlook, because of SyncOption " + sync.SyncOption.ToString() + ": {0}", match.GoogleContact.Title), EventType.Information); return; } //create a Outlook contact from Google contact outlookContactItem = Synchronizer.CreateOutlookContactItem(Synchronizer.SyncContactsFolder); sync.UpdateContact(match.GoogleContact, outlookContactItem); match.OutlookContact = new OutlookContactInfo(outlookContactItem, sync); } else if (match.OutlookContact != null && match.GoogleContact != null) { //merge contact details //determine if this contact pair were synchronized //DateTime? lastUpdated = GetOutlookPropertyValueDateTime(match.OutlookContact, sync.OutlookPropertyNameUpdated); DateTime? lastSynced = match.OutlookContact.UserProperties.LastSync; if (lastSynced.HasValue) { //contact pair was syncronysed before. //determine if google contact was updated since last sync //lastSynced is stored without seconds. take that into account. DateTime lastUpdatedOutlook = match.OutlookContact.LastModificationTime.AddSeconds(-match.OutlookContact.LastModificationTime.Second); DateTime lastUpdatedGoogle = match.GoogleContact.Updated.AddSeconds(-match.GoogleContact.Updated.Second); //check if both outlok and google contacts where updated sync last sync if (lastUpdatedOutlook.Subtract(lastSynced.Value).TotalSeconds > TimeTolerance && lastUpdatedGoogle.Subtract(lastSynced.Value).TotalSeconds > TimeTolerance) { //both contacts were updated. //options: 1) ignore 2) loose one based on SyncOption //throw new Exception("Both contacts were updated!"); switch (sync.SyncOption) { case SyncOption.MergeOutlookWins: case SyncOption.OutlookToGoogleOnly: //overwrite google contact Logger.Log("Outlook and Google contact have been updated, Outlook contact is overwriting Google because of SyncOption " + sync.SyncOption + ": " + match.OutlookContact.FileAs + ".", EventType.Information); sync.UpdateContact(outlookContactItem, match.GoogleContact); break; case SyncOption.MergeGoogleWins: case SyncOption.GoogleToOutlookOnly: //overwrite outlook contact Logger.Log("Outlook and Google contact have been updated, Google contact is overwriting Outlook because of SyncOption " + sync.SyncOption + ": " + match.OutlookContact.FileAs + ".", EventType.Information); sync.UpdateContact(match.GoogleContact, outlookContactItem); break; case SyncOption.MergePrompt: //promp for sync option if (sync.ConflictResolution != ConflictResolution.GoogleWinsAlways && sync.ConflictResolution != ConflictResolution.OutlookWinsAlways && sync.ConflictResolution != ConflictResolution.SkipAlways) { var r = new ConflictResolver(); sync.ConflictResolution = r.Resolve(match, false); } switch (sync.ConflictResolution) { case ConflictResolution.Skip: case ConflictResolution.SkipAlways: Logger.Log(string.Format("User skipped contact ({0}).", match.ToString()), EventType.Information); sync.SkippedCount++; break; case ConflictResolution.OutlookWins: case ConflictResolution.OutlookWinsAlways: sync.UpdateContact(outlookContactItem, match.GoogleContact); break; case ConflictResolution.GoogleWins: case ConflictResolution.GoogleWinsAlways: sync.UpdateContact(match.GoogleContact, outlookContactItem); break; default: throw new ApplicationException("Cancelled"); } break; } return; } //check if outlook contact was updated (with X second tolerance) if (sync.SyncOption != SyncOption.GoogleToOutlookOnly && (lastUpdatedOutlook.Subtract(lastSynced.Value).TotalSeconds > TimeTolerance || lastUpdatedGoogle.Subtract(lastSynced.Value).TotalSeconds > TimeTolerance && sync.SyncOption == SyncOption.OutlookToGoogleOnly ) ) { //outlook contact was changed or changed Google contact will be overwritten if (lastUpdatedGoogle.Subtract(lastSynced.Value).TotalSeconds > TimeTolerance && sync.SyncOption == SyncOption.OutlookToGoogleOnly) Logger.Log("Google contact has been updated since last sync, but Outlook contact is overwriting Google because of SyncOption " + sync.SyncOption + ": " + match.OutlookContact.FileAs + ".", EventType.Information); sync.UpdateContact(outlookContactItem, match.GoogleContact); //at the moment use outlook as "master" source of contacts - in the event of a conflict google contact will be overwritten. //TODO: control conflict resolution by SyncOption return; } //check if google contact was updated (with X second tolerance) if (sync.SyncOption != SyncOption.OutlookToGoogleOnly && (lastUpdatedGoogle.Subtract(lastSynced.Value).TotalSeconds > TimeTolerance || lastUpdatedOutlook.Subtract(lastSynced.Value).TotalSeconds > TimeTolerance && sync.SyncOption == SyncOption.GoogleToOutlookOnly ) ) { //google contact was changed or changed Outlook contact will be overwritten if (lastUpdatedOutlook.Subtract(lastSynced.Value).TotalSeconds > TimeTolerance && sync.SyncOption == SyncOption.GoogleToOutlookOnly) Logger.Log("Outlook contact has been updated since last sync, but Google contact is overwriting Outlook because of SyncOption " + sync.SyncOption + ": " + match.OutlookContact.FileAs + ".", EventType.Information); sync.UpdateContact(match.GoogleContact, outlookContactItem); } } else { //contacts were never synced. //merge contacts. switch (sync.SyncOption) { case SyncOption.MergeOutlookWins: case SyncOption.OutlookToGoogleOnly: //overwrite google contact sync.UpdateContact(outlookContactItem, match.GoogleContact); break; case SyncOption.MergeGoogleWins: case SyncOption.GoogleToOutlookOnly: //overwrite outlook contact sync.UpdateContact(match.GoogleContact, outlookContactItem); break; case SyncOption.MergePrompt: //promp for sync option if (sync.ConflictResolution != ConflictResolution.GoogleWinsAlways && sync.ConflictResolution != ConflictResolution.OutlookWinsAlways && sync.ConflictResolution != ConflictResolution.SkipAlways) { var r = new ConflictResolver(); sync.ConflictResolution = r.Resolve(match, true); } switch (sync.ConflictResolution) { case ConflictResolution.Skip: case ConflictResolution.SkipAlways: //Keep both, Google AND Outlook sync.Contacts.Add(new ContactMatch(match.OutlookContact, null)); sync.Contacts.Add(new ContactMatch(null, match.GoogleContact)); break; case ConflictResolution.OutlookWins: case ConflictResolution.OutlookWinsAlways: sync.UpdateContact(outlookContactItem, match.GoogleContact); break; case ConflictResolution.GoogleWins: case ConflictResolution.GoogleWinsAlways: sync.UpdateContact(match.GoogleContact, outlookContactItem); break; default: throw new ApplicationException("Cancelled"); } break; } } } else throw new ArgumentNullException("ContactMatch has all peers null."); } catch (ArgumentNullException e) { throw e; } catch (Exception e) { throw new Exception("Error syncing contact " + (match.OutlookContact != null ? match.OutlookContact.FileAs : match.GoogleContact.Title) + ": " + e.Message, e); } finally { if (outlookContactItem != null && match.OutlookContact != null) { match.OutlookContact.Update(outlookContactItem, sync); Marshal.ReleaseComObject(outlookContactItem); outlookContactItem = null; } } }