private ConflictResolutionResult ResolveByUpdateConversionHisotry(MigrationConflict conflict, ConflictResolutionRule rule, out List <MigrationAction> actions)
        {
            actions = null;
            var unresolvedRslt = new ConflictResolutionResult(false, ConflictResolutionType.Other);

            string tgtItemId    = rule.DataFieldDictionary[HistoryNotFoundUpdateConversionHistoryAction.DATAKEY_TARGET_ITEM_ID];
            string srcRevRanges = rule.DataFieldDictionary[HistoryNotFoundUpdateConversionHistoryAction.DATAKEY_SOURCE_REVISION_RANGES];
            string tgtRevRanges = rule.DataFieldDictionary[HistoryNotFoundUpdateConversionHistoryAction.DATAKEY_TARGET_REVISION_RANGES];

            int[] srcRevs;
            int[] tgtRevs;
            if (string.IsNullOrEmpty(tgtItemId) ||
                !IntegerRange.TryParseRangeString(srcRevRanges, out srcRevs) ||
                !IntegerRange.TryParseRangeString(srcRevRanges, out tgtRevs) ||
                srcRevs == null || srcRevs.Length == 0 || tgtRevs == null || tgtRevs.Length == 0 || srcRevs.Length != tgtRevs.Length)
            {
                return(unresolvedRslt);
            }

            WorkItemHistoryNotFoundConflictType conflictType = conflict.ConflictType as WorkItemHistoryNotFoundConflictType;

            Debug.Assert(null != conflictType, "conflictType is null");

            WorkItemHistoryNotFoundConflictTypeDetails dtls = conflictType.GetConflictDetails(conflict);

            ConversionResult convRslt = new ConversionResult(dtls.SourceMigrationSourceId, dtls.TargetMigrationSourceId);

            convRslt.ChangeId           = HistoryNotFoundResolutionChangeId;
            convRslt.ContinueProcessing = true;

            for (int i = 0; i < srcRevs.Length; ++i)
            {
                convRslt.ItemConversionHistory.Add(new ItemConversionHistory(dtls.SourceWorkItemID, srcRevs[i].ToString(), tgtItemId, tgtRevs[i].ToString()));
            }

            int  sessionRunId            = 0;
            Guid sourceMigrationSourceId = Guid.Empty;

            using (RuntimeEntityModel context = RuntimeEntityModel.CreateInstance())
            {
                long actionInternalId = conflict.ConflictedChangeAction.ActionId;
                var  actionQuery      = context.RTChangeActionSet.Where(a => a.ChangeActionId == actionInternalId);
                if (actionQuery.Count() == 0)
                {
                    return(unresolvedRslt);
                }

                RTChangeAction action = actionQuery.First();
                action.ChangeGroupReference.Load();
                action.ChangeGroup.SessionRunReference.Load();
                sessionRunId = action.ChangeGroup.SessionRun.Id;

                sourceMigrationSourceId = action.ChangeGroup.SourceUniqueId;
            }

            convRslt.Save(sessionRunId, sourceMigrationSourceId);

            return(new ConflictResolutionResult(true, ConflictResolutionType.Other));
        }
        /// <summary>
        /// Determines whether a rule can handles the subject conflict.
        /// </summary>
        /// <param name="conflict">The conflict to be resolved</param>
        /// <param name="rule">The candidate rule</param>
        /// <returns></returns>
        public bool CanResolve(MigrationConflict conflict, ConflictResolutionRule rule)
        {
            if (conflict.ConflictedChangeAction == null ||
                !ConflictTypeHandled.ScopeInterpreter.IsInScope(conflict.ScopeHint, rule.ApplicabilityScope))
            {
                return(false);
            }

            if (rule.ActionRefNameGuid.Equals(new HistoryNotFoundSubmitMissingChangesAction().ReferenceName))
            {
                if (SessionGroupIsRunning(conflict))
                {
                    // auto submitting missiong change action requires the session to be interrupted
                    return(false);
                }
            }

            if (rule.ActionRefNameGuid.Equals(new HistoryNotFoundUpdateConversionHistoryAction().ReferenceName))
            {
                // todo: check if session is running

                string srcItemId    = rule.DataFieldDictionary[HistoryNotFoundUpdateConversionHistoryAction.DATAKEY_SOURCE_ITEM_ID];
                string tgtItemId    = rule.DataFieldDictionary[HistoryNotFoundUpdateConversionHistoryAction.DATAKEY_TARGET_ITEM_ID];
                string srcRevRanges = rule.DataFieldDictionary[HistoryNotFoundUpdateConversionHistoryAction.DATAKEY_SOURCE_REVISION_RANGES];
                string tgtRevRanges = rule.DataFieldDictionary[HistoryNotFoundUpdateConversionHistoryAction.DATAKEY_TARGET_REVISION_RANGES];

                if (string.IsNullOrEmpty(srcItemId) || string.IsNullOrEmpty(tgtItemId))
                {
                    return(false);
                }

                int[] srcRevs;
                int[] tgtRevs;
                if (!IntegerRange.TryParseRangeString(srcRevRanges, out srcRevs) ||
                    !IntegerRange.TryParseRangeString(srcRevRanges, out tgtRevs))
                {
                    return(false);
                }

                if (srcRevs == null || srcRevs.Length == 0 || tgtRevs == null || tgtRevs.Length == 0 || srcRevs.Length != tgtRevs.Length)
                {
                    return(false);
                }
            }

            return(true);
        }
        private ConflictResolutionResult ResolveBySubmitMissingChanges(
            IServiceContainer serviceContainer,
            MigrationConflict conflict,
            ConflictResolutionRule rule,
            out List <MigrationAction> actions)
        {
            actions = null;
            var retVal = new ConflictResolutionResult(false, ConflictResolutionType.Other);

            WITTranslationService translationService = serviceContainer.GetService(typeof(ITranslationService)) as WITTranslationService;

            Debug.Assert(null != translationService, "translationService is not initialized or not a wit translation service");

            using (RuntimeEntityModel context = RuntimeEntityModel.CreateInstance())
            {
                RTSessionGroup rtSessionGroup = FindSessionGroupForConflictedAction(conflict, context);
                if (null == rtSessionGroup)
                {
                    return(retVal);
                }

                BM.BusinessModelManager bmm = new BM.BusinessModelManager();
                BM.Configuration        sessionGroupConfig = bmm.LoadConfiguration(rtSessionGroup.GroupUniqueId);

                // find target-side migration source config
                var  parentChangeGroup       = FindChangeGroupForConflictedAction(conflict, context);
                Guid targetMigrationSourceId = parentChangeGroup.SourceUniqueId;
                BM.MigrationSource targetMigrationSourceConfig = sessionGroupConfig.SessionGroup.MigrationSources[targetMigrationSourceId];
                if (null == targetMigrationSourceConfig)
                {
                    return(retVal);
                }

                // find source-side migration source config
                RTSession  rtSession     = FindSessionForConflictedAction(conflict, context);
                BM.Session parentSession = null;
                foreach (BM.Session s in sessionGroupConfig.SessionGroup.Sessions.Session)
                {
                    if (new Guid(s.SessionUniqueId).Equals(rtSession.SessionUniqueId))
                    {
                        parentSession = s;
                        break;
                    }
                }
                if (parentSession == null)
                {
                    return(retVal);
                }
                Guid sourceMigrationSourceId = ((new Guid(parentSession.LeftMigrationSourceUniqueId)).Equals(targetMigrationSourceId))
                    ? new Guid(parentSession.RightMigrationSourceUniqueId) : new Guid(parentSession.LeftMigrationSourceUniqueId);
                BM.MigrationSource sourceMigrationSourceConfig = sessionGroupConfig.SessionGroup.MigrationSources[sourceMigrationSourceId];
                if (null == sourceMigrationSourceConfig)
                {
                    return(retVal);
                }

                string sourceServerUrl   = sourceMigrationSourceConfig.ServerUrl;
                string sourceTeamProject = sourceMigrationSourceConfig.SourceIdentifier;
                string targetServerUrl   = targetMigrationSourceConfig.ServerUrl;
                string targetTeamProject = targetMigrationSourceConfig.SourceIdentifier;

                string srcWorkItemIdStr = TfsMigrationWorkItemStore.GetSourceWorkItemId(conflict.ConflictedChangeAction);
                Debug.Assert(!string.IsNullOrEmpty(srcWorkItemIdStr), "srcWorkItemId is null or empty");
                int srcWorkItemId;
                if (!int.TryParse(srcWorkItemIdStr, out srcWorkItemId))
                {
                    return(retVal);
                }

                string srcRevRanges    = rule.DataFieldDictionary[HistoryNotFoundSubmitMissingChangesAction.DATAKEY_REVISION_RANGE];
                int[]  sourceRevToSync = new int[0];
                if (string.IsNullOrEmpty(srcRevRanges))
                {
                    sourceRevToSync = ExtractMissingRevs(conflict.ConflictedChangeAction);
                }
                else
                {
                    if (!IntegerRange.TryParseRangeString(srcRevRanges, out sourceRevToSync))
                    {
                        return(retVal);
                    }
                }
                if (sourceRevToSync.Length == 0)
                {
                    return(retVal);
                }

                try
                {
                    // compute delta from source side
                    TfsWITAnalysisProvider analysisProvider = new TfsWITAnalysisProvider(sourceServerUrl, sourceTeamProject);
                    WorkItem sourceWorkItem = analysisProvider.GetWorkItem(srcWorkItemId);

                    Hist.MigrationAction[] sourceRevDetails = new Hist.MigrationAction[sourceRevToSync.Length];
                    for (int revIndex = 0; revIndex < sourceRevToSync.Length; ++revIndex)
                    {
                        var details = new TfsWITRecordDetails(sourceWorkItem, sourceRevToSync[revIndex]);
                        SanitizeDetails(details);
                        translationService.MapWorkItemTypeFieldValues(
                            sourceWorkItem.Id.ToString(), details.DetailsDocument, sourceMigrationSourceId);

                        TfsConstants.ChangeActionId actionId = (sourceRevToSync[revIndex] == 1 ? TfsConstants.ChangeActionId.Add : TfsConstants.ChangeActionId.Edit);
                        sourceRevDetails[revIndex] = new Hist.MigrationAction(sourceWorkItem.Id.ToString(), details, actionId);
                    }

                    // migrate to target side
                    TfsWITMigrationProvider migrationProvider = new TfsWITMigrationProvider(targetServerUrl, targetTeamProject, string.Empty);
                    Hist.ConversionResult   conversionResult  = migrationProvider.ProcessChangeGroup(sourceRevDetails);

                    // update conversion history
                    ConversionResult convRslt = new ConversionResult(sourceMigrationSourceId, targetMigrationSourceId);
                    convRslt.ChangeId           = HistoryNotFoundResolutionChangeId;
                    convRslt.ContinueProcessing = true;

                    foreach (var itemConvHist in conversionResult.ItemConversionHistory)
                    {
                        convRslt.ItemConversionHistory.Add(new ItemConversionHistory(
                                                               itemConvHist.SourceItemId, itemConvHist.SourceItemVersion, itemConvHist.TargetItemId, itemConvHist.TargetItemVersion));
                    }

                    parentChangeGroup.SessionRunReference.Load();
                    int sessionRunId = parentChangeGroup.SessionRun.Id;
                    convRslt.Save(sessionRunId, sourceMigrationSourceId);
                }
                catch (Exception ex)
                {
                    TraceManager.TraceException(ex);
                    retVal.Comment = ex.ToString();
                    return(retVal);
                }
            }

            retVal.Resolved = true;
            return(retVal);
        }