public void Init() { var workStepRepository = new MemoryWorkStepRepository(); var workItemRepository = new MemoryWorkItemRepository(); var workflowRepository = new WorkflowRepository(workItemRepository, workStepRepository); _wp = new Workflow(workflowRepository); _jsonRenderer = new JsonRenderer(_wp); }
private WorkItem MergeParallelWorkItems(WorkItemTransition transition) { var unlockedParentWorkItem = WorkflowRepository.GetWorkItem(transition.WorkItem.Parent.Id).UpdateStatus(WorkItemStatus.Normal); WorkflowRepository.UpdateWorkItem(unlockedParentWorkItem); foreach (var childWorkItem in WorkflowRepository.GetChildWorkItems(transition.WorkItem.Parent).ToList()) { if (WorkflowRepository.IsExpandStep(transition.WorkStep)) { CleanUpIfMovingFromExpandStep(new WorkItemTransition(childWorkItem, transition.WorkStep)); } WorkflowRepository.DeleteWorkItem(childWorkItem.Id); } return(unlockedParentWorkItem); }
private void DeleteWorkItemRecursively(WorkItem workItem) { var expandedChildWorkItems = WorkflowRepository.GetChildWorkItems(workItem.AsParent(WorkItemParentType.Expanded)); var parallelChildWorkItems = WorkflowRepository.GetChildWorkItems(workItem.AsParent(WorkItemParentType.Parallelled)); var childWorkItems = expandedChildWorkItems.Concat(parallelChildWorkItems); if (childWorkItems.Count() > 0) { foreach (var childWorkItem in childWorkItems) { DeleteWorkItemRecursively(childWorkItem); } } WorkflowRepository.DeleteWorkItem(workItem.Id); CleanUpIfInExpandStep(workItem); }
private void MoveToWithinParallelStep(WorkItemTransition transition) { var newTransition = transition; if (!WorkflowRepository.IsValidWorkStepForWorkItem(transition.WorkItem, transition.WorkStep)) { newTransition = TraverseParallelMoveHierarchy(transition); } ThrowIfMovingToStepWithWrongClass(newTransition); CleanUpIfMovingFromExpandStep(newTransition); newTransition = AttemptMergeIfMovingChildOfParallelledWorkItem(newTransition); var resultTransition = DoMove(newTransition); TryUpdatingExpandLockIfMovingChildOfExpandedWorkItem(resultTransition); }
private void Create(WorkItem newWorkItem) { var leafStep = WorkflowRepository.GetLeafStep(newWorkItem.Path); if (leafStep.Type != WorkStepType.Begin) { throw new InvalidOperationException("Can only create work items in begin step"); } var classes = WorkflowRepository.GetWorkItemClasses(leafStep); newWorkItem = newWorkItem.MoveTo(leafStep, _timeSource.GetTime()).UpdateClasses(classes); WorkStep transientStep; if (WorkflowRepository.IsWithinTransientStep(leafStep, out transientStep)) { var parentItem = GetTransientParentWorkItem(transientStep); WorkflowRepository.UpdateWorkItem(parentItem.UpdateStatus(WorkItemStatus.ExpandLocked)); newWorkItem = newWorkItem.MoveTo(leafStep, _timeSource.GetTime()).UpdateParent(parentItem, WorkItemParentType.Expanded); foreach (var workItemClass in newWorkItem.Classes) { foreach (var rootClass in WorkItemClass.FindRootClasses(workItemClass)) { newWorkItem = newWorkItem.AddClass(rootClass); } } } else if (WorkflowRepository.IsWithinExpandStep(leafStep)) { throw new InvalidOperationException("Cannot create item directly under expand step"); } if (!newWorkItem.Ordinal.HasValue) { newWorkItem = newWorkItem.UpdateOrdinal(WorkflowRepository.GetNextOrdinal(newWorkItem)); } WorkflowRepository.CreateWorkItem(newWorkItem); }
public void UpdateWorkItem(WorkItem changedWorkItem) { var currentWorkItem = GetWorkItemOrThrow(changedWorkItem.Id); ThrowIfConflictingTimestamp(currentWorkItem, changedWorkItem); currentWorkItem = currentWorkItem.UpdatePropertiesAndOrdinalFrom(changedWorkItem).UpdateTimestamp(TimeSource.GetTime()); var leafStep = WorkflowRepository.GetLeafStep(changedWorkItem.Path); if (changedWorkItem.Path == currentWorkItem.Path || currentWorkItem.Path == leafStep.Path) { WorkflowRepository.UpdateWorkItem(currentWorkItem); } else { var mover = new WorkItemMover(WorkflowRepository, TimeSource); mover.MoveWorkItem(currentWorkItem, leafStep); } }
private WorkItem CreateParallelledChildrenAndReturnWorkItemToMove(WorkItemTransition transition, WorkStep parallelStep) { var helper = new ParallelStepHelper(WorkflowRepository); var splitWorkItems = helper.SplitForParallelism(transition.WorkItem, parallelStep); foreach (var splitWorkItem in splitWorkItems) { WorkflowRepository.CreateWorkItem(splitWorkItem); WorkStep expandStep; var isInExpandStep = WorkflowRepository.IsInExpandStep(transition.WorkItem, out expandStep); if (isInExpandStep) { CreateTransientWorkSteps(splitWorkItem, expandStep); } } var idToMove = ParallelStepHelper.GetParallelId(transition.WorkItem.Id, parallelStep, transition.WorkStep); var workItemToMove = splitWorkItems.First(wi => wi.Id == idToMove); return(workItemToMove); }
private WorkItemTransition TraversePathsForParallelStep(WorkItemTransition transition, IEnumerable <string> pathsBetweenRootAndTarget) { var currentWorkItem = transition.WorkItem; WorkStep parentWorkStep = null; foreach (var inBetweenPath in pathsBetweenRootAndTarget) { var currentWorkStep = WorkflowRepository.GetWorkStep(inBetweenPath); var currentTransition = new WorkItemTransition(currentWorkItem, currentWorkStep); if (parentWorkStep != null && WorkflowRepository.IsParallelStep(parentWorkStep)) { var transitionToParallelRoot = new WorkItemTransition(currentWorkItem, parentWorkStep); LockAndMoveToParallelRoot(transitionToParallelRoot); currentWorkItem = CreateParallelledChildrenAndReturnWorkItemToMove(currentTransition, parentWorkStep); } parentWorkStep = currentWorkStep; } return(new WorkItemTransition(currentWorkItem, transition.WorkStep)); }
public IEnumerable <WorkStep> GetChildWorkSteps(string path) { return(WorkflowRepository.GetChildWorkSteps(path)); }
public IEnumerable <WorkItem> GetChildWorkItems(WorkItemParent parent) { return(WorkflowRepository.GetChildWorkItems(parent)); }
public WorkStep GetWorkStep(string path) { return(WorkflowRepository.GetWorkStep(path)); }
public bool ExistsWorkStep(string path) { return(WorkflowRepository.ExistsWorkStep(path)); }
public WorkItem GetWorkItem(string id) { return(WorkflowRepository.GetWorkItem(id)); }
public bool ExistsWorkItem(string workItemId) { return(WorkflowRepository.ExistsWorkItem(workItemId)); }
public IEnumerable <WorkItem> GetWorkItems(string path) { return(WorkflowRepository.GetWorkItems(path)); }
public void DeleteWorkStep(string path) { WorkflowRepository.DeleteWorkStep(path); }
private WorkItem GetTransientParentWorkItem(WorkStep transientStep) { var workItemId = transientStep.Path.Split(WorkflowPath.Separator).Last(); return(WorkflowRepository.GetWorkItem(workItemId)); }
public void CreateWorkStep(WorkStep workStep) { if (workStep.ParentPath != WorkStep.Root.Path) { if (!WorkflowRepository.ExistsWorkStep(workStep.ParentPath)) { throw new InvalidOperationException("Parent does not exist"); } } if (workStep.Type == WorkStepType.Transient) { throw new InvalidOperationException("Cannot create transient workstep"); } WorkStep parent = null; if (workStep.ParentPath != WorkStep.Root.Path) { parent = WorkflowRepository.GetWorkStep(workStep.ParentPath); } if (workStep.WorkItemClass == null && parent != null && parent.Type != WorkStepType.Parallel) { workStep = workStep.UpdateWorkItemClass(parent.WorkItemClass); } if (parent != null && parent.Type == WorkStepType.Parallel) { var leaf = WorkflowPath.GetLeafDirectory(workStep.Path); var workItemClass = parent.WorkItemClass + "-" + leaf; if (workStep.WorkItemClass == null) { workStep = workStep.UpdateWorkItemClass(workItemClass); } else if (workStep.WorkItemClass != workItemClass) { throw new InvalidOperationException("Invalid work item class for child of parallel step. Expected '" + workItemClass + "' but was '" + workStep.WorkItemClass + "'"); } } var siblings = WorkflowRepository.GetChildWorkSteps(workStep.ParentPath); var firstSibling = siblings.FirstOrDefault(); if (workStep.WorkItemClass == null && firstSibling != null) { workStep = workStep.UpdateWorkItemClass(firstSibling.WorkItemClass); } if (!workStep.Ordinal.HasValue) { var last = siblings.OrderBy(ws => ws.Ordinal).LastOrDefault(); var ordinal = last == null ? 0 : last.Ordinal.Value + 1; workStep = workStep.UpdateOrdinal(ordinal); } if (siblings.Where(ws => ws.Ordinal == workStep.Ordinal).Count() > 0) { throw new InvalidOperationException("Cannot create workstep with same ordinal as sibling"); } if (workStep.WorkItemClass == null) { throw new InvalidOperationException("Work item class missing and could not resolve one"); } if (parent != null && parent.Type == WorkStepType.Expand && parent.WorkItemClass == workStep.WorkItemClass) { throw new InvalidOperationException("Child of expand step cannot have same workitem class as parent"); } if (parent != null && parent.Type != WorkStepType.Expand && parent.Type != WorkStepType.Parallel && parent.WorkItemClass != workStep.WorkItemClass) { throw new InvalidOperationException("Incompatible work item class. Should be same as parent"); } if (firstSibling != null && firstSibling.WorkItemClass != workStep.WorkItemClass) { if (parent == null || parent.Type != WorkStepType.Parallel) { throw new InvalidOperationException("Incompatible work item class. Should be same as siblings"); } } WorkflowRepository.CreateWorkStep(workStep); }
private bool IsMovingWithinParallelStep(WorkItemTransition transition) { return(WorkflowRepository.IsWithinParallelStep(transition.WorkStep)); }
private void ThrowIfMovingToWithinExpandStep(WorkItemTransition transition) { WorkStep dummyStep; if (!WorkflowRepository.IsExpandStep(transition.WorkStep) && !WorkflowRepository.IsWithinTransientStep(transition.WorkStep, out dummyStep) && WorkflowRepository.IsWithinExpandStep(transition.WorkStep)) { throw new InvalidOperationException("Cannot move item to within expand step"); } }