}     // makeBatchOp()

        /// <summary>
        /// Run the next iteration of this batch operation
        /// </summary>
        public void runBatchOp(CswNbtObjClassBatchOp BatchNode)
        {
            try
            {
                if (BatchNode != null && BatchNode.OpNameValue == CswEnumNbtBatchOpName.FutureNodes)
                {
                    BatchNode.start();

                    FutureNodesBatchData BatchData = new FutureNodesBatchData(BatchNode.BatchData.Text);
                    if (BatchData.GeneratorNodeId != null && BatchData.NextStartDate != DateTime.MinValue)
                    {
                        CswNbtNode GenNode = _CswNbtResources.Nodes[BatchData.GeneratorNodeId];
                        if (null != GenNode)
                        {
                            CswNbtObjClassGenerator GeneratorNode = (CswNbtObjClassGenerator)GenNode;
                            DateTime ThisDate = BatchData.NextStartDate;

                            CswNbtActGenerateNodes CswNbtActGenerateNodes = new CswNbtActGenerateNodes(_CswNbtResources);
                            CswNbtActGenerateNodes.MarkFuture = true;

                            // Run this iteration
                            bool Finished = false;
                            if (ThisDate != DateTime.MinValue &&
                                ThisDate.Date <= BatchData.FinalDate.Date &&
                                (GeneratorNode.FinalDueDate.Empty || ThisDate.Date <= GeneratorNode.FinalDueDate.DateTimeValue.Date))
                            {
                                Finished = CswNbtActGenerateNodes.makeNode(GenNode, ThisDate);
                                //BatchNode.appendToLog( "Created future task for " + ThisDate.ToShortDateString() + "." );
                            }
                            else
                            {
                                BatchNode.finish();
                            }

                            // Setup for next iteration
                            if (Finished)
                            {
                                BatchData.NextStartDate = GeneratorNode.DueDateInterval.getNextOccuranceAfter(ThisDate);
                                if (BatchData.NextStartDate.Date == ThisDate.Date)  // infinite loop guard
                                {
                                    BatchNode.finish();
                                }
                                BatchData.IterationCount += 1;
                            }
                            BatchNode.BatchData.Text    = BatchData.ToString();
                            BatchNode.PercentDone.Value = getPercentDone(BatchNode);
                        } // if( null != GenNode )
                    }     // if( _BatchData.GeneratorNodeId != null && _BatchData.NextStartDate != DateTime.MinValue )

                    BatchNode.postChanges(false);
                } // if( BatchNode != null && BatchNode.OpNameValue == NbtBatchOpName.FutureNodes )
            }
            catch (Exception ex)
            {
                BatchNode.error(ex);
            }
        } // runBatchOp()
        } // makeBatchOp()

        /// <summary>
        /// Create a new batch operation to handle future node generation
        /// </summary>
        /// <param name="GenNode">Generator Node</param>
        /// <param name="FinalDate"></param>
        public CswNbtObjClassBatchOp makeBatchOp(CswNbtNode GenNode, DateTime FinalDate)
        {
            CswNbtObjClassBatchOp BatchNode = null;

            if (null != GenNode)
            {
                CswNbtObjClassGenerator GeneratorNode = (CswNbtObjClassGenerator)GenNode;


                // BZ 6752 - The first future node is the first node generated
                // after today + warning days, according to the time interval
                // But it has to include initial due date, no matter what the time interval.

                CswNbtNodePropTimeInterval NextDueDateTimeInterval = GeneratorNode.DueDateInterval;
                Double WarningDays = 0;
                if (GeneratorNode.WarningDays.Value > 0)
                {
                    WarningDays = GeneratorNode.WarningDays.Value;
                }
                DateTime StartDate = DateTime.Now.AddDays(WarningDays).Date;   //bz# 6937 (capture date only, not time)

                DateTime DateOfNextOccurance = DateTime.MinValue;
                if (GeneratorNode.DueDateInterval.getStartDate().Date >= StartDate)  //bz # 6937 (change gt to gteq)
                {
                    DateOfNextOccurance = GeneratorNode.DueDateInterval.getStartDate().Date;
                }
                else
                {
                    DateOfNextOccurance = NextDueDateTimeInterval.getNextOccuranceAfter(StartDate);
                }

                // Determine number of iterations
                Int32    StartingCount = 0;
                DateTime ThisDate      = DateOfNextOccurance;

                while (ThisDate != DateTime.MinValue &&
                       ThisDate.Date <= FinalDate &&
                       (GeneratorNode.FinalDueDate.Empty || ThisDate.Date <= GeneratorNode.FinalDueDate.DateTimeValue.Date))
                {
                    StartingCount++;
                    ThisDate = GeneratorNode.DueDateInterval.getNextOccuranceAfter(ThisDate);
                }

                FutureNodesBatchData BatchData = new FutureNodesBatchData(string.Empty);
                BatchData.GeneratorNodeId = GenNode.NodeId;
                BatchData.NextStartDate   = DateOfNextOccurance;
                BatchData.FinalDate       = FinalDate;
                BatchData.StartingCount   = StartingCount;
                BatchData.IterationCount  = 0;

                BatchNode = CswNbtBatchManager.makeNew(_CswNbtResources, _BatchOpName, BatchData.ToString());
            } // if(null != GeneratorNode)
            return(BatchNode);
        }     // makeBatchOp()
        /// <summary>
        /// Returns the percentage of the task that is complete
        /// </summary>
        public Double getPercentDone(CswNbtObjClassBatchOp BatchNode)
        {
            Double ret = 100;

            if (BatchNode != null && BatchNode.OpNameValue == CswEnumNbtBatchOpName.FutureNodes)
            {
                FutureNodesBatchData BatchData = new FutureNodesBatchData(BatchNode.BatchData.Text);
                if (BatchData.StartingCount > 0)
                {
                    ret = Math.Round((Double)BatchData.IterationCount / BatchData.StartingCount * 100, 0);
                }
            }
            return(ret);
        } // getPercentDone()