/// <summary> /// Normalizes content by using lookup tables and removes unneeded whitespace /// </summary> /// <param name="sourceClient"> /// The source client. /// </param> /// <param name="targetClient"> /// The target client. /// </param> /// <param name="baseliClient"> /// The baseline client. /// </param> /// <param name="sourceStorePath"> /// The source storage path. /// </param> /// <param name="targetStorePath"> /// The target storage path. /// </param> /// <param name="baselineStorePath"> /// The baseline storage path. /// </param> /// <param name="commandParameter"> /// The command parameter. /// </param> /// <returns> /// True if the response from the <see cref="SyncComponent.UiProvider"/> is "continue" /// </returns> public bool ExecuteCommand( IClientBase sourceClient, IClientBase targetClient, IClientBase baseliClient, string sourceStorePath, string targetStorePath, string baselineStorePath, string commandParameter) { if (targetClient == null) { throw new InvalidOperationException("item.targetClient is null"); } if (sourceClient == null) { throw new InvalidOperationException("item.sourceClient is null"); } var elements = sourceClient.GetAll(sourceStorePath); foreach (var element in elements) { this.LogProcessingEvent(element, "normalizing ... "); element.NormalizeContent(); } targetClient.WriteRange(elements, targetStorePath); return(true); }
/// <summary> /// Match using the profile identifiers - each profile identifier is expected to assigned to a unique entity /// </summary> /// <param name="sourceClient"> /// The source client. /// </param> /// <param name="targetClient"> /// The target client. /// </param> /// <param name="baseliClient"> /// The baseline client. /// </param> /// <param name="sourceStorePath"> /// The source storage path. /// </param> /// <param name="targetStorePath"> /// The target storage path. /// </param> /// <param name="baselineStorePath"> /// The baseline storage path. /// </param> /// <param name="commandParameter"> /// The command parameter. /// </param> /// <returns> /// True if the response from the <see cref="SyncComponent.UiProvider"/> is "continue" /// </returns> public bool ExecuteCommand( IClientBase sourceClient, IClientBase targetClient, IClientBase baseliClient, string sourceStorePath, string targetStorePath, string baselineStorePath, string commandParameter) { if (targetClient == null) { throw new InvalidOperationException("item.targetClient is null"); } if (sourceClient == null) { throw new InvalidOperationException("item.sourceClient is null"); } if (sourceStorePath == null) { throw new InvalidOperationException("sourceStorePath is null"); } if (targetStorePath == null) { throw new InvalidOperationException("targetStorePath is null"); } var baseline = baseliClient.GetAll(baselineStorePath); targetClient.WriteRange( MatchThisByProfileId(sourceClient.GetAll(sourceStorePath), baseline), targetStorePath); return(true); }
/// <summary> /// This command does lookup contact ralations for a List of <see cref="StdContact"/>. The connector that does read the /// data need to be specified inside the <paramref name="commandParameter"/> and must implement the interface <see cref="IExtendedReader"/>. /// Only contacts that can be mapped to internal Ids using the <paramref name="baseliClient"/> will be collected - no additional /// data is collected (there's no profile lookup for the unknown contacts). /// </summary> /// <param name="sourceClient"> The source client provides a set of <see cref="StdContact"/> entries for that the contact relations should be read. </param> /// <param name="targetClient"> The target client will write the processed list of <see cref="StdContact"/> that now does contain the contact relations. </param> /// <param name="baseliClient"> The baseline client provides lookup data for determine valid translations for the relation ids read from the connector specified in the <paramref name="commandParameter"/>. </param> /// <param name="sourceStorePath"> The source storage path. </param> /// <param name="targetStorePath"> The target storage path. </param> /// <param name="baselineStorePath"> The baseline storage path. </param> /// <param name="commandParameter"> The connector to the contact relations (must support <see cref="IExtendedReader"/>). </param> /// <returns> True if the response from the <see cref="SyncComponent.UiProvider"/> is "continue" </returns> public bool ExecuteCommand( IClientBase sourceClient, IClientBase targetClient, IClientBase baseliClient, string sourceStorePath, string targetStorePath, string baselineStorePath, string commandParameter) { if (targetClient == null) { throw new InvalidOperationException("item.targetClient is null"); } if (sourceClient == null) { throw new InvalidOperationException("item.sourceClient is null"); } if (baseliClient == null) { throw new InvalidOperationException("item.baseliClient is null"); } var extendedClient = sourceClient as IExtendedReader; if (extendedClient == null) { throw new InvalidOperationException("sourceClient is null or not an IExtendedReader"); } ((SyncComponent)extendedClient).ProcessingEvent += this.LogProcessingEvent; // get the baseline var baseline = baseliClient.GetAll(baselineStorePath); // get all source elements var elements = targetClient.GetAll(targetStorePath); // add the matching profile ids from the baseline as StdContact - // .ToContacts().ToStdElement() will convert each MatchingEntry // of the list into a StdContact elements.MergeHighEvidence(baseline.ToStdContacts().ToStdElements()); // fill the extended contact information var matchEntities = baseline.ToMatchingEntries(); extendedClient.FillAllContacts(elements, matchEntities); elements.ForEach(e => extendedClient.FillContacts(e, matchEntities)); // copy to the target connector targetClient.AddRange(elements, targetStorePath); baseliClient.WriteRange(baseline, baselineStorePath); ((SyncComponent)extendedClient).ProcessingEvent -= this.LogProcessingEvent; return(true); }
/// <summary> /// Detects merge conflicts and resolves them using user interaction /// </summary> /// <param name="sourceClient"> /// The source client. /// </param> /// <param name="targetClient"> /// The target client. /// </param> /// <param name="baseliClient"> /// The baseline client. /// </param> /// <param name="sourceStorePath"> /// The source storage path. /// </param> /// <param name="targetStorePath"> /// The target storage path. /// </param> /// <param name="baselineStorePath"> /// The baseline storage path. /// </param> /// <param name="commandParameter"> /// The command parameter. /// </param> /// <returns> /// True if the response from the <see cref="SyncComponent.UiProvider"/> is "continue" /// </returns> public bool ExecuteCommand( IClientBase sourceClient, IClientBase targetClient, IClientBase baseliClient, string sourceStorePath, string targetStorePath, string baselineStorePath, string commandParameter) { if (targetClient == null) { throw new InvalidOperationException("item.targetClient is null"); } if (sourceClient == null) { throw new InvalidOperationException("item.sourceClient is null"); } if (sourceStorePath == null) { throw new InvalidOperationException("sourceStorePath is null"); } if (targetStorePath == null) { throw new InvalidOperationException("targetStorePath is null"); } var targetList = targetClient.GetAll(targetStorePath); var sourceList = sourceClient.GetAll(sourceStorePath); var type = targetList.Count > 0 ? targetList[0].GetType() : sourceList.Count > 0 ? sourceList[0].GetType() : typeof(StdElement); var mergeResultList = ((IUiSyncInteraction)this.UiProvider).PerformAttributeMerge( SyncTools.DetectConflicts( SyncTools.BuildConflictTestContainerList( sourceList, targetList, (baseliClient == null) ? null : baseliClient.GetAll(baselineStorePath), type), true), targetList); // only write to target if we did get a merge result if (mergeResultList != null) { targetClient.WriteRange(mergeResultList, targetStorePath); } return(true); }
/// <summary> /// Match internally without user interaction by comparing the email addresses /// </summary> /// <param name="sourceClient"> /// The source client. /// </param> /// <param name="targetClient"> /// The target client. /// </param> /// <param name="baseliClient"> /// The baseline client. /// </param> /// <param name="sourceStorePath"> /// The source storage path. /// </param> /// <param name="targetStorePath"> /// The target storage path. /// </param> /// <param name="baselineStorePath"> /// The baseline storage path. /// </param> /// <param name="commandParameter"> /// The command parameter. /// </param> /// <returns> /// returns always true /// </returns> public bool ExecuteCommand( IClientBase sourceClient, IClientBase targetClient, IClientBase baseliClient, string sourceStorePath, string targetStorePath, string baselineStorePath, string commandParameter) { if (targetClient == null) { throw new InvalidOperationException("targetClient is null"); } if (sourceClient == null) { throw new InvalidOperationException("sourceClient is null"); } if (sourceStorePath == null) { throw new InvalidOperationException("sourceStorePath is null"); } if (targetStorePath == null) { throw new InvalidOperationException("targetStorePath is null"); } targetClient.WriteRange( this.MatchThisByEMail( sourceClient.GetAll(sourceStorePath).ToStdContacts(), targetClient.GetAll(targetStorePath).ToStdContacts()), targetStorePath); return(true); }
/// <summary> /// Merge properties of entities from source to target if there is a very high propability that the /// source property is "better" than the target property /// </summary> /// <param name="sourceClient"> /// The source client. /// </param> /// <param name="targetClient"> /// The target client. /// </param> /// <param name="baseliClient"> /// The baseline client. /// </param> /// <param name="sourceStorePath"> /// The source storage path. /// </param> /// <param name="targetStorePath"> /// The target storage path. /// </param> /// <param name="baselineStorePath"> /// The baseline storage path. /// </param> /// <param name="commandParameter"> /// The command parameter. /// </param> /// <returns> /// True if the response from the <see cref="SyncComponent.UiProvider"/> is "continue" /// </returns> public bool ExecuteCommand( IClientBase sourceClient, IClientBase targetClient, IClientBase baseliClient, string sourceStorePath, string targetStorePath, string baselineStorePath, string commandParameter) { if (targetClient == null) { throw new InvalidOperationException("item.targetClient is null"); } if (sourceClient == null) { throw new InvalidOperationException("item.sourceClient is null"); } targetClient.WriteRange( targetClient.GetAll(targetStorePath).MergeHighEvidence(sourceClient.GetAll(sourceStorePath)), targetStorePath); return(true); }
/// <summary> /// Opens the matching window and matches using a baseline client /// </summary> /// <param name="sourceClient"> /// The source client. /// </param> /// <param name="targetClient"> /// The target client. /// </param> /// <param name="baseliClient"> /// The baseline client. /// </param> /// <param name="sourceStorePath"> /// The source storage path. /// </param> /// <param name="targetStorePath"> /// The target storage path. /// </param> /// <param name="baselineStorePath"> /// The baseline storage path. /// </param> /// <param name="commandParameter"> /// The command parameter. /// </param> /// <returns> /// True if the response from the <see cref="SyncComponent.UiProvider"/> is "continue" /// </returns> public bool ExecuteCommand( IClientBase sourceClient, IClientBase targetClient, IClientBase baseliClient, string sourceStorePath, string targetStorePath, string baselineStorePath, string commandParameter) { CheckParameters( targetClient, sourceClient, baseliClient, baselineStorePath, sourceStorePath, targetStorePath); var backupConnector = targetClient as IBackupStorage; if (backupConnector != null) { backupConnector.BackupStorage(targetStorePath); } // todo: split the command parameter in oder to specify whether to add orphaned source entries or skip them. var sourceTypeAttributes = sourceClient.GetType().GetCustomAttributes( typeof(ConnectorDescriptionAttribute), false); var identifierToUse = (!string.IsNullOrEmpty(commandParameter)) ? (ProfileIdentifierType) Enum.Parse(typeof(ProfileIdentifierType), commandParameter, true) : (sourceTypeAttributes != null && sourceTypeAttributes.Length > 0) ? ((ConnectorDescriptionAttribute)sourceTypeAttributes[0]). MatchingIdentifier : ProfileIdentifierType.Default; var targetMatchList = targetClient.GetAll(targetStorePath); var sourceMatchList = sourceClient.GetAll(sourceStorePath); var matchResultList = ((IUiSyncInteraction)this.UiProvider).PerformEntityMerge( sourceMatchList, targetMatchList, baseliClient.GetAll(baselineStorePath), identifierToUse); // only write to target if we did get a merge result if (targetMatchList != null && matchResultList != null) { targetClient.WriteRange(targetMatchList, targetStorePath); } // only write to target if we did get a merge result if (matchResultList != null) { var sourceContactList = sourceMatchList.ToStdContacts(); var matchingEntryList = matchResultList.ToMatchingEntries(); // Check for new (not matched) contacts and generate new matching entries for such new entries. var orphanSource = from x in sourceContactList join matchEntry in matchingEntryList on x.ExternalIdentifier equals matchEntry.ProfileId into matchGroup from y in matchGroup.DefaultIfEmpty() where y == null && !string.IsNullOrEmpty(x.ExternalIdentifier.GetProfileId(identifierToUse)) select new MatchingEntry { Id = x.Id, ProfileId = x.ExternalIdentifier }; // add all new contacts matching entries to the base line orphanSource.ForEach(matchResultList.Add); // write baseline to base line connector baseliClient.WriteRange(matchResultList, baselineStorePath); } return(true); }