Inheritance: IWorkflowRepository, IDisposable
        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);
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        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);
        }
Beispiel #4
0
        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);
            }
        }
Beispiel #7
0
        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);
        }
Beispiel #8
0
        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);
        }
Beispiel #19
0
 private bool IsMovingWithinParallelStep(WorkItemTransition transition)
 {
     return(WorkflowRepository.IsWithinParallelStep(transition.WorkStep));
 }
Beispiel #20
0
        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");
            }
        }