public INodes GetLeafNodes()
        {
            INodes leafs = new Nodes();

            foreach (var node in _nodes)
            {
                INodes successors = GetSuccessorNodes(node.GetNode());
                if (successors == null || successors.Any() == false)
                {
                    leafs.Add(node.GetNode());
                }
            }

            if (leafs.Any() == false)
            {
                return(null);
            }

            return(leafs);
        }
        /**
         * Top-down
         */
        public void ScheduleBackward()
        {
            // S = {0} (alle einplanbaren Operations/Demands/Providers)

            if (_clearOldTimes)
            {
                // d_0 = 0
                foreach (var uniqueNode in _orderOperationGraph.GetAllUniqueNodes())
                {
                    IScheduleNode uniqueScheduleNode = uniqueNode.GetEntity();
                    if (uniqueScheduleNode.IsReadOnly() == false &&
                        uniqueScheduleNode.GetType() != typeof(CustomerOrderPart))
                    {
                        uniqueScheduleNode.ClearStartTimeBackward();
                        uniqueScheduleNode.ClearEndTimeBackward();
                    }
                }
            }

            // while S nor empty do
            while (_S.Any())
            {
                INode         i = _S.Pop();
                IScheduleNode iAsScheduleNode = i.GetEntity();

                INodes successorNodes = _orderOperationGraph.GetSuccessorNodes(i);
                if (successorNodes != null && successorNodes.Any())
                {
                    foreach (var successor in successorNodes)
                    {
                        _S.Push(successor);

                        IScheduleNode successorScheduleNode = successor.GetEntity();
                        if (successorScheduleNode.IsReadOnly())
                        {
                            continue;
                        }


                        // Konservativ vorwärtsterminieren ist korrekt,
                        // aber rückwärts muss wenn immer möglich terminiert werden
                        // (prüfe parents und ermittle minStart und setze das)
                        INodes predecessorNodes =
                            _orderOperationGraph.GetPredecessorNodes(successor);
                        DueTime minStartTime = iAsScheduleNode.GetStartTimeBackward();
                        if (minStartTime == null)
                        {
                            throw new MrpRunException(
                                      "How can the StartTime of an already scheduled node be null ?");
                        }

                        foreach (var predecessorNode in predecessorNodes)
                        {
                            DueTime predecessorsStartTime =
                                predecessorNode.GetEntity().GetStartTimeBackward();
                            if (predecessorsStartTime != null &&
                                predecessorsStartTime.IsSmallerThan(minStartTime))
                            {
                                minStartTime = predecessorsStartTime;
                            }
                        }

                        if (successorScheduleNode.GetType() == typeof(CustomerOrderPart))
                        {
                            throw new MrpRunException(
                                      "Only a root node can be a CustomerOrderPart.");
                        }

                        if (successorScheduleNode.IsReadOnly() == false)
                        {
                            successorScheduleNode.SetEndTimeBackward(minStartTime);
                        }
                    }
                }
            }
        }
        public void ScheduleForward()
        {
            Stack <INode> S = new Stack <INode>();

            // d_0 = 0
            foreach (var node in _orderOperationGraph.GetLeafNodes())
            {
                IScheduleNode scheduleNode = node.GetEntity();
                if (scheduleNode.IsReadOnly() == false &&
                    scheduleNode.GetStartTimeBackward().IsSmallerThan(_simulationInterval.GetStart()))
                {
                    // implicitly the due/endTime will also be set accordingly
                    scheduleNode.SetStartTimeBackward(_simulationInterval.GetStart());
                    S.Push(node);
                }
                else // no forward scheduling is needed
                {
                }
            }


            // while S nor empty do
            while (S.Any())
            {
                INode         i = S.Pop();
                IScheduleNode iAsScheduleNode = (IScheduleNode)i.GetEntity();

                INodes predecessors = _orderOperationGraph.GetPredecessorNodes(i);
                if (predecessors != null && predecessors.Any())
                {
                    foreach (var predecessor in predecessors)
                    {
                        IScheduleNode predecessorScheduleNode = predecessor.GetEntity();

                        // if predecessor starts before endTime of current d/p --> change that
                        if (predecessorScheduleNode.IsReadOnly() == false && predecessorScheduleNode
                            .GetStartTimeBackward().IsSmallerThan(iAsScheduleNode.GetEndTimeBackward()))
                        {
                            // COPs are not allowed to change
                            if (predecessorScheduleNode.GetType() != typeof(CustomerOrderPart))
                            {
                                // don't take getDueTime() since in case of a demand,
                                // this will be the startTime, which is to early

                                // This must be the maximum endTime of all childs !!!
                                DueTime maxEndTime = iAsScheduleNode.GetEndTimeBackward();
                                foreach (var successor in _orderOperationGraph.GetSuccessorNodes(
                                             predecessor))
                                {
                                    DueTime successorsEndTime = successor.GetEntity().GetEndTimeBackward();
                                    if (successorsEndTime.IsGreaterThan(maxEndTime))
                                    {
                                        maxEndTime = successorsEndTime;
                                    }
                                }

                                predecessorScheduleNode.SetStartTimeBackward(maxEndTime);
                            }
                        }

                        S.Push(predecessor);
                    }
                }
            }
        }