public void MoveWorkStep(WorkStep stepToMove, WorkStep toStep) { if (stepToMove.WorkItemClass != toStep.WorkItemClass) { throw new InvalidOperationException("Cannot move work step. Work item classes are not compatible"); } var siblings = _workflowRepository.GetChildWorkSteps(toStep.Path); if (siblings.Where(ws => ws.Ordinal == stepToMove.Ordinal).Count() > 0) { throw new InvalidOperationException("Cannot move work step. Conflicting ordinals"); } if (_workflowRepository.IsWithinTransientStep(stepToMove)) { throw new InvalidOperationException("Cannot move transient work step or step within transient work step"); } var commonRoot = WorkflowPath.FindCommonRoot(stepToMove.Path, toStep.Path); foreach (var path in WorkflowPath.GetPathsBetween(commonRoot, stepToMove.Path)) { if (path == commonRoot || path == stepToMove.Path) { continue; } if (_workflowRepository.GetWorkStep(path).Type == WorkStepType.Expand) { throw new InvalidOperationException("Cannot move work step within expand step outside expand step"); } if (_workflowRepository.GetWorkStep(path).Type == WorkStepType.Parallel) { throw new InvalidOperationException("Cannot move work step within expand step outside parallel step"); } } var wipLimitChecker = new WipLimitChecker(_workflowRepository); if (!wipLimitChecker.CanAcceptWorkStep(toStep, stepToMove)) { throw new InvalidOperationException("Cannot move work step when WIP limit of new ancestors are violated"); } MoveWorkStepRecursively(stepToMove, toStep); }
private IEnumerable <string> GetPathsToTraverseForParallelStep(WorkItemTransition transition) { IEnumerable <string> pathsBetweenRootAndTarget; WorkItem parallelParent; if (IsMovedUnderneathParallelParent(transition, out parallelParent)) { var commonRootStepPath = WorkflowPath.FindCommonRoot(parallelParent.Path, transition.WorkStep.Path); pathsBetweenRootAndTarget = WorkflowPath.GetPathsBetween(commonRootStepPath, transition.WorkStep.Path).Skip(1); } else { var commonRootStepPath = WorkflowPath.FindCommonRoot(transition.WorkItem.Path, transition.WorkStep.Path); pathsBetweenRootAndTarget = WorkflowPath.GetPathsBetween(commonRootStepPath, transition.WorkStep.Path); } return(pathsBetweenRootAndTarget); }