/// <summary> /// Saves a tree of work items in the document, merging them with any existing work items. /// </summary> /// <param name="workItems">The work items to be saved.</param> /// <param name="fields">The fields in the work item to be saved.</param> /// <param name="cancellationToken">Used to cancel the save.</param> public void SaveWorkItems(WorkItemTree workItems, string[] fields, CancellationToken cancellationToken) { if (workItems == null) { throw new ArgumentNullException("workItems"); } ITfsWorkItem[] workItemList = workItems.DepthFirstNodes().Select(node => node.WorkItem).ToArray(); this.workItemManager.AddRange(workItemList); this.queryWorkItems.Add(new QueryWorkItems(this.queryWorkItems.Count, workItemList.Select(wi => wi.Id).ToArray())); this.SaveQueryWorkItems(); this.SaveWorkItemsInWorkItemManager(fields, cancellationToken); this.mostRecentlySavedWorkItems = workItems; }
/// <summary> /// Maps work items into the document using the given layout. Each work item is bookmarked. /// </summary> /// <param name="workItems">The work items to be mapped into the document.</param> /// <param name="layout">The layout to be used to map the saved work items.</param> /// <param name="bookmarkNamingFunction">A function to return the bookmark to use for the given work item id.</param> /// <param name="cancellationToken">Used to cancel the save.</param> /// <remarks> /// It is assumed that the document already contains the XML data for the work items. /// </remarks> public void MapWorkItemsIntoDocument(WorkItemTree workItems, LayoutInformation layout, Func <int, string> bookmarkNamingFunction, CancellationToken cancellationToken) { if (workItems == null) { throw new ArgumentNullException("workItems"); } if (layout == null) { throw new ArgumentNullException("layout"); } if (bookmarkNamingFunction == null) { throw new ArgumentNullException("bookmarkNamingFunction"); } DateTime start = DateTime.Now; int count = 0; CustomXMLPart part = this.wordDocument.GetXmlPart(Constants.WorkItemNamespace); if (this.wordDocument.IsAtStart()) { this.wordDocument.InsertParagraph(ModelResources.FormatterStartOfImportBoilerPlate, Constants.NormalStyleName); } foreach (WorkItemTreeNode node in workItems.DepthFirstNodes()) { cancellationToken.ThrowIfCancellationRequested(); count++; IWorkItemLayout workItemLayout = new WorkItemLayout(layout, this.teamProjectTemplate); this.MapWorkItemIntoDocument(node, workItemLayout, bookmarkNamingFunction, part, InsertionPoint.CurrentLocation, 0); } if (this.wordDocument.IsAtEnd()) { this.wordDocument.InsertParagraph(ModelResources.FormatterEndOfImportBoilerPlate, Constants.NormalStyleName); } DateTime end = DateTime.Now; this.logger.Log(TraceEventType.Information, "Elapsed time to insert {0} items was {1} seconds", count, (end - start).TotalSeconds); }
/// <summary> /// Runs a tree query. /// </summary> /// <param name="query">The query to execute.</param> /// <param name="cancellationToken">Used to cancel the operation.</param> /// <returns>A tree of work items.</returns> private static WorkItemTree RunTreeQuery(ITfsQuery query, CancellationToken cancellationToken) { WorkItemTree ans = new WorkItemTree(); WorkItemLinkInfo[] wilis = query.RunLinkQuery(cancellationToken); int[] ids = new int[wilis.Length]; for (int i = 0; i < ids.Length; i++) { ids[i] = wilis[i].TargetId; } string workItemQueryString = QueryUtilities.ConvertTreeQueryToQueryForItem(query); IList <ITfsWorkItem> workItems = query.WorkItemStore.Query(ids.Distinct().ToArray(), workItemQueryString); for (int i = 0; i < wilis.Length; i++) { WorkItemLinkInfo wili = wilis[i]; ITfsWorkItem wi = workItems.Select(item => item).Where(item => item.Id == wili.TargetId).Single(); if (wili.SourceId <= 0) { ans.RootNodes.Add(new WorkItemTreeNode(wi, 0)); } else { WorkItemTreeNode parent = null; try { parent = ans.DepthFirstNodes().Where(node => node.WorkItem.Id == wili.SourceId).Single(); } catch (InvalidOperationException) { throw new InvalidOperationException(ModelResources.QueryNotWellFormedTree); } parent.Children.Add(new WorkItemTreeNode(wi, parent.Level + 1)); } } return(ans); }
/// <summary> /// Refreshes the work items in the document. /// </summary> /// <remarks> /// This call will update the rich text content controls which are not bound to the Custom XML Parts. /// </remarks> /// <param name="cancellationToken">Used to cancel the save.</param> /// <returns>List of verification errors, empty if there were no errors.</returns> public IEnumerable <string> RefreshWorkItems(CancellationToken cancellationToken) { IEnumerable <string> ans; if (this.queryAndLayoutManager == null) { throw new InvalidOperationException(ModelResources.TeamProjectNotSet); } ans = this.verifier.VerifyDocument(this.queryWorkItems.ToArray(), Utilities.BookmarkNamingFunction, Utilities.BookmarkParsingFunction, Utilities.XpathParsingFunction); if (ans.Count() == 0) { this.workItemManager.Clear(); List <QueryWorkItems> afterQueryWorkItems = new List <QueryWorkItems>(); foreach (QueryAndLayoutInformation queryAndLayout in this.queryAndLayoutManager.FinalQueriesAndLayouts) { cancellationToken.ThrowIfCancellationRequested(); QueryDefinition finalQuery = queryAndLayout.Query; WorkItemTree workItems = this.teamProject.QueryRunner.QueryForWorkItems(finalQuery, cancellationToken); afterQueryWorkItems.Add(new QueryWorkItems(afterQueryWorkItems.Count, workItems.DepthFirstNodes().ToArray())); this.workItemManager.AddRange(workItems.DepthFirstNodes().Select(node => node.WorkItem).ToArray()); } string[] fields = this.queryAndLayoutManager.AllLayoutFields.ToArray(); FormatterRefreshData refreshData = new FormatterRefreshData { WorkItemManager = this.workItemManager, QueryWorkItemsBefore = this.queryWorkItems.ToArray(), QueryWorkItemsAfter = afterQueryWorkItems.ToArray(), Layouts = this.queryAndLayoutManager.FinalQueriesAndLayouts.Select(qli => qli.Layout), QueryIsFlat = this.queryAndLayoutManager.FinalQueriesAndLayouts.Select(qli => qli.Query.QueryType == QueryType.List) }; this.formatter.RefreshWorkItems(refreshData, (int qi, int id) => Utilities.QuerySpecificBookmarkNamingFunction(qi)(id), cancellationToken); this.queryWorkItems = afterQueryWorkItems; this.SaveWorkItemsInWorkItemManager(fields, cancellationToken); this.SaveQueryWorkItems(); } return(ans); }