public void UpdatePerItemLinkChangeGroupsByCheckingRelatedItemRecordsWithoutImplicitDelete(
     string sourceItemUri,
     LinkChangeGroup group,
     ILinkProvider linkProvider)
 {
     UpdatePerItemLinkChangeGroupsByCheckingRelatedItemRecords(sourceItemUri, group, linkProvider, false);
 }
Exemple #2
0
        public void ExtractLinkChangeActions(TfsMigrationWorkItem source, List <LinkChangeGroup> linkChangeGroups, WorkItemLinkStore store)
        {
            if (null == source)
            {
                throw new ArgumentNullException("source");
            }

            if (null == source.WorkItem)
            {
                throw new ArgumentException("source.WorkItem is null");
            }

            var linkChangeGroup = new LinkChangeGroup(
                source.WorkItem.Id.ToString(CultureInfo.InvariantCulture), LinkChangeGroup.LinkChangeGroupStatus.Created, false);

            foreach (Link l in source.WorkItem.Links)
            {
                ExternalLink el = l as ExternalLink;

                if (el != null && IsMyLink(el))
                {
                    var link = new Toolkit.Linking.ArtifactLink(
                        source.WorkItem.Id.ToString(CultureInfo.InvariantCulture),
                        new Toolkit.Linking.Artifact(source.Uri, s_sourceArtifactType),
                        new Toolkit.Linking.Artifact(LinkingConstants.ExternalArtifactPrefix + el.LinkedArtifactUri, s_targetArtifactType),
                        el.Comment,
                        this);
                    linkChangeGroup.AddChangeAction(new LinkChangeAction(WellKnownChangeActionId.Add, link,
                                                                         LinkChangeAction.LinkChangeActionStatus.Created,
                                                                         false));
                }
            }

            linkChangeGroups.Add(linkChangeGroup);
        }
Exemple #3
0
        public void ExtractLinkChangeActions(TfsMigrationWorkItem source, List <LinkChangeGroup> linkChangeGroups, WorkItemLinkStore store)
        {
            if (null == source)
            {
                throw new ArgumentNullException("source");
            }

            if (null == source.WorkItem)
            {
                throw new ArgumentException("source.WorkItem is null");
            }

            var linkChangeGroup = new LinkChangeGroup(
                source.WorkItem.Id.ToString(CultureInfo.InvariantCulture), LinkChangeGroup.LinkChangeGroupStatus.Created, false);

            ReadOnlyCollection <ExternalLink> myLinks = ExtractMyLinks(source.WorkItem);

            foreach (ExternalLink el in myLinks)
            {
                var link = new Toolkit.Linking.ArtifactLink(
                    source.WorkItem.Id.ToString(CultureInfo.InvariantCulture),
                    new Toolkit.Linking.Artifact(source.Uri, s_sourceArtifactType),
                    new Toolkit.Linking.Artifact(el.LinkedArtifactUri, s_targetArtifactType),
                    el.Comment,
                    this);
                linkChangeGroup.AddChangeAction(new LinkChangeAction(WellKnownChangeActionId.Add, link,
                                                                     LinkChangeAction.LinkChangeActionStatus.Created,
                                                                     false));
            }

            linkChangeGroups.Add(linkChangeGroup);
        }
 public void UpdatePerItemLinkChangeGroupsByCheckingRelatedItemRecords(
     string sourceItemUri,
     LinkChangeGroup group,
     ILinkProvider linkProvider)
 {
     UpdatePerItemLinkChangeGroupsByCheckingRelatedItemRecords(sourceItemUri, group, linkProvider, true);
 }
        protected override Dictionary <int, List <LinkChangeAction> > RegroupLinkChangeActions(
            LinkChangeGroup linkChangeGroup)
        {
            var perWorkItemLinkChanges = new Dictionary <int, List <LinkChangeAction> >();

            foreach (LinkChangeAction linkChangeAction in linkChangeGroup.Actions)
            {
                Debug.Assert(!string.IsNullOrEmpty(linkChangeAction.Link.SourceArtifactId));

                // skipping v2 WorkItemLinks, as they are submitted separately
                if (linkChangeAction.Link.LinkType is WorkItemLinkTypeBase)
                {
                    continue;
                }

                int  sourceArtifactWorkItemId;
                bool idConversionResult = int.TryParse(linkChangeAction.Link.SourceArtifactId,
                                                       out sourceArtifactWorkItemId);
                Debug.Assert(idConversionResult);

                if (!perWorkItemLinkChanges.ContainsKey(sourceArtifactWorkItemId))
                {
                    perWorkItemLinkChanges.Add(sourceArtifactWorkItemId, new List <LinkChangeAction>());
                }

                if (!perWorkItemLinkChanges[sourceArtifactWorkItemId].Contains(linkChangeAction))
                {
                    perWorkItemLinkChanges[sourceArtifactWorkItemId].Add(linkChangeAction);
                }
            }

            return(perWorkItemLinkChanges);
        }
        public void ExtractLinkChangeActions(
            Session session,
            OAdEntity hostRecord,
            List <LinkChangeGroup> linkChangeGroups)
        {
            string hostRecDispName      = CQWrapper.GetEntityDisplayName(hostRecord);
            string hostRecEntityDefName = CQWrapper.GetEntityDefName(hostRecord);
            string hostRecMigrItemId    = UtilityMethods.CreateCQRecordMigrationItemId(hostRecEntityDefName, hostRecDispName);

            var linkChangeGroup = new LinkChangeGroup(hostRecMigrItemId, LinkChangeGroup.LinkChangeGroupStatus.Created, false);

            if (!CQWrapper.HasDuplicates(hostRecord))
            {
                return;
            }

            object[] dupRecObjs = CQWrapper.GetDuplicates(hostRecord) as object[];

            foreach (object dupRecObj in dupRecObjs)
            {
                OAdLink aLink = dupRecObj as OAdLink;

                if (null != aLink)
                {
                    OAdEntity childRecord = CQWrapper.GetChildEntity(aLink) as OAdEntity;
                    if (null != childRecord)
                    {
                        string childRecDispName      = CQWrapper.GetEntityDisplayName(childRecord);
                        string childRecEntityDefName = CQWrapper.GetEntityDefName(childRecord);
                        string childRecMigrItemId    = UtilityMethods.CreateCQRecordMigrationItemId(childRecEntityDefName, childRecDispName);

                        ILink dupLink = new ArtifactLink(hostRecDispName,
                                                         new Artifact(hostRecMigrItemId, new ClearQuestRecordArtifactType()),
                                                         new Artifact(childRecMigrItemId, new ClearQuestRecordArtifactType()),
                                                         string.Empty,
                                                         this);
                        LinkChangeAction action = new LinkChangeAction(WellKnownChangeActionId.Add,
                                                                       dupLink,
                                                                       LinkChangeAction.LinkChangeActionStatus.Created,
                                                                       false);
                        linkChangeGroup.AddChangeAction(action);
                    }
                    else
                    {
                        // [teyang] TODO replace debug assertion with a conflict?
                        Debug.Assert(false, "null == childRecord");
                    }
                }
                else
                {
                    // [teyang] TODO replace debug assertion with a conflict?
                    Debug.Assert(false, "null == aLink");
                }
            }

            linkChangeGroups.Add(linkChangeGroup);
        }
Exemple #7
0
        public void BatchSubmitLinkChange(LinkChangeGroup linkChanges)
        {
            if (linkChanges.Actions.Count == 0)
            {
                linkChanges.Status = LinkChangeGroup.LinkChangeGroupStatus.Completed;
                return;
            }

            // group changes by work item Id
            Dictionary <string, List <LinkChangeAction> > perRecordLinkChanges = RegroupLinkChangeActions(linkChanges);

            WorkItemLinkStore relatedArtifactsStore = new WorkItemLinkStore(m_configurationService.SourceId);

            // batch-submit links of each cq record
            bool successForAllActions = true;

            foreach (var perWorkItemLinkChange in perRecordLinkChanges)
            {
                string[]  identity   = UtilityMethods.ParseCQRecordMigrationItemId(perWorkItemLinkChange.Key);
                OAdEntity hostEntity = CQWrapper.GetEntity(m_userSession, identity[0], identity[1]);

                foreach (LinkChangeAction linkChangeAction in perWorkItemLinkChange.Value)
                {
                    if (linkChangeAction.Status != LinkChangeAction.LinkChangeActionStatus.ReadyForMigration ||
                        linkChangeAction.IsConflicted)
                    {
                        continue;
                    }

                    var handler = linkChangeAction.Link.LinkType as ILinkHandler;
                    Debug.Assert(null != handler, "linktype is not an ILinkHandler");
                    if (!handler.Update(m_migrationContext, m_userSession, hostEntity, linkChangeAction))
                    {
                        successForAllActions = false;
                        // [teyang] todo conflict handling
                        linkChangeAction.Status       = LinkChangeAction.LinkChangeActionStatus.Completed;
                        linkChangeAction.IsConflicted = true;
                        TraceManager.TraceError("Failed processing link change action: {0} linked to {1}",
                                                linkChangeAction.Link.SourceArtifact.Uri,
                                                linkChangeAction.Link.TargetArtifact.Uri);
                    }
                    else
                    {
                        MarkLinkChangeActionCompleted(linkChangeAction, relatedArtifactsStore);
                    }
                }
            }

            linkChanges.Status = successForAllActions
                                 ? LinkChangeGroup.LinkChangeGroupStatus.Completed
                                 : LinkChangeGroup.LinkChangeGroupStatus.ReadyForMigration;
        }
Exemple #8
0
 public virtual void BatchSubmitLinkChange(LinkChangeGroup linkChanges)
 {
     try
     {
         m_migrationSource.WorkItemStore.SubmitLinkChanges(linkChanges, m_serviceContainer);
     }
     catch (Exception exception)
     {
         ErrorManager errMgr = m_serviceContainer.GetService(typeof(ErrorManager)) as ErrorManager;
         errMgr.TryHandleException(exception);
         linkChanges.IsConflicted = true;
     }
 }
        private List <LinkChangeAction> ExtractWorkItemLinkChanges(
            LinkChangeGroup linkChangeGroup)
        {
            var extractedLinkChanges = new List <LinkChangeAction>();

            foreach (LinkChangeAction linkChangeAction in linkChangeGroup.Actions)
            {
                Debug.Assert(!string.IsNullOrEmpty(linkChangeAction.Link.SourceArtifactId));
                if (linkChangeAction.Link.LinkType is WorkItemLinkTypeBase)
                {
                    extractedLinkChanges.Add(linkChangeAction);
                }
            }
            return(extractedLinkChanges);
        }
        public void ExtractLinkChangeActions(ClearQuestOleServer.Session session, ClearQuestOleServer.OAdEntity hostRecord, List <LinkChangeGroup> linkChangeGroups)
        {
            string recordId = CQWrapper.GetFieldValue(CQWrapper.GetEntityFieldValue(hostRecord, CQIdFieldName));
            string url      = string.Format(m_urlFormat, recordId);

            var linkChangeGroup = new LinkChangeGroup(recordId, LinkChangeGroup.LinkChangeGroupStatus.Created, false);

            string hostEntityDefName  = CQWrapper.GetEntityDefName(hostRecord);
            string hostEntityDispName = CQWrapper.GetEntityDisplayName(hostRecord);
            string hostRecordId       = UtilityMethods.CreateCQRecordMigrationItemId(hostEntityDefName, hostEntityDispName);

            ArtifactLink     link   = new ArtifactLink(hostRecordId, new Artifact(hostRecordId, s_sourceArtifactType), new Artifact(url, s_targetArtifactType), string.Empty, this);
            LinkChangeAction action = new LinkChangeAction(WellKnownChangeActionId.Add, link, LinkChangeAction.LinkChangeActionStatus.Created, false);

            linkChangeGroup.AddChangeAction(action);
            linkChangeGroups.Add(linkChangeGroup);
        }
Exemple #11
0
        protected override void SubmitLinkChangesWithUpdateDoc(
            LinkChangeGroup linkChanges,
            ServiceContainer serviceContainer,
            TfsLinkingProviderBase.LinkSubmissionPhase submissionPhase)
        {
            ConfigurationService configService      = serviceContainer.GetService(typeof(ConfigurationService)) as ConfigurationService;
            ITranslationService  translationService = serviceContainer.GetService(typeof(ITranslationService)) as ITranslationService;

            bool nonWorkItemLinkChangesAllSubmitted = SubmitNonWorkItemLinkChanges(
                linkChanges, serviceContainer, configService, translationService, submissionPhase);
            bool workItemLinkChangesAllSubmitted = SubmitWorkItemLinkChanges(
                linkChanges, serviceContainer, configService, translationService, submissionPhase);

            linkChanges.Status = (nonWorkItemLinkChangesAllSubmitted && workItemLinkChangesAllSubmitted && AllActionSubmitted(linkChanges))
                                     ? LinkChangeGroup.LinkChangeGroupStatus.Completed
                                     : LinkChangeGroup.LinkChangeGroupStatus.ReadyForMigration;
        }
Exemple #12
0
        internal void ValidateLinkChangeMigrationInstructions(LinkChangeGroup group)
        {
            string sourceItemUri = group.Actions[0].Link.SourceArtifact.Uri;

            var queryByItem          = QueryByItem(sourceItemUri);
            var perItemExistingLinks = from link in queryByItem
                                       where link.RelationshipExistsOnServer
                                       select link;

            foreach (LinkChangeAction action in group.Actions)
            {
                var existingLinkQuery = from link in perItemExistingLinks
                                        where link.Relationship.Equals(action.Link.LinkType.ReferenceName) &&
                                        link.RelatedArtifactId.Equals(action.Link.TargetArtifact.Uri)
                                        select link;

                if (action.ChangeActionId.Equals(WellKnownChangeActionId.Add))
                {
                    if (existingLinkQuery.Count() > 0)
                    {
                        if (existingLinkQuery.First().OtherProperty.HasValue)
                        {
                            bool linkInStoreIsLocked = ((WorkItemLinkStore.LinkLockStatus)existingLinkQuery.First().OtherProperty.Value == WorkItemLinkStore.LinkLockStatus.Locked);
                            if (linkInStoreIsLocked == action.Link.IsLocked)
                            {
                                // link already exist on server, no need to "add"
                                action.Status = LinkChangeAction.LinkChangeActionStatus.Skipped;
                            }
                        }
                    }
                }
                else if (action.ChangeActionId.Equals(WellKnownChangeActionId.Delete))
                {
                    if (existingLinkQuery.Count() == 0)
                    {
                        // link doesn't exist on server, no need to "delete"
                        action.Status = LinkChangeAction.LinkChangeActionStatus.Skipped;
                    }
                }
                else
                {
                    // we don't know anything about the action in this case
                }
            }
        }
Exemple #13
0
        public virtual void ExtractLinkChangeActions(TfsMigrationWorkItem source, List <LinkChangeGroup> linkChangeGroups, WorkItemLinkStore store)
        {
            if (null == source)
            {
                throw new ArgumentNullException("source");
            }

            if (null == source.WorkItem)
            {
                throw new ArgumentException("source.WorkItem is null");
            }

            var linkChangeGroup = new LinkChangeGroup(
                source.WorkItem.Id.ToString(CultureInfo.InvariantCulture), LinkChangeGroup.LinkChangeGroupStatus.Created, false);

            foreach (Link l in source.WorkItem.Links)
            {
                RelatedLink rl = l as RelatedLink;

                if (rl != null)
                {
                    // v1 work item related link does not have direction info
                    // to avoid generating two link change actions for the same link
                    // we only pick one from the work item of smaller id
                    if (source.WorkItem.Id >= rl.RelatedWorkItemId)
                    {
                        continue;
                    }

                    var link = new Toolkit.Linking.ArtifactLink(
                        source.WorkItem.Id.ToString(CultureInfo.InvariantCulture),
                        new Toolkit.Linking.Artifact(source.Uri, s_sourceArtifactType),
                        new Toolkit.Linking.Artifact(TfsWorkItemHandler.UriFromId(rl.RelatedWorkItemId.ToString(CultureInfo.InvariantCulture)), s_targetArtifactType),
                        rl.Comment,
                        this);
                    linkChangeGroup.AddChangeAction(new LinkChangeAction(WellKnownChangeActionId.Add, link,
                                                                         LinkChangeAction.LinkChangeActionStatus.Created,
                                                                         false));
                }
            }

            linkChangeGroups.Add(linkChangeGroup);
        }
        protected override void SubmitLinkChangesWithUpdateDoc(
            LinkChangeGroup linkChanges,
            ServiceContainer serviceContainer,
            TfsLinkingProviderBase.LinkSubmissionPhase submissionPhase)
        {
            ConfigurationService configService      = serviceContainer.GetService(typeof(ConfigurationService)) as ConfigurationService;
            ITranslationService  translationService = serviceContainer.GetService(typeof(ITranslationService)) as ITranslationService;

            if (m_hwmSubmittedLinkChangeId == null)
            {
                m_hwmSubmittedLinkChangeId = new HighWaterMark <long>(TfsConstants.HwmSubmittedLinkChangeId);
                configService.RegisterHighWaterMarkWithSession(m_hwmSubmittedLinkChangeId);
            }

            bool nonWorkItemLinkChangesAllSubmitted = SubmitNonWorkItemLinkChanges(
                linkChanges, serviceContainer, configService, translationService, submissionPhase);
            bool workItemLinkChangesAllSubmitted = SubmitWorkItemLinkChanges(
                linkChanges, serviceContainer, configService, translationService, submissionPhase);

            linkChanges.Status = (nonWorkItemLinkChangesAllSubmitted && workItemLinkChangesAllSubmitted && AllActionSubmitted(linkChanges))
                                     ? LinkChangeGroup.LinkChangeGroupStatus.Completed
                                     : LinkChangeGroup.LinkChangeGroupStatus.ReadyForMigration;
        }
Exemple #15
0
        private Dictionary <string, List <LinkChangeAction> > RegroupLinkChangeActions(LinkChangeGroup linkChanges)
        {
            Dictionary <string, List <LinkChangeAction> > retVal = new Dictionary <string, List <LinkChangeAction> >();

            foreach (LinkChangeAction action in linkChanges.Actions)
            {
                if (!retVal.ContainsKey(action.Link.SourceArtifactId))
                {
                    retVal.Add(action.Link.SourceArtifactId, new List <LinkChangeAction>());
                }

                if (!retVal[action.Link.SourceArtifactId].Contains(action))
                {
                    retVal[action.Link.SourceArtifactId].Add(action);
                }
            }

            return(retVal);
        }
        public void ExtractLinkChangeActions(
            Session session,
            OAdEntity hostRecord,
            List <LinkChangeGroup> linkChangeGroups)
        {
            string hostRecDispName      = CQWrapper.GetEntityDisplayName(hostRecord);
            string hostRecEntityDefName = CQWrapper.GetEntityDefName(hostRecord);

            if (string.IsNullOrEmpty(hostRecEntityDefName) ||
                !CQStringComparer.EntityName.Equals(hostRecEntityDefName, this.m_hostRecordType))
            {
                return;
            }

            string hostRecMigrItemId = UtilityMethods.CreateCQRecordMigrationItemId(hostRecEntityDefName, hostRecDispName);

            var linkChangeGroup = new LinkChangeGroup(hostRecMigrItemId, LinkChangeGroup.LinkChangeGroupStatus.Created, false);

            OAdFieldInfo fldInfo     = CQWrapper.GetEntityFieldValue(hostRecord, m_referenceFieldName);
            int          cqFieldType = CQWrapper.GetFieldType(fldInfo);

            if (cqFieldType == CQConstants.FIELD_REFERENCE)
            {
                // get the current entity def handle
                OAdEntityDef curEntityDef          = CQWrapper.GetEntityDef(session, hostRecEntityDefName);
                OAdEntityDef refEntityDef          = CQWrapper.GetFieldReferenceEntityDef(curEntityDef, m_referenceFieldName);
                string       childRecEntityDefName = CQWrapper.GetEntityDefName(refEntityDef);

                int valueStatus = CQWrapper.GetFieldValueStatus(fldInfo);
                if (valueStatus == (int)CQConstants.FieldStatus.HAS_VALUE)
                {
                    // single value required
                    string refFldVal = CQWrapper.GetFieldValue(fldInfo);
                    if (!CQStringComparer.RecordName.Equals(refFldVal, hostRecDispName))
                    {
                        // NOT a reference to self.. Note TFS cannot have a reference to self
                        OAdEntity childRecord = CQWrapper.GetEntity(session, childRecEntityDefName, refFldVal);
                        if (null != childRecord)
                        {
                            string childRecDispName   = CQWrapper.GetEntityDisplayName(childRecord);
                            string childRecMigrItemId = UtilityMethods.CreateCQRecordMigrationItemId(
                                childRecEntityDefName, childRecDispName);

                            ILink refFieldLink = new ArtifactLink(
                                hostRecDispName,
                                new Artifact(hostRecMigrItemId, new ClearQuestRecordArtifactType()),
                                new Artifact(childRecMigrItemId, new ClearQuestRecordArtifactType()),
                                string.Empty,
                                this);

                            LinkChangeAction action = new LinkChangeAction(
                                WellKnownChangeActionId.Add,
                                refFieldLink,
                                LinkChangeAction.LinkChangeActionStatus.Created,
                                false);

                            linkChangeGroup.AddChangeAction(action);
                        }
                        else
                        {
                            // [teyang] TODO replace debug assertion with a conflict?
                            Debug.Assert(false, "null == childRecord");
                        }
                    }
                }
            }

            linkChangeGroups.Add(linkChangeGroup);
        }
Exemple #17
0
        public ReadOnlyCollection <LinkChangeGroup> GenerateNextLinkDeltaSlice(
            LinkService linkService,
            int maxDeltaSliceSize)
        {
            try
            {
                var linkChangeGroups = new List <LinkChangeGroup>();

                if (null == ExtractLinkChangeActionsCallback)
                {
                    return(linkChangeGroups.AsReadOnly());
                }

                // load high watermark; as for CQ, we store local time for queries
                m_hwmLink.Reload();
                DateTime hwmDeltaValue = m_hwmLink.Value;
                if (hwmDeltaValue.Equals(default(DateTime)))
                {
                    hwmDeltaValue = new DateTime(1900, 1, 1);
                }
                hwmDeltaValue = hwmDeltaValue.AddSeconds(-1);           // go back 1 second as we'll drop the millisec below

                string hwmDeltaValueStr = hwmDeltaValue.ToString(m_migrationContext.CQQueryDateTimeFormat, CultureInfo.InvariantCulture);

                // record current time to update HWM after processing
                DateTime newHwmValue = CQUtilityMethods.GetTimeForNewHighWaterMark(m_migrationContext.CQTimeOffsetFromServerHistoryTimesInMinutes);

                // store to be used for analysis
                WorkItemLinkStore store = new WorkItemLinkStore(m_configurationService.SourceId);

                // extract links
                var inMaxDeltaSliceSize = maxDeltaSliceSize;
                foreach (CQRecordFilter filter in m_filters)
                {
                    CQRecordQueryBase recordQuery = CQRecordQueryFactory.CreateQuery(m_userSession, filter, hwmDeltaValueStr, this);
                    foreach (ClearQuestOleServer.OAdEntity record in recordQuery)
                    {
                        // HACK HACK
                        if (record == null)
                        {
                            continue;
                        }
                        // HACK HACK

                        string recDispName = CQWrapper.GetEntityDisplayName(record);

                        TraceManager.TraceInformation("Generating linking delta for CQ Record: {0}", recDispName);

                        var perWorkItemlinkChangeGroups = new List <LinkChangeGroup>();
                        ExtractLinkChangeActionsCallback(m_userSession, record, perWorkItemlinkChangeGroups);

                        if (perWorkItemlinkChangeGroups.Count == 0)
                        {
                            TraceManager.TraceInformation("Number of links: {0}", 0);
                            continue;
                        }

                        LinkChangeGroup consolidatedLinkChangeGroup = perWorkItemlinkChangeGroups[0];
                        for (int i = 1; i < perWorkItemlinkChangeGroups.Count; ++i)
                        {
                            foreach (LinkChangeAction action in perWorkItemlinkChangeGroups[i].Actions)
                            {
                                consolidatedLinkChangeGroup.AddChangeAction(action);
                            }
                        }
                        TraceManager.TraceInformation("Number of links: {0}", consolidatedLinkChangeGroup.Actions.Count.ToString());

                        // VERY IMPORTANT STEP: update the link delta to store
                        string hostRecMigrItemId = UtilityMethods.CreateCQRecordMigrationItemId(record);
                        store.UpdatePerItemLinkChangeGroupsByCheckingRelatedItemRecords(
                            hostRecMigrItemId, consolidatedLinkChangeGroup, this);

                        if (consolidatedLinkChangeGroup.Actions.Count > 0)
                        {
                            linkChangeGroups.Add(consolidatedLinkChangeGroup);
                        }
                        maxDeltaSliceSize -= consolidatedLinkChangeGroup.Actions.Count;

                        if (maxDeltaSliceSize <= 0)
                        {
                            // size limit reached - persist groups to DB, then empty the slice and process next slice
                            linkService.AddChangeGroups(linkChangeGroups);
                            linkChangeGroups.Clear();
                            maxDeltaSliceSize = inMaxDeltaSliceSize;
                        }
                    }
                }

                // persist remaining groups to DB
                linkService.AddChangeGroups(linkChangeGroups);

                // clean up the returned link change group collection
                // when the caller (toolkit) receives an empty collection, it understands there is no more
                // delta to generate for the moment, and proceeds to next phase
                linkChangeGroups.Clear();

                // update primary Highwater Mark
                m_hwmLink.Update(newHwmValue);
                TraceManager.TraceInformation("Persisted CQ linking HWM: {0}", ClearQuestConstants.CqLinkHwm);
                TraceManager.TraceInformation("Updated CQ linking HWM: {0}", newHwmValue.ToString());

                return(linkChangeGroups.AsReadOnly());
            }
            catch (Exception exception)
            {
                // [teyang] TODO CONFLICT HANDLING

                //MigrationConflict genericeConflict = WitGeneralConflictType.CreateConflict(exception);
                //var conflictManager = m_conflictManager.GetService(typeof(ConflictManager)) as ConflictManager;
                //Debug.Assert(null != conflictManager);
                //List<MigrationAction> resolutionActions;
                //ConflictResolutionResult resolveRslt =
                //    conflictManager.TryResolveNewConflict(conflictManager.SourceId, genericeConflict, out resolutionActions);
                //Debug.Assert(!resolveRslt.Resolved);
                TraceManager.TraceException(exception);
                return(new List <LinkChangeGroup>().AsReadOnly());
            }
        }
        private void UpdatePerItemLinkChangeGroupsByCheckingRelatedItemRecords(
            string sourceItemUri,
            LinkChangeGroup group,
            ILinkProvider linkProvider,
            bool createDeleteActionImplicitly)
        {
            var queryByItem          = QueryByItem(sourceItemUri);
            var perItemExistingLinks = from link in queryByItem
                                       where link.RelationshipExistsOnServer
                                       select link;

            if (perItemExistingLinks.Count() == 0)
            {
                // no link existed before, all 'add' link actions should be pushed to the other side
                // AND we are going to record these links as existing on this side now
                AddLinks(group.Actions);
            }
            else
            {
                // check the delta link change actions

                // this list contains all the actions that do not need to push into the pipeline
                List <LinkChangeAction> actionThatEstablishExistingLinkRelationship = new List <LinkChangeAction>();
                foreach (LinkChangeAction action in group.Actions)
                {
                    if (action.Link.LinkType.GetsActionsFromLinkChangeHistory)
                    {
                        // For link types that can provide a history of link changes, we don't need to keep track of related artifact metadata
                        // so continue to the next LinkChangeAction
                        continue;
                    }
                    Debug.Assert(sourceItemUri.Equals(action.Link.SourceArtifact.Uri), "link of different action exists in the same group");
                    var linkQuery = from l in perItemExistingLinks
                                    where l.Relationship.Equals(action.Link.LinkType.ReferenceName) &&
                                    l.RelatedArtifactId.Equals(action.Link.TargetArtifact.Uri)
                                    select l;

                    if (action.ChangeActionId.Equals(WellKnownChangeActionId.Add))
                    {
                        if (linkQuery.Count() > 0)
                        {
                            if (!linkQuery.First().OtherProperty.HasValue)
                            {
                                // link lock property is not available - required by backward-compability
                                UpdateLink(action, true);
                            }
                            else
                            {
                                bool linkInStoreHasLock = (((WorkItemLinkStore.LinkLockStatus)linkQuery.First().OtherProperty.Value) == WorkItemLinkStore.LinkLockStatus.Locked);

                                if (action.Link.IsLocked == linkInStoreHasLock)
                                {
                                    // link already exist and lock-property matches - no need to push to the other side
                                    actionThatEstablishExistingLinkRelationship.Add(action);
                                }
                                else
                                {
                                    UpdateLink(action, true);
                                }
                            }
                        }
                        else
                        {
                            // link does not exist, keep it and push through the pipeline
                            // AND we are going to record these links as existing on this side now
                            UpdateLink(action, true);
                        }
                    }
                    else // delete
                    {
                        if (linkQuery.Count() > 0)
                        {
                            // link exists, so we will mark in our store that it no longer exists
                            UpdateLink(action, false);
                        }
                        else
                        {
                            // link does not exist, no need to migrate this action
                            actionThatEstablishExistingLinkRelationship.Add(action);
                        }
                    }
                }

                // make sure we generate "Delete Link" action for ones that exist in the our recorded link table but is not included
                // in delta link actions
                List <LinkChangeAction> deletionActions = new List <LinkChangeAction>();
                if (createDeleteActionImplicitly)
                {
                    foreach (var recordedExistingLink in perItemExistingLinks)
                    {
                        Debug.Assert(linkProvider.SupportedLinkTypes.ContainsKey(recordedExistingLink.Relationship),
                                     "linkProvider.SupportedLinkTypes.ContainsKey(recordedExistingLink.Relationship) returns false");
                        LinkType linkType = linkProvider.SupportedLinkTypes[recordedExistingLink.Relationship];
                        if (linkType.GetsActionsFromLinkChangeHistory)
                        {
                            // The link type is one that support link change history, so we ignore the contents of the
                            // RelatedArtifactTable and rely on the link change history instead.
                            continue;
                        }

                        bool recordedActionInGroup = false;
                        foreach (LinkChangeAction action in group.Actions)
                        {
                            if (action.Link.LinkType.ReferenceName.Equals(recordedExistingLink.Relationship, StringComparison.OrdinalIgnoreCase) &&
                                action.Link.TargetArtifact.Uri.Equals(recordedExistingLink.RelatedArtifactId, StringComparison.OrdinalIgnoreCase))
                            {
                                recordedActionInGroup = true;
                                break;
                            }
                        }

                        if (!recordedActionInGroup)
                        {
                            TraceManager.TraceInformation("Link '{0}'->'{1}' ({2}) appears to have been deleted - generating link deletion action to be migrated",
                                                          recordedExistingLink.ItemId, recordedExistingLink.RelatedArtifactId, recordedExistingLink.Relationship);

                            LinkChangeAction linkDeleteAction = linkType.CreateLinkDeletionAction(
                                recordedExistingLink.ItemId, recordedExistingLink.RelatedArtifactId, recordedExistingLink.Relationship);

                            if (null != linkDeleteAction)
                            {
                                deletionActions.Add(linkDeleteAction);
                            }

                            recordedExistingLink.RelationshipExistsOnServer = false;
                        }
                    }
                }

                if (actionThatEstablishExistingLinkRelationship.Count > 0)
                {
                    foreach (LinkChangeAction actionToDelete in actionThatEstablishExistingLinkRelationship)
                    {
                        group.DeleteChangeAction(actionToDelete);
                    }
                }

                if (deletionActions.Count > 0)
                {
                    group.PrependActions(deletionActions);
                }
            }

            m_context.TrySaveChanges();
        }
Exemple #19
0
        public void ExtractLinkChangeActions(TfsMigrationWorkItem source, List <LinkChangeGroup> linkChangeGroups, WorkItemLinkStore store)
        {
            if (null == source)
            {
                throw new ArgumentNullException("source");
            }

            if (null == source.WorkItem)
            {
                throw new ArgumentException("source.WorkItem is null");
            }

            var linkChangeGroup = new LinkChangeGroup(
                source.WorkItem.Id.ToString(CultureInfo.InvariantCulture), LinkChangeGroup.LinkChangeGroupStatus.Created, false);

            List <string> revertedLinkSourceWorkItemUris = new List <string>();

            if (null != store)
            {
                revertedLinkSourceWorkItemUris = store.GetRevertedLinkSourceItems(source.Uri, ReferenceName);
            }

            foreach (WorkItemLink l in source.WorkItem.WorkItemLinks)
            {
                #region obsolete
                //// always recognize the "ForwardLink"
                //if (!l.LinkTypeEnd.IsForwardLink)
                //{
                //    continue;
                //}
                #endregion

                // always recognize the WorkItem with smaller Id for non-directional link
                if (!l.LinkTypeEnd.LinkType.IsDirectional && l.SourceId > l.TargetId)
                {
                    continue;
                }

                if (!TFStringComparer.LinkName.Equals(l.LinkTypeEnd.LinkType.ReferenceName, ReferenceName))
                {
                    continue;
                }

                var sourceIdStr    = l.SourceId.ToString(CultureInfo.InvariantCulture);
                var targetIdStr    = l.TargetId.ToString(CultureInfo.InvariantCulture);
                var sourceArtifact = new ToolkitLinking.Artifact(TfsWorkItemHandler.UriFromId(sourceIdStr), s_sourceArtifactType);
                var targetArtifact = new ToolkitLinking.Artifact(TfsWorkItemHandler.UriFromId(targetIdStr), s_targetArtifactType);

                ToolkitLinking.ArtifactLink link;
                if (l.LinkTypeEnd.IsForwardLink)
                {
                    link = new ToolkitLinking.ArtifactLink(sourceIdStr, sourceArtifact, targetArtifact, l.Comment, this, l.IsLocked);
                }
                else
                {
                    link = new ToolkitLinking.ArtifactLink(targetIdStr, targetArtifact, sourceArtifact, l.Comment, this, l.IsLocked);
                    if (revertedLinkSourceWorkItemUris.Contains(targetArtifact.Uri))
                    {
                        revertedLinkSourceWorkItemUris.Remove(targetArtifact.Uri);
                    }
                }

                var linkChangeAction = new LinkChangeAction(WellKnownChangeActionId.Add,
                                                            link,
                                                            LinkChangeAction.LinkChangeActionStatus.Created,
                                                            false);

                linkChangeGroup.AddChangeAction(linkChangeAction);
            }

            foreach (string revertedLinkSrcItemUri in revertedLinkSourceWorkItemUris)
            {
                string          sourceWorkItemId = TfsWorkItemHandler.IdFromUri(revertedLinkSrcItemUri);
                LinkChangeGroup group            =
                    new LinkChangeGroup(sourceWorkItemId, LinkChangeGroup.LinkChangeGroupStatus.Created, false);
                var deleteLinkChangeAction = new LinkChangeAction(
                    WellKnownChangeActionId.Delete,
                    new ToolkitLinking.ArtifactLink(sourceWorkItemId,
                                                    new ToolkitLinking.Artifact(revertedLinkSrcItemUri, s_sourceArtifactType),
                                                    new ToolkitLinking.Artifact(source.Uri, s_targetArtifactType),
                                                    string.Empty, this),
                    LinkChangeAction.LinkChangeActionStatus.Created, false);
                group.AddChangeAction(deleteLinkChangeAction);
                linkChangeGroups.Add(group);
            }

            linkChangeGroups.Add(linkChangeGroup);
        }
Exemple #20
0
        private void CreateLinkChangeGroupsForForceSyncItem(TfsMigrationWorkItem tfsMigrationWorkItem)
        {
            if (m_linkService == null)
            {
                Debug.Fail("LinkService is null");
                return;
            }

            var linkChangeGroups         = new List <LinkChangeGroup>();
            var detectedLinkChangeGroups = new List <LinkChangeGroup>();

            ExtractLinkChangeActionsCallback(tfsMigrationWorkItem, detectedLinkChangeGroups, null);

            if (detectedLinkChangeGroups.Count == 0)
            {
                TraceManager.TraceInformation("Number of non-Work Item links: {0}", 0);
            }
            else
            {
                Dictionary <string, LinkChangeGroup> perWorkItemConsolidatedLinkChangeGroup = new Dictionary <string, LinkChangeGroup>();
                for (int i = 0; i < detectedLinkChangeGroups.Count; ++i)
                {
                    foreach (LinkChangeAction action in detectedLinkChangeGroups[i].Actions)
                    {
                        if (!perWorkItemConsolidatedLinkChangeGroup.ContainsKey(action.Link.SourceArtifact.Uri))
                        {
                            var linkChangeGroup = new LinkChangeGroup(
                                action.Link.SourceArtifactId, LinkChangeGroup.LinkChangeGroupStatus.Created, false);
                            perWorkItemConsolidatedLinkChangeGroup.Add(action.Link.SourceArtifact.Uri, linkChangeGroup);
                        }
                        perWorkItemConsolidatedLinkChangeGroup[action.Link.SourceArtifact.Uri].AddChangeAction(action);
                    }
                }

                foreach (var workItemLinkGroup in perWorkItemConsolidatedLinkChangeGroup)
                {
                    string workItemIdStr = TfsWorkItemHandler.IdFromUri(workItemLinkGroup.Key);
                    TraceManager.TraceInformation("Detected {0} non-Work Item links for force sync Work Item '{1}'",
                                                  workItemLinkGroup.Value.Actions.Count, workItemIdStr);

                    if (workItemLinkGroup.Value.Actions.Count > 0)
                    {
                        workItemLinkGroup.Value.IsForcedSync = true;
                        linkChangeGroups.Add(workItemLinkGroup.Value);
                    }
                }
            }

            if (tfsMigrationWorkItem.WorkItem.WorkItemLinks.Count > 0)
            {
                // Handle work item to work item links
                LinkChangeGroup workItemlinkChangeGroup = new LinkChangeGroup(
                    tfsMigrationWorkItem.WorkItem.Id.ToString(CultureInfo.InvariantCulture), LinkChangeGroup.LinkChangeGroupStatus.Created, false);

                Dictionary <string, LinkType> linkTypesByName = new Dictionary <string, LinkType>();
                foreach (WorkItemLink workItemLink in tfsMigrationWorkItem.WorkItem.WorkItemLinks)
                {
                    string   linkTypeName = workItemLink.LinkTypeEnd.LinkType.ReferenceName;
                    LinkType linkType;
                    if (!linkTypesByName.TryGetValue(linkTypeName, out linkType))
                    {
                        ExtendedLinkProperties extendedLinkProperties = new ExtendedLinkProperties();

                        linkType = new WorkItemLinkTypeBase(linkTypeName,
                                                            linkTypeName,
                                                            extendedLinkProperties,
                                                            m_migrationSource.WorkItemStore.WorkItemStore);
                        linkTypesByName.Add(linkTypeName, linkType);
                    }

                    LinkChangeAction addLinkChangeAction = GetAddLinkChangeActionFromWorkItemLink(workItemLink, linkType);
                    workItemlinkChangeGroup.AddChangeAction(addLinkChangeAction);
                }
                if (workItemlinkChangeGroup.Actions.Count > 0)
                {
                    workItemlinkChangeGroup.IsForcedSync = true;
                    linkChangeGroups.Add(workItemlinkChangeGroup);
                    TraceManager.TraceInformation("Detected {0} Work Item links for force sync Work Item '{1}'",
                                                  workItemlinkChangeGroup.Actions.Count, tfsMigrationWorkItem.WorkItem.Id);
                }
            }

            // Persist link change groups to DB
            if (linkChangeGroups.Count > 0)
            {
                m_linkService.AddChangeGroups(linkChangeGroups);
            }
        }
Exemple #21
0
        public virtual ReadOnlyCollection <LinkChangeGroup> GenerateNextLinkDeltaSlice(
            LinkService linkService,
            int maxDeltaSliceSize)
        {
            try
            {
                var linkChangeGroups = new List <LinkChangeGroup>();

                if (null == ExtractLinkChangeActionsCallback)
                {
                    return(linkChangeGroups.AsReadOnly());
                }

                // load main Highwater Mark
                m_hwmLink.Reload();
                DateTime hwmLinkValue    = m_hwmLink.Value;
                string   hwmLinkValueStr = hwmLinkValue.ToString(CultureInfo.InvariantCulture);

                // load Work Items for extracting links
                string sourceId  = m_migrationSource.UniqueId;
                string storeName = m_migrationSource.WorkItemStore.StoreName;

                // Get items based on primary Highwater Mark
                TraceManager.TraceInformation(TfsWITAdapterResources.GettingModifiedItems, sourceId, storeName);
                IEnumerable <TfsMigrationWorkItem> items = m_migrationSource.WorkItemStore.GetItems(ref hwmLinkValueStr);
                TraceManager.TraceInformation(TfsWITAdapterResources.ReceivedModifiedItems, sourceId, storeName);

                // Record the updated HWM value
                DateTime newHwmLinkValue = Convert.ToDateTime(hwmLinkValueStr, CultureInfo.InvariantCulture);

                // store to be used to analyze deleted links
                WorkItemLinkStore store = new WorkItemLinkStore(new Guid(sourceId));

                // extract links
                var inMaxDeltaSliceSize = maxDeltaSliceSize;
                foreach (TfsMigrationWorkItem tfsMigrationWorkItem in items)
                {
                    if (tfsMigrationWorkItem.WorkItem == null)
                    {
                        continue;
                    }

                    TraceManager.TraceInformation("Generating linking delta for Work Item: {0}", tfsMigrationWorkItem.WorkItem.Id.ToString());
                    var perWorkItemlinkChangeGroups = new List <LinkChangeGroup>();
                    ExtractLinkChangeActionsCallback(tfsMigrationWorkItem, perWorkItemlinkChangeGroups, store);

                    if (perWorkItemlinkChangeGroups.Count == 0)
                    {
                        TraceManager.TraceInformation("Number of links: {0}", 0);
                        continue;
                    }

                    LinkChangeGroup consolidatedLinkChangeGroup = perWorkItemlinkChangeGroups[0];
                    for (int i = 1; i < perWorkItemlinkChangeGroups.Count; ++i)
                    {
                        foreach (LinkChangeAction action in perWorkItemlinkChangeGroups[i].Actions)
                        {
                            consolidatedLinkChangeGroup.AddChangeAction(action);
                        }
                    }
                    TraceManager.TraceInformation("Number of links: {0}", consolidatedLinkChangeGroup.Actions.Count.ToString());

                    // VERY IMPORTANT: use the RelatedArtifactsStore to detect link deletion
                    store.UpdatePerItemLinkChangeGroupsByCheckingRelatedItemRecords(
                        tfsMigrationWorkItem.Uri, consolidatedLinkChangeGroup, this);

                    if (consolidatedLinkChangeGroup.Actions.Count > 0)
                    {
                        linkChangeGroups.Add(consolidatedLinkChangeGroup);
                    }
                    maxDeltaSliceSize -= consolidatedLinkChangeGroup.Actions.Count;

                    if (maxDeltaSliceSize <= 0)
                    {
                        // size limit reached - persist groups to DB
                        linkService.AddChangeGroups(linkChangeGroups);
                        linkChangeGroups.Clear();
                        maxDeltaSliceSize = inMaxDeltaSliceSize;
                    }
                }

                // persist remaining groups to DB
                linkService.AddChangeGroups(linkChangeGroups);

                // clean up the returned link change group collection
                // when the caller (toolkit) receives an empty collection, it understands there is no more
                // delta to generate for the moment, and proceeds to next phase
                linkChangeGroups.Clear();

                // update primary Highwater Mark
                m_hwmLink.Update(newHwmLinkValue);
                TraceManager.TraceInformation("Persisted WIT linking HWM: {0}", Toolkit.Constants.HwmDeltaLink);
                TraceManager.TraceInformation(TfsWITAdapterResources.UpdatedHighWatermark, hwmLinkValueStr);

                return(linkChangeGroups.AsReadOnly());
            }
            catch (Exception exception)
            {
                ErrorManager errMgr = m_serviceContainer.GetService(typeof(ErrorManager)) as ErrorManager;
                errMgr.TryHandleException(exception);
                return(new List <LinkChangeGroup>().AsReadOnly());
            }
        }
Exemple #22
0
        private LinkChangeGroup GetLinkChangeGroupFromLinkChanges(TfsMigrationWorkItem source)
        {
            LinkChangeGroup linkChangeGroup = new LinkChangeGroup(
                source.WorkItem.Id.ToString(CultureInfo.InvariantCulture), LinkChangeGroup.LinkChangeGroupStatus.Created, false);

            Dictionary <string, LinkType> linkTypesByName = new Dictionary <string, LinkType>();

            foreach (WorkItemLinkChange linkChange in source.LinkChanges)
            {
                LinkType linkType;
                if (!linkTypesByName.TryGetValue(linkChange.LinkType, out linkType))
                {
                    ExtendedLinkProperties extendedLinkProperties = new ExtendedLinkProperties();

                    linkType = new WorkItemLinkTypeBase(linkChange.LinkType,
                                                        linkChange.LinkType,
                                                        extendedLinkProperties,
                                                        m_migrationSource.WorkItemStore.WorkItemStore);
                    linkTypesByName.Add(linkChange.LinkType, linkType);
                }

                bool actionAdded = false;
                if (linkChange.IsActive)  // Link added
                {
                    // Get matching link l from WorkItem links collection
                    WorkItemLink l = GetWorkItemLinkFromLinkChange(source, linkChange);

                    if (l != null)
                    {
                        LinkChangeAction addLinkChangeAction = GetAddLinkChangeActionFromWorkItemLink(l, linkType);
                        addLinkChangeAction.ServerLinkChangeId = linkChange.RowVersion.ToString();
                        linkChangeGroup.AddChangeAction(addLinkChangeAction);
                        actionAdded = true;
                    }
                    else
                    {
                        TraceManager.TraceInformation(String.Format(
                                                          "Unable to find link on work item {0} corresponding to detected link addition from {1} to {2} of type {3}; it may have been recently deleted",
                                                          source.WorkItem.Id, linkChange.SourceID, linkChange.TargetID, linkChange.LinkType));
                    }
                }
                else // Link deleted
                {
                    var deleteLinkChangeAction = new LinkChangeAction(
                        WellKnownChangeActionId.Delete,
                        new ToolkitLinking.ArtifactLink(linkChange.SourceID.ToString(),
                                                        new ToolkitLinking.Artifact(TfsWorkItemHandler.UriFromId(linkChange.SourceID.ToString()), WorkItemLinkTypeBase.s_sourceArtifactType),
                                                        new ToolkitLinking.Artifact(TfsWorkItemHandler.UriFromId(linkChange.TargetID.ToString()), WorkItemLinkTypeBase.s_targetArtifactType),
                                                        string.Empty, linkType),
                        LinkChangeAction.LinkChangeActionStatus.Created, false);
                    deleteLinkChangeAction.ServerLinkChangeId = linkChange.RowVersion.ToString();
                    linkChangeGroup.AddChangeAction(deleteLinkChangeAction);
                    actionAdded = true;
                }

                if (actionAdded)
                {
                    TraceManager.TraceVerbose("Adapter: Generating link change action: {0} '{1}'->'{2}' (Type: {3})",
                                              linkChange.IsActive ? "Add" : "Delete", linkChange.SourceID, linkChange.TargetID, linkChange.LinkType);
                }
            }

            return(linkChangeGroup);
        }
Exemple #23
0
        public override System.Collections.ObjectModel.ReadOnlyCollection <LinkChangeGroup> GenerateNextLinkDeltaSlice(
            LinkService linkService,
            int maxDeltaSliceSize)
        {
            try
            {
                var linkChangeGroups = new List <LinkChangeGroup>();

                if (null == ExtractLinkChangeActionsCallback)
                {
                    return(linkChangeGroups.AsReadOnly());
                }

                // load main Highwater Mark
                m_hwmLink.Reload();
                DateTime hwmLinkValue = m_hwmLink.Value;
                // search back 60 seconds to deal with potential WIT race condition
                if (!hwmLinkValue.Equals(default(DateTime)))
                {
                    hwmLinkValue = hwmLinkValue.AddSeconds(-60);
                }
                string hwmLinkValueStr = hwmLinkValue.ToString(CultureInfo.InvariantCulture);

                // load Work Items for extracting links
                string sourceId  = m_migrationSource.UniqueId;
                string storeName = m_migrationSource.WorkItemStore.StoreName;

                // Get items based on primary Highwater Mark
                TraceManager.TraceInformation(TfsWITAdapterResources.GettingModifiedItems, sourceId, storeName);
                IEnumerable <TfsMigrationWorkItem> items = m_migrationSource.WorkItemStore.GetItems(ref hwmLinkValueStr);
                TraceManager.TraceInformation(TfsWITAdapterResources.ReceivedModifiedItems, sourceId, storeName);

                // Record the updated HWM value
                DateTime wiqlExecutionTime = Convert.ToDateTime(hwmLinkValueStr, CultureInfo.InvariantCulture);

                // store to be used to analyze deleted links
                WorkItemLinkStore store = new WorkItemLinkStore(new Guid(sourceId));

                // extract links
                DateTime lastWorkITemUpdateTime = DateTime.MinValue;
                var      inMaxDeltaSliceSize    = maxDeltaSliceSize;
                foreach (TfsMigrationWorkItem tfsMigrationWorkItem in items)
                {
                    if (tfsMigrationWorkItem.WorkItem == null)
                    {
                        continue;
                    }

                    TraceManager.TraceInformation("Generating linking delta for Work Item: {0}", tfsMigrationWorkItem.WorkItem.Id.ToString());
                    var detectedLinkChangeGroups = new List <LinkChangeGroup>();
                    ExtractLinkChangeActionsCallback(tfsMigrationWorkItem, detectedLinkChangeGroups, store);

                    if (detectedLinkChangeGroups.Count == 0)
                    {
                        TraceManager.TraceInformation("Number of links: {0}", 0);
                        continue;
                    }

                    Dictionary <string, LinkChangeGroup> perWorkItemConsolidatedLinkChangeGroup = new Dictionary <string, LinkChangeGroup>();
                    for (int i = 0; i < detectedLinkChangeGroups.Count; ++i)
                    {
                        foreach (LinkChangeAction action in detectedLinkChangeGroups[i].Actions)
                        {
                            if (!perWorkItemConsolidatedLinkChangeGroup.ContainsKey(action.Link.SourceArtifact.Uri))
                            {
                                var linkChangeGroup = new LinkChangeGroup(
                                    action.Link.SourceArtifactId, LinkChangeGroup.LinkChangeGroupStatus.Created, false);
                                perWorkItemConsolidatedLinkChangeGroup.Add(action.Link.SourceArtifact.Uri, linkChangeGroup);
                            }
                            perWorkItemConsolidatedLinkChangeGroup[action.Link.SourceArtifact.Uri].AddChangeAction(action);
                        }
                    }

                    // always make sure that the currently analyzed work item has a link change group to represent it
                    // even though the group can be empty
                    if (!perWorkItemConsolidatedLinkChangeGroup.ContainsKey(tfsMigrationWorkItem.Uri))
                    {
                        perWorkItemConsolidatedLinkChangeGroup.Add(
                            tfsMigrationWorkItem.Uri,
                            new LinkChangeGroup(TfsWorkItemHandler.IdFromUri(tfsMigrationWorkItem.Uri), LinkChangeGroup.LinkChangeGroupStatus.Created, false));
                    }


                    foreach (var workItemLinkGroup in perWorkItemConsolidatedLinkChangeGroup)
                    {
                        string workItemIdStr = TfsWorkItemHandler.IdFromUri(workItemLinkGroup.Key);
                        TraceManager.TraceInformation("Detected {0} links for Work Item '{1}'",
                                                      workItemLinkGroup.Value.Actions.Count, workItemIdStr);

                        if (workItemLinkGroup.Key.Equals(tfsMigrationWorkItem.Uri, StringComparison.OrdinalIgnoreCase))
                        {
                            // VERY IMPORTANT: use the RelatedArtifactsStore to detect link deletion
                            store.UpdatePerItemLinkChangeGroupsByCheckingRelatedItemRecords(
                                workItemLinkGroup.Key, workItemLinkGroup.Value, this);
                        }
                        else
                        {
                            store.UpdatePerItemLinkChangeGroupsByCheckingRelatedItemRecordsWithoutImplicitDelete(
                                workItemLinkGroup.Key, workItemLinkGroup.Value, this);
                        }

                        if (workItemLinkGroup.Value.Actions.Count > 0)
                        {
                            linkChangeGroups.Add(workItemLinkGroup.Value);
                        }
                        maxDeltaSliceSize -= workItemLinkGroup.Value.Actions.Count;

                        if (maxDeltaSliceSize <= 0)
                        {
                            // size limit reached - persist groups to DB
                            linkService.AddChangeGroups(linkChangeGroups);
                            linkChangeGroups.Clear();
                            maxDeltaSliceSize = inMaxDeltaSliceSize;
                        }
                    }

                    DateTime lastRevChangedDate = tfsMigrationWorkItem.WorkItem.ChangedDate;

                    if (lastWorkITemUpdateTime.CompareTo(lastRevChangedDate) <= 0)
                    {
                        lastWorkITemUpdateTime = lastRevChangedDate;
                    }
                }

                // persist remaining groups to DB
                linkService.AddChangeGroups(linkChangeGroups);

                // clean up the returned link change group collection
                // when the caller (toolkit) receives an empty collection, it understands there is no more
                // delta to generate for the moment, and proceeds to next phase
                linkChangeGroups.Clear();

                // update primary Highwater Mark
                //m_hwmLink.Update(newHwmLinkValue);

                string newHwmValueStr = hwmLinkValueStr;
                if (lastWorkITemUpdateTime.Equals(DateTime.MinValue))
                {
                    // no changes in this sync cycle, record the wiql query execution time
                    m_hwmLink.Update(wiqlExecutionTime);
                }
                else
                {
                    // hwm is recorded in UTC, so does the WIQL query asof time
                    lastWorkITemUpdateTime = lastWorkITemUpdateTime.ToUniversalTime();

                    if (lastWorkITemUpdateTime.CompareTo(wiqlExecutionTime) <= 0)
                    {
                        // last work item rev time is earlier than wiql query execution time, use it as hwm
                        m_hwmLink.Update(lastWorkITemUpdateTime);
                        newHwmValueStr = lastWorkITemUpdateTime.ToString();
                    }
                    else
                    {
                        m_hwmLink.Update(wiqlExecutionTime);
                    }
                }
                TraceManager.TraceInformation("Persisted WIT linking HWM: {0}", Toolkit.Constants.HwmDeltaLink);
                TraceManager.TraceInformation(TfsWITAdapterResources.UpdatedHighWatermark, newHwmValueStr);

                return(linkChangeGroups.AsReadOnly());
            }
            catch (Exception exception)
            {
                MigrationConflict genericeConflict = WitGeneralConflictType.CreateConflict(exception);
                var conflictManager = m_conflictManager.GetService(typeof(ConflictManager)) as ConflictManager;
                Debug.Assert(null != conflictManager);
                List <MigrationAction>   resolutionActions;
                ConflictResolutionResult resolveRslt =
                    conflictManager.TryResolveNewConflict(conflictManager.SourceId, genericeConflict, out resolutionActions);
                Debug.Assert(!resolveRslt.Resolved);
                return(new List <LinkChangeGroup>().AsReadOnly());
            }
        }
        private bool SubmitWorkItemLinkChanges(
            LinkChangeGroup linkChanges,
            ServiceContainer serviceContainer,
            ConfigurationService configService,
            ITranslationService translationService,
            TfsLinkingProviderBase.LinkSubmissionPhase submissionPhase)
        {
            var linkChangeActions = ExtractWorkItemLinkChanges(linkChanges);

            if (linkChangeActions.Count == 0)
            {
                return(true);
            }

            ConflictManager conflictManageer         = serviceContainer.GetService(typeof(ConflictManager)) as ConflictManager;
            var             updatedocsForEditLinks   = new List <XmlDocument>(linkChangeActions.Count);
            var             updateDocsForAddLinks    = new List <XmlDocument>(linkChangeActions.Count);
            var             updateDocsForDeleteLinks = new List <XmlDocument>(linkChangeActions.Count);
            Dictionary <int, LinkChangeAction> docForEditlinksToActionMap   = new Dictionary <int, LinkChangeAction>();
            Dictionary <int, LinkChangeAction> docForAddlinksToActionMap    = new Dictionary <int, LinkChangeAction>();
            Dictionary <int, LinkChangeAction> docForDeletelinksToActionMap = new Dictionary <int, LinkChangeAction>();

            for (int i = 0; i < linkChangeActions.Count; ++i)
            {
                if (linkChangeActions[i].Status != LinkChangeAction.LinkChangeActionStatus.ReadyForMigration ||
                    linkChangeActions[i].IsConflicted)
                {
                    continue;
                }

                if (!ProcessActionInCurrentSubmissionPhase(linkChangeActions[i], submissionPhase))
                {
                    continue;
                }

                var tfsUpdateDocument = InitializeUpdateDocument();

                var handler = linkChangeActions[i].Link.LinkType as ILinkHandler;
                Debug.Assert(null != handler);

                handler.UpdateTfs(tfsUpdateDocument, linkChangeActions[i]);

                if (linkChangeActions[i].ChangeActionId.Equals(WellKnownChangeActionId.Add))
                {
                    docForAddlinksToActionMap.Add(updateDocsForAddLinks.Count, linkChangeActions[i]);
                    updateDocsForAddLinks.Add(tfsUpdateDocument.UpdateDocument);
                }
                else if (linkChangeActions[i].ChangeActionId.Equals(WellKnownChangeActionId.Delete))
                {
                    docForDeletelinksToActionMap.Add(updateDocsForDeleteLinks.Count, linkChangeActions[i]);
                    updateDocsForDeleteLinks.Add(tfsUpdateDocument.UpdateDocument);
                }
                else if (linkChangeActions[i].ChangeActionId.Equals(WellKnownChangeActionId.Edit))
                {
                    docForEditlinksToActionMap.Add(updatedocsForEditLinks.Count, linkChangeActions[i]);
                    updatedocsForEditLinks.Add(tfsUpdateDocument.UpdateDocument);
                }
                else
                {
                    TraceManager.TraceVerbose("Change action '{0}' in Link Change Group '{1}' is not supported.",
                                              linkChangeActions[i].ChangeActionId.ToString(), linkChanges.GroupName);
                    linkChangeActions[i].Status = LinkChangeAction.LinkChangeActionStatus.Completed;
                }
            }

            bool succeeded = true;

            if (updatedocsForEditLinks.Count > 0)
            {
                succeeded &= SubmitBatchedAddOrDeleteLinkChanges(
                    updatedocsForEditLinks, docForEditlinksToActionMap, translationService, configService, conflictManageer);
            }
            if (updateDocsForDeleteLinks.Count > 0)
            {
                succeeded &= SubmitBatchedAddOrDeleteLinkChanges(
                    updateDocsForDeleteLinks, docForDeletelinksToActionMap, translationService, configService, conflictManageer);
            }
            if (updateDocsForAddLinks.Count > 0)
            {
                succeeded &= SubmitBatchedAddOrDeleteLinkChanges(
                    updateDocsForAddLinks, docForAddlinksToActionMap, translationService, configService, conflictManageer);
            }
            return(succeeded);
        }
Exemple #25
0
        public override void ExtractLinkChangeActions(TfsMigrationWorkItem source, List <LinkChangeGroup> linkChangeGroups, WorkItemLinkStore store)
        {
            if (null == source)
            {
                throw new ArgumentNullException("source");
            }

            if (null == source.WorkItem)
            {
                throw new ArgumentException("source.WorkItem is null");
            }

            var linkChangeGroup = new LinkChangeGroup(
                source.WorkItem.Id.ToString(CultureInfo.InvariantCulture), LinkChangeGroup.LinkChangeGroupStatus.Created, false);

            foreach (Link l in source.WorkItem.Links)
            {
                RelatedLink rl = l as RelatedLink;

                if (rl != null)
                {
                    // v1 work item related link does not have direction info
                    // to avoid generating two link change actions for the same link
                    // we only pick one from the work item of smaller id
                    if (source.WorkItem.Id >= rl.RelatedWorkItemId)
                    {
                        continue;
                    }

                    #region TFS 2010 specific logic
                    if (rl.LinkTypeEnd != null &&
                        rl.LinkTypeEnd.LinkType != null)
                    {
                        if (rl.LinkTypeEnd.LinkType.ReferenceName.Equals(Tfs2010RelatedLinkTypeReferenceName, StringComparison.OrdinalIgnoreCase))
                        {
                            #endregion

                            var link = new Toolkit.Linking.ArtifactLink(
                                source.WorkItem.Id.ToString(CultureInfo.InvariantCulture),
                                new Toolkit.Linking.Artifact(source.Uri, s_sourceArtifactType),
                                new Toolkit.Linking.Artifact(TfsWorkItemHandler.UriFromId(rl.RelatedWorkItemId.ToString(CultureInfo.InvariantCulture)), s_targetArtifactType),
                                rl.Comment, this, rl.IsLocked);
                            linkChangeGroup.AddChangeAction(new LinkChangeAction(WellKnownChangeActionId.Add, link,
                                                                                 LinkChangeAction.LinkChangeActionStatus.Created,
                                                                                 false));
                        }
                    }
                    else
                    {
                        var link = new Toolkit.Linking.ArtifactLink(
                            source.WorkItem.Id.ToString(CultureInfo.InvariantCulture),
                            new Toolkit.Linking.Artifact(source.Uri, s_sourceArtifactType),
                            new Toolkit.Linking.Artifact(TfsWorkItemHandler.UriFromId(rl.RelatedWorkItemId.ToString(CultureInfo.InvariantCulture)), s_targetArtifactType),
                            rl.Comment,
                            this);
                        linkChangeGroup.AddChangeAction(new LinkChangeAction(WellKnownChangeActionId.Add, link,
                                                                             LinkChangeAction.LinkChangeActionStatus.Created,
                                                                             false));
                    }
                }
            }

            linkChangeGroups.Add(linkChangeGroup);
        }
        protected bool SubmitNonWorkItemLinkChanges(
            LinkChangeGroup linkChanges,
            ServiceContainer serviceContainer,
            ConfigurationService configService,
            ITranslationService translationService,
            TfsLinkingProviderBase.LinkSubmissionPhase submissionPhase)
        {
            // group non-WorkItemLink changes by work item Id
            Dictionary <int, List <LinkChangeAction> > perWorkItemLinkChanges = RegroupLinkChangeActions(linkChanges);
            var orderedWorkitemId = new Dictionary <int, int>();
            int index             = 0;

            foreach (int workItemId in perWorkItemLinkChanges.Keys)
            {
                orderedWorkitemId.Add(index++, workItemId);
            }

            // batch-submit links of each work item
            var updateDocs = new List <XmlDocument>(perWorkItemLinkChanges.Count);

            foreach (var perWorkItemLinkChange in perWorkItemLinkChanges)
            {
                if (perWorkItemLinkChange.Value.Count == 0)
                {
                    continue;
                }

                WorkItem workItem = WorkItemStore.GetWorkItem(perWorkItemLinkChange.Key);

                var tfsUpdateDocument = InitializeUpdateDocument();
                tfsUpdateDocument.CreateWorkItemUpdateDoc(workItem);
                bool hasNonWorkItemLinkChanges = false;
                foreach (LinkChangeAction linkChangeAction in perWorkItemLinkChange.Value)
                {
                    if (linkChangeAction.Status != LinkChangeAction.LinkChangeActionStatus.ReadyForMigration ||
                        linkChangeAction.IsConflicted ||
                        linkChangeAction.Link.LinkType is WorkItemLinkTypeBase)
                    {
                        continue;
                    }

                    if (!ProcessActionInCurrentSubmissionPhase(linkChangeAction, submissionPhase))
                    {
                        continue;
                    }

                    hasNonWorkItemLinkChanges = true;
                    var handler = linkChangeAction.Link.LinkType as ILinkHandler;
                    Debug.Assert(null != handler);
                    handler.UpdateTfs(tfsUpdateDocument, linkChangeAction);
                }

                if (hasNonWorkItemLinkChanges)
                {
                    updateDocs.Add(tfsUpdateDocument.UpdateDocument);
                }
            }

            if (updateDocs.Count == 0)
            {
                return(true);
            }

            UpdateResult[] results = TfsBatchUpdateHelper.Submit(Core, WorkItemServer, updateDocs.ToArray());

            if (results.Length != updateDocs.Count)
            {
                throw new SynchronizationEngineException("Wrong number of link update results.");
            }

            bool succeeded = true;

            for (int i = 0; i < results.Length; ++i)
            {
                UpdateResult rslt = results[i];

                if (rslt.Exception != null &&
                    !rslt.Exception.Message.Contains("The specified link already exists"))
                {
                    TraceManager.TraceError(rslt.Exception.ToString());
                    succeeded = false;
                    // TODO
                    // Try resolve conflict and push to backlog if resolution fails
                    foreach (LinkChangeAction action in perWorkItemLinkChanges[orderedWorkitemId[i]])
                    {
                        action.IsConflicted = true;
                    }
                }
                else
                {
                    foreach (LinkChangeAction action in perWorkItemLinkChanges[orderedWorkitemId[i]])
                    {
                        if (ProcessActionInCurrentSubmissionPhase(action, submissionPhase))
                        {
                            MarkLinkChangeActionCompleted(action);
                        }
                    }

                    if (rslt.Exception == null)
                    {
                        UpdateLinkConversionHistory(configService, translationService, rslt, perWorkItemLinkChanges[orderedWorkitemId[i]]);
                    }
                    else if (rslt.Exception.Message.Contains("The specified link already exists"))
                    {
                        WorkItemLinkStore relatedArtifactsStore = new WorkItemLinkStore(configService.SourceId);
                        relatedArtifactsStore.UpdateSyncedLinks(perWorkItemLinkChanges[orderedWorkitemId[i]]);
                    }
                }
            }
            return(succeeded);
        }