public Project AddTaskLink(TaskId predecessorId, TaskId successorId, TaskLinkType type = TaskLinkType.FinishToStart, TimeSpan lag = default) { var taskLink = TaskLink.Create(predecessorId, successorId, type, lag); return(AddTaskLink(taskLink)); }
private static ProjectData SetTaskPredecessorsOrSuccessors(ProjectData project, TaskId id, string value, bool isSuccessors) { var linkField = isSuccessors ? TaskFields.SuccessorLinks : TaskFields.PredecessorLinks; value = value.Trim(); var predecessorsBuilder = ImmutableArray.CreateBuilder <TaskId>(); var remainingTaskLinks = project.Get(linkField, id).ToList(); if (value.Length > 0) { var parts = value.Split(','); foreach (var part in parts) { var partText = part.Trim(); var taskText = partText; var sign = Math.Max(partText.IndexOf('+'), partText.IndexOf('-')); var lag = TimeSpan.Zero; if (sign >= 0) { var lagText = partText.Substring(sign).Trim(); lag = project.Information.TimeConversion.ParseDuration(lagText); taskText = partText.Substring(0, sign).Trim(); } var taskOrdinalText = taskText; var linkType = (TaskLinkType?)null; if (taskText.EndsWith("FS", StringComparison.OrdinalIgnoreCase)) { linkType = TaskLinkType.FinishToStart; } else if (taskText.EndsWith("SS", StringComparison.OrdinalIgnoreCase)) { linkType = TaskLinkType.StartToStart; } else if (taskText.EndsWith("FF", StringComparison.OrdinalIgnoreCase)) { linkType = TaskLinkType.FinishToFinish; } else if (taskText.EndsWith("SF", StringComparison.OrdinalIgnoreCase)) { linkType = TaskLinkType.StartToFinish; } if (linkType != null) { taskOrdinalText = taskText.Substring(0, taskText.Length - 2).Trim(); } else if (sign < 0) { linkType = TaskLinkType.FinishToStart; } else { throw new FormatException($"'{partText}' isn't a valid value"); } if (!int.TryParse(taskOrdinalText, out var taskOrdinal)) { throw new FormatException($"'{taskOrdinalText}' isn't a valid int"); } var taskId = project.GetTask(taskOrdinal); if (taskId.IsDefault) { throw new FormatException($"'{taskOrdinal}' isn't a valid task"); } var predecessorId = isSuccessors ? id : taskId; var successorId = isSuccessors ? taskId : id; var taskLink = TaskLink.Create(predecessorId, successorId, linkType.Value, lag); var existingLink = project.GetTaskLink(predecessorId, successorId); if (existingLink != null) { project = project.RemoveTaskLink(existingLink); } else if (project.TaskLinkCausesCycle(taskLink)) { var predecessorOrdinal = project.Get(TaskFields.Ordinal, predecessorId); var successorOrdinal = project.Get(TaskFields.Ordinal, successorId); throw new InvalidOperationException($"Cannot add a link from task {predecessorOrdinal} to task {successorOrdinal} as this would cause a cycle."); } project = project.AddTaskLink(taskLink); remainingTaskLinks.Remove(taskLink); } } foreach (var taskLink in remainingTaskLinks) { project = project.RemoveTaskLink(taskLink); } return(project); }