/// <summary>In case of items with same remote ids, some new exchange items resolved as apply to remote. /// In case there is no activity metadata, conflict resolved as apply to local.</summary> /// <param name="syncItem">Sync entity instance.</param> /// <param name="itemMetaData">Metadata instance.</param> /// <param name="localStoreId">Local storage id.</param> /// <returns>Sync conflict resoluton for sync item.</returns> public override SyncConflictResolution ResolveConflict(IRemoteItem syncItem, ItemMetadata itemMetaData, Guid localStoreId) { if (syncItem.Action == SyncAction.CreateRecurringMaster) { return(SyncConflictResolution.ApplyToLocal); } bool isActivityExists = itemMetaData.Any(item => item.SyncSchemaName == "Activity"); if (!isActivityExists) { return(SyncConflictResolution.ApplyToLocal); } if (_userConnection.GetIsFeatureEnabled("ResolveConflictsByContent")) { var appointment = syncItem as ExchangeAppointment; if (appointment.Action == SyncAction.Delete) { return(SyncConflictResolution.ApplyToRemote); } Exchange.Appointment remoteItem = appointment.Item as Exchange.Appointment; appointment.LoadItemProperties(remoteItem); string oldActivityHash = GetActivityHashFromMetadata(itemMetaData); if (!appointment.IsAppointmentChanged(remoteItem, oldActivityHash, _userConnection)) { return(SyncConflictResolution.ApplyToRemote); } } SyncConflictResolution result = base.ResolveConflict(syncItem, itemMetaData, localStoreId); return(result); }
protected override void ExecuteDirectory(string directoryPath, SearchContext context) { bool secondExists = Directory.Exists(Options.Target); if (secondExists) { _destinationPaths = new HashSet <string>(FileSystemHelpers.Comparer); } try { _isSecondToFirst = false; if (ConflictResolution == SyncConflictResolution.FirstWins && !secondExists) { CreateDirectory(Options.Target); } base.ExecuteDirectory(directoryPath, context); } finally { _isSecondToFirst = true; } if (secondExists) { _ignoredPaths = _destinationPaths; _destinationPaths = null; string secondDirectory = directoryPath; directoryPath = Options.Target; Options.Paths = ImmutableArray.Create(new PathInfo(directoryPath, PathOrigin.None)); Options.Target = secondDirectory; if (ConflictResolution == SyncConflictResolution.FirstWins) { ConflictResolution = SyncConflictResolution.SecondWins; } else if (ConflictResolution == SyncConflictResolution.SecondWins) { ConflictResolution = SyncConflictResolution.FirstWins; } base.ExecuteDirectory(directoryPath, context); } _ignoredPaths = null; }
/// <summary> /// Utility for invoking user code for conflict interceptors /// </summary> /// <param name="context">The context to pass as parameter to user code</param> /// <param name="mergedVersion">The merged version for Merge resolution</param> /// <param name="entityType">Entity type of the conflict being raised</param> /// <returns>Actual resolution picked by user</returns> internal SyncConflictResolution?InvokeConflictInterceptor(SyncConflictContext context, Type entityType, out IOfflineEntity mergedVersion) { SyncInterceptorsInfoWrapper wrapper = null; if (this.SyncInterceptors.TryGetValue(context.ScopeName, out wrapper)) { // Look for unfiltered Conflict and if that is null then look for filtered one. // Its an error to have both unfiltered and filtered ConflictInterceptor so both cannot be set. MethodInfo methodInfo = wrapper.ConflictInterceptor ?? wrapper.GetConflictInterceptor(entityType); if (methodInfo != null) { object[] inputParams = new object[] { context, null }; SyncConflictResolution resolution = (SyncConflictResolution)InvokeUserInterceptorMethod(methodInfo, OperationContext.Current.InstanceContext.GetServiceInstance(), inputParams); // Merged version is in the second parameter which is passed by reference. Look it up mergedVersion = (IOfflineEntity)inputParams[1]; return(resolution); } } mergedVersion = null; return(null); }
/// <summary> /// Called to add a Sync conflict item /// </summary> /// <param name="winningEntry">the winning entity</param> /// <param name="winningEntryTempId">the winning entity's tempId</param> /// <param name="losingEntry">The losing entity</param> /// <param name="losingEntryTempId">The losing entity's tempId</param> /// <param name="resolution">The conflict resolution aplied by the server</param> public virtual void AddConflictItem(IOfflineEntity winningEntry, string winningEntryTempId, IOfflineEntity losingEntry, string losingEntryTempId, SyncConflictResolution resolution) { if (winningEntry == null) { throw new ArgumentNullException("winningEntry"); } if (losingEntry == null) { throw new ArgumentNullException("losingEntry"); } WriteItemInternal(winningEntry, winningEntryTempId, losingEntry /*conflicting*/, losingEntryTempId, resolution.ToString() /*desc*/, true /*isconflict*/, false /*emitMetadataOnly*/); }
/// <summary> /// Called to add a Sync conflict item /// </summary> /// <param name="winningEntry">the winning entity</param> /// <param name="winningEntryTempId">the winning entity's tempId</param> /// <param name="losingEntry">The losing entity</param> /// <param name="losingEntryTempId">The losing entity's tempId</param> /// <param name="resolution">The conflict resolution aplied by the server</param> public virtual void AddConflictItem(IOfflineEntity winningEntry, string winningEntryTempId, IOfflineEntity losingEntry, string losingEntryTempId, SyncConflictResolution resolution) { if (winningEntry == null) { throw new ArgumentNullException("winningEntry"); } if (losingEntry == null) { throw new ArgumentNullException("losingEntry"); } WriteItemInternal(winningEntry, winningEntryTempId, losingEntry/*conflicting*/, losingEntryTempId, resolution.ToString() /*desc*/, true/*isconflict*/, false/*emitMetadataOnly*/); }