public override BugDictionary CreateBugs(string xmlfile, Progress progress) { #region Pre Condition Debug.Assert(xmlfile != null); #if DEBUG System.Console.WriteLine("CreateBugs(" + xmlfile + ")"); #endif #endregion BugDictionary bugs = new BugDictionary(); XmlDocument doc = new XmlDocument(); doc.XmlResolver = null; // Prevents it from searching for the bugzilla dtd (incase it is not accessible. doc.Load(xmlfile); foreach (XmlNode node in doc.SelectNodes("/bugzilla/bug")) { Bug bug = new Bug(); bug.Id = int.Parse(node.SelectNodes("bug_id")[0].InnerText); bug.Status = node.SelectNodes("bug_status")[0].InnerText; if (null != node.SelectNodes("resolution")[0]) { bug.Resolution = node.SelectNodes("resolution")[0].InnerText; } if (null != node.SelectNodes("target_milestone")[0]) { bug.Milestone = node.SelectNodes("target_milestone")[0].InnerText; } if (null != node.SelectNodes("rep_platform")[0]) { bug.Platform = node.SelectNodes("rep_platform")[0].InnerText; } if (null != node.SelectNodes("keywords")[0]) { bug.Keywords = node.SelectNodes("keywords")[0].InnerText; } if (null != node.SelectNodes("op_sys")[0]) { bug.OS = node.SelectNodes("op_sys")[0].InnerText; } if (null != node.SelectNodes("qa_contact")[0]) { bug.QAContact = node.SelectNodes("qa_contact")[0].InnerText; } bug.Summary = node.SelectNodes("short_desc")[0].InnerText; bug.Owner = node.SelectNodes("assigned_to")[0].Attributes[0].InnerText; bug.Priority = node.SelectNodes("priority")[0].InnerText; bug.CreationDate = node.SelectNodes("creation_ts")[0].InnerText; bug.Severity = node.SelectNodes("bug_severity")[0].InnerText; bug.Product = node.SelectNodes("product")[0].InnerText; bug.Component = node.SelectNodes("component")[0].InnerText; bug.Version = node.SelectNodes("version")[0].InnerText; bug.Reporter = node.SelectNodes("reporter")[0].InnerText; #region Actual Time, Estimated Time, Remaining Time if (node.SelectNodes("actual_time").Count > 0) { bug.ActualTime = Convert.ToDouble(node.SelectNodes("actual_time")[0].InnerText); } else { bug.ActualTime = Convert.ToDouble(Config.GetSystem("DefaultBugDuration")); } if (node.SelectNodes("estimated_time").Count > 0) { bug.OriginalTimeEstimate = Convert.ToDouble(node.SelectNodes("estimated_time")[0].InnerText); } else { bug.OriginalTimeEstimate = Convert.ToDouble(Config.GetSystem("DefaultBugDuration")); } if (node.SelectNodes("remaining_time").Count > 0) { bug.RemainingTime = Convert.ToDouble(node.SelectNodes("remaining_time")[0].InnerText); } else { bug.RemainingTime = Convert.ToDouble(Config.GetSystem("DefaultBugDuration")); } #endregion foreach (XmlNode depNode in node.SelectNodes("dependson")) { bug.DependsOn.Add(Convert.ToInt32(depNode.InnerText)); } foreach (XmlNode depNode in node.SelectNodes("blocked")) { bug.Blocks.Add(Convert.ToInt32(depNode.InnerText)); } bugs.Add(bug.Id, bug); if (null != progress) { progress.UpdateProgress(1, "Reading " + bug.Id + " from " + xmlfile + "."); } } #region Post Condition Debug.Assert(bugs != null); #endregion return(bugs); }
/// <summary> /// Takes a bug and places the data from the bug into the Project Task. /// </summary> /// <param name="bug">Bug with Info</param> /// <param name="task">Task to get the Info</param> public void UpdateProjectTask(Bug bug, Task task) { #region Pre Condition Debug.Assert(null != _dataMap); #endregion bool found = false; #region Crazy Reflection Code _project.DefaultWorkUnits = PjUnit.pjHour; Type myTaskType = typeof(Microsoft.Office.Interop.MSProject.Task); System.Reflection.PropertyInfo[] taskPropInfo = myTaskType.GetProperties(); Debug.Assert(Program.ASSUMPTION_Task_Number1_to_BugID, "Need to do some majic with the mapping here"); foreach (System.Reflection.PropertyInfo taskInfo in taskPropInfo) { found = false; foreach (object obj in _dataMap.GetEnumerator()) { KeyValuePair <string, string> de = (KeyValuePair <string, string>)obj; if (taskInfo.Name == (string)de.Value) { if (!found) { // Take care of the users property mapping from the XML Type myBugType = typeof(Bug); System.Reflection.PropertyInfo[] bugPropInfo = myBugType.GetProperties(); foreach (System.Reflection.PropertyInfo bugInfo in bugPropInfo) { if (bugInfo.Name == (string)de.Key) { if ((String.Compare("blocks", de.Key, true) == 0) && (!found)) { string s = bug.BlocksAsString(); taskInfo.SetValue(task, bug.BlocksAsString(), null); found = true; } else if ((String.Compare("dependson", de.Key, true) == 0) && (!found)) { string s = bug.BlocksAsString(); taskInfo.SetValue(task, bug.DependsOnAsString(), null); found = true; } else { // Stupid unit conversion. If we are doing a duration field, we need to fiddle with units. if (taskInfo.Name.StartsWith("Duration", StringComparison.OrdinalIgnoreCase)) { taskInfo.SetValue(task, Convert.ToString((double)bugInfo.GetValue(bug, null)) + " hrs", null); } else { taskInfo.SetValue(task, bugInfo.GetValue(bug, null), null); } found = true; } } if (found) { break; } } } // TODO: If not found in foreach, try custom fields } if (found) { break; } } } #endregion Debug.Assert(null != _priorityDataMap); if (_priorityDataMap.ContainsKey(bug.Priority)) { task.Priority = Convert.ToInt16(_priorityDataMap[bug.Priority]); } else { if (_priorityDataMap.ContainsKey("undefined")) { task.Priority = Convert.ToInt16(_priorityDataMap["undefined"]); } else { task.Priority = 501; } } // Don't reverse these lines. Project re-calculates fields as you set // the values, and changing the order breaks things. task.ActualWork = bug.ActualTime.ToString() + " hrs"; task.RemainingWork = bug.RemainingTime.ToString() + " hrs"; // Bug has no more work to be done. if (bug.Status.Contains("FIXED") || bug.Status.Contains("INVALID") || bug.Status.Contains("WONTFIX") || bug.Status.Contains("WORKSFORME") || bug.Status.Contains("LATER") || bug.Status.Contains("REMIND")) { task.PercentComplete = "100%"; task.ActualWork = bug.ActualTime + " hrs"; task.ActualDuration = bug.ActualTime + " hrs"; task.RemainingWork = bug.RemainingTime + " hrs"; } else { // Ensure that the tasks are placed to the current date. // task.ConstraintType = (short)Microsoft.Office.Project.Server.Library.Task.ConstraintType.StartNoEarlierThan; task.ConstraintType = 4; task.ConstraintDate = DateTime.Now; } }
public override BugDictionary CreateBugs(string csvfile, Progress progress) { Dictionary <int, string> Headers; DataTable csvTable; BugDictionary bugs; Bug bug; #region Pre Condition Debug.Assert("" != csvfile); #endregion Headers = new Dictionary <int, string>(); csvTable = CSVParse(csvfile); bugs = new BugDictionary(); #region Header // Use the header row to make a map of where stuff goes //string[] csvHeaders = csvTable[0]; int index = 0; foreach (string header in csvTable.Rows[0].ItemArray) { Headers.Add(index, header); index++; } #endregion #region Verification // Write code to ensure that we have enough of the fields #endregion #region Data Row Parse DataRow row; for (int i = 1; i < csvTable.Rows.Count; i++) { row = csvTable.Rows[i]; bug = new Bug(); for (int j = 0; j < row.ItemArray.Length; j++) { if (Headers.ContainsKey(j) && (null != row.ItemArray[j]) && (false == (row.ItemArray[j] is System.DBNull)) && (null != row.ItemArray[j]) && ("" != (string)row.ItemArray[j])) { CSVBugPopulate(bug, Headers[j], (string)row.ItemArray[j]); } } // This deals with the case of null rows at the end. if (0 != bug.Id) { bugs.Add(bug.Id, bug); } if (null != progress) { progress.UpdateProgress(1, "Reading " + bug.Id + " from " + csvfile + "."); } } #endregion #region Post Condition foreach (KeyValuePair <int, Bug> kvp in bugs) { bug = ((Bug)kvp.Value); Debug.Assert(0 != bug.Id); Debug.Assert((null != bug.Summary) && ("" != bug.Summary)); } #endregion return(bugs); }
/// <summary> /// Takes a listing of bugs delegates the creation of project tasks. /// </summary> /// <param name="bugs"></param> /// <remarks>This makes the assumption that the Task.Number1 field is always avaible for us to use. This is our bug key.</remarks> public void CreateProjectTasks(BugDictionary bugs, Progress progress) { ArrayList orphanTasks = new ArrayList(); Dictionary <int, Task> bugzillaTasks = new Dictionary <int, Task>(); Dictionary <int, Bug> deepCopyBugs = new Dictionary <int, Bug>(); bool foundStartHolder = false; #region Create Bugs Deep Copy // We need to make a deep copy of the bugs since we need to remove // them from the list as we add them to the list, and doing this // to the active dictionary would be bad, and adding another // variable to the dictionary to indicate what has been removed // was going to be a pain. foreach (KeyValuePair <int, Bug> kvp in bugs) { deepCopyBugs.Add(kvp.Key, kvp.Value); } #endregion #region Set Microsoft Project Configuration _project = _projectApp.ActiveProject; _project.DefaultWorkUnits = PjUnit.pjHour; _project.DefaultDurationUnits = PjUnit.pjHour; #region Show Fields in table if (ShowAllBugzillaFieldsInProject) { // THIS IS HARD CODED, it should be made reflective. foreach (KeyValuePair <string, string> de in _dataMap.GetEnumerator()) { if (de.Key != "Owner") { // BUG: Don't just eat the exception. Figure out how to update the column properly. try { _project.Application.SelectTaskColumn(de.Value, Missing.Value, Missing.Value, Missing.Value); _project.Application.ColumnDelete(); } catch (Exception) { } try { _project.Application.TableEdit("&Entry", true, Missing.Value, true, Missing.Value, Missing.Value, de.Value, de.Key, Missing.Value, 0, true, true, 255, Missing.Value, Missing.Value, 1, Missing.Value, Missing.Value); _project.Application.TableApply("&Entry"); } catch (Exception) { } } } try { _project.Application.TableEdit("&Entry", true, Missing.Value, true, Missing.Value, Missing.Value, "Remaining Work", "Remaining Work", Missing.Value, 0, true, true, 255, Missing.Value, Missing.Value, 1, Missing.Value, Missing.Value); _project.Application.TableApply("&Entry"); } catch (Exception) { } try { _project.Application.TableEdit("&Entry", true, Missing.Value, true, Missing.Value, Missing.Value, "Actual Work", "Actual Work", Missing.Value, 0, true, true, 255, Missing.Value, Missing.Value, 1, Missing.Value, Missing.Value); _project.Application.TableApply("&Entry"); } catch (Exception) { } try { _project.Application.TableEdit("&Entry", true, Missing.Value, true, Missing.Value, Missing.Value, "Priority", "Priority", Missing.Value, 0, true, true, 255, Missing.Value, Missing.Value, 1, Missing.Value, Missing.Value); _project.Application.TableApply("&Entry"); } catch (Exception) { } } #endregion #endregion #region Start Task foreach (Task task in _project.Tasks) { if (task.Name == "Today") { startHolderId = task.ID; foundStartHolder = true; break; } } if (false == foundStartHolder) { Task task = _project.Tasks.Add("Today", 1); task.PercentComplete = "100%"; task.ActualWork = 0; task.Milestone = true; task.RemainingWork = 0; startHolderId = task.ID; foundStartHolder = true; task.Start = DateTime.Now; } #endregion #region Update Existing Tasks Debug.Assert(startHolderId != 0); Debug.Assert(foundStartHolder); foreach (Task task in _project.Tasks) { if (deepCopyBugs.ContainsKey((int)task.Number1)) { Debug.Assert(Program.ASSUMPTION_Task_Number1_to_BugID); Bug bug = deepCopyBugs[(int)task.Number1]; deepCopyBugs.Remove(bug.Id); bug.ProjectTaskId = task.ID; if ((null == task.Predecessors) || ("" == task.Predecessors)) { task.Predecessors = startHolderId.ToString(); } else { task.Predecessors += ", " + startHolderId.ToString(); } UpdateProjectTask(bug, task); bugzillaTasks.Add(bug.Id, task); } else { // Probably shoudl do something here... // Debug.Assert(false, "Task \"" + task.Summary + "\" exists in project but not in bugzilla."); } progress.UpdateProgress(1, "Scanning project task " + task.Name + "."); } #endregion #region Create New Tasks foreach (Bug bug in deepCopyBugs.Values) { Task task = _project.Tasks.Add(bug.Summary, 2); Debug.Assert(null != bug); Debug.Assert(bug.Id != 0); Debug.Assert(null != task); UpdateProjectTask(bug, task); bug.ProjectTaskId = task.ID; bugzillaTasks.Add(bug.Id, task); progress.UpdateProgress(1, "Created task from bug " + bug.Id + "."); } #endregion #region Debug Verification Debug.Assert(bugs.Count == bugzillaTasks.Count); #endregion #region Set any Dependencies as defined in bugzilla foreach (KeyValuePair <int, Task> obj in bugzillaTasks) { Task task = (Task)(obj).Value; // Set dependency to today. if (("" == task.Predecessors) || (null == task.Predecessors)) { task.Predecessors += startHolderId.ToString(); } else { task.Predecessors = task.Predecessors + ", " + startHolderId.ToString(); } // Get the bug for the task Debug.Assert(Program.ASSUMPTION_Task_Number1_to_BugID); Debug.Assert(bugs.ContainsKey((int)task.Number1)); Bug bug = bugs[(int)task.Number1]; Debug.Assert(null != bug); // Search for any depends on in the bug foreach (int depNum in bug.Blocks) { Debug.Assert(0 != bug.ProjectTaskId); if (false == bugzillaTasks.ContainsKey(depNum)) { System.Windows.Forms.MessageBox.Show("There is a dependency reference to a bug which is not contained in your search. Please re-define your search.", "Projzilla Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error); return; } Task myTask = bugzillaTasks[depNum]; if (("" == myTask.Predecessors) || (null == myTask.Predecessors)) { myTask.Predecessors = task.ID.ToString(); } else { string preds; preds = myTask.Predecessors + ", " + task.ID.ToString(); myTask.Predecessors = preds; } } progress.UpdateProgress(1, "Scanning and updating dependencies."); } #endregion }
/// <summary> /// Given the CSV key, this will place it into the bug. /// We should really revisit this code since it is hacky. /// </summary> /// <param name="bug"></param> /// <param name="csvKey"></param> /// <param name="value"></param> private void CSVBugPopulate(Bug bug, string csvKey, string value) { #region Pre Condition Debug.Assert("" != csvKey); Debug.Assert(null != bug); #endregion if ("" == value) { return; } switch (csvKey) { case "bug_id": bug.Id = int.Parse(value); break; case "bug_severity": bug.Severity = CleanCSVDataField(value); break; case "priority": bug.Priority = CleanCSVDataField(value); break; case "op_sys": bug.OS = CleanCSVDataField(value); break; case "assigned_to": bug.Owner = CleanCSVDataField(value); break; case "bug_status": bug.Status = CleanCSVDataField(value); break; case "resolution": bug.Resolution = CleanCSVDataField(value); break; case "short_short_desc": case "short_desc": bug.Summary = CleanCSVDataField(value); break; case "estimated_time": bug.OriginalTimeEstimate = Convert.ToDouble(value); break; case "remaining_time": bug.RemainingTime = Convert.ToDouble(value); break; case "actual_time": bug.ActualTime = Convert.ToDouble(value); break; case "target_milestone": bug.Milestone = CleanCSVDataField(value); break; case "assigned_to_realname": bug.Owner = CleanCSVDataField(value); break; case "rep_platform": bug.Platform = CleanCSVDataField(value); break; case "reporter": bug.Reporter = CleanCSVDataField(value); break; case "product": bug.Product = CleanCSVDataField(value); break; case "component": bug.Component = CleanCSVDataField(value); break; case "version": bug.Version = CleanCSVDataField(value); break; case "keywords": bug.Keywords = CleanCSVDataField(value); break; case "opendate": bug.CreationDate = CleanCSVDataField(value); break; // These ones have no mapping because CSV doesn't give them // or we don't use them. case "reporter_realname": case "changeddate": case "percentage_complete": break; default: break; } #region Post Condition #endregion }