private List<string> ProcessTemplate(ILog log, Business.ITATSystem itatSystem, Business.Template template, List<TemplateCounter> templateCounters)
        {
            List<string> errors = new List<string>();
            int managedItemsProcessed = 0;
            Stopwatch stopWatch = new Stopwatch();

            Business.Retro.AuditType auditType = Business.Retro.AuditType.None;
            switch (template.RetroModel)
            {
                case Business.Retro.RetroModel.OnWithEditLanguage:
                    auditType = Business.Retro.AuditType.RetroWithEditLanguage;
                    break;

                case Business.Retro.RetroModel.OnWithoutEditLanguage:
                    auditType = Business.Retro.AuditType.RetroWithoutEditLanguage;
                    break;
            }

            TemplateCounter templateCounter = new TemplateCounter(template.Name);
            List<Guid> managedItemIDs = GetManagedItems(template.ID, template.RetroDate);
            List<string> orphanedManagedItems = GetOrphanedManagedItems(template.ID);
            templateCounter.OrphanedManagedItemNumbers.AddRange(orphanedManagedItems);
            if (managedItemIDs.Count > 0)
            {
                List<string> processedManagedItemNumbers = new List<string>();
                List<string> failedManagedItemIDs = new List<string>();
                List<string> failedManagedItemNumbers = new List<string>();
                //Used temporarily for metrics
                DateTime startTime = DateTime.Now;
                int initialManagedItemsProcessed = managedItemsProcessed;
                TimeSpan initialElapsedTime = stopWatch.Elapsed;
                int managedItemsToBeProcessed = managedItemIDs.Count;
                log.Info(string.Format("Processing system {0} template {1} - {2:D} manageditems", itatSystem.Name, template.Name, managedItemIDs.Count));
                DateTime dtTemplateRetroDate = DateTime.Now;
                foreach (Guid managedItemID in managedItemIDs)
                {
                    errors.AddRange(ProcessManagedItem(log, itatSystem, template, stopWatch, templateCounter,
                                            ref managedItemsProcessed, managedItemID, auditType, processedManagedItemNumbers,
                                            failedManagedItemIDs, failedManagedItemNumbers));
                }
                Data.Template.UpdateTemplateSummary(template.ID, template.Name, (short)template.Status, dtTemplateRetroDate);
                if (processedManagedItemNumbers.Count > 0)
                {
                    processedManagedItemNumbers.Sort();
                    log.Info(string.Format("For System {0}, Template {1}, Retro applied to the following ManagedItems:", itatSystem.Name, template.Name));
                    List<string> loggingInfo = GetManagedItemLoggingInfo(processedManagedItemNumbers, true, 20);
                    foreach (string logInfo in loggingInfo)
                        log.Info(logInfo);
                }
                else
                {
                    log.Info(string.Format("For System {0}, Template {1}, Retro not applied to any ManagedItems", itatSystem.Name, template.Name));
                }
                //Here - log the ones that are orphaned
                if (orphanedManagedItems.Count > 0)
                {
                    orphanedManagedItems.Sort();
                    log.Info(string.Format("For System {0}, Template {1}, The following ManagedItems are orphaned:", itatSystem.Name, template.Name));
                    List<string> loggingInfo = GetManagedItemLoggingInfo(orphanedManagedItems, true, 20);
                    foreach (string logInfo in loggingInfo)
                        log.Info(logInfo);
                }
                else
                {
                    log.Info(string.Format("For System {0}, Template {1}, There were no orphaned ManagedItems", itatSystem.Name, template.Name));
                }
                //Here - log the ones that failed
                if (failedManagedItemIDs.Count > 0)
                {
                    failedManagedItemIDs.Sort();
                    log.Error(string.Format("For System {0}, Template {1}, Retro errors encountered for the following ManagedItemIDs:", itatSystem.Name, template.Name));
                    List<string> loggingError = GetManagedItemLoggingInfo(failedManagedItemIDs, true, 20);
                    foreach (string logInfo in loggingError)
                        log.Error(logInfo);
                    if (failedManagedItemNumbers.Count > 0)
                    {
                        failedManagedItemNumbers.Sort();
                        log.Error(string.Format("For System {0}, Template {1}, Retro errors encountered for the following captured ManagedItemNumbers:", itatSystem.Name, template.Name));
                        loggingError = GetManagedItemLoggingInfo(failedManagedItemNumbers, true, 20);
                        foreach (string logInfo in loggingError)
                            log.Error(logInfo);
                    }
                }
                else
                {
                    log.Info(string.Format("For System {0}, Template {1}, There were no ManagedItem errors", itatSystem.Name, template.Name));
                }
                templateCounters.Add(templateCounter);
                LogMetrics(log, startTime, initialManagedItemsProcessed, initialElapsedTime, managedItemsToBeProcessed);
                if (templateCounter.RevertedManagedItemNumbers.Count > 0)
                {
                    templateCounter.RevertedManagedItemNumbers.Sort();
                    StringBuilder sbRevertMessage = new StringBuilder();
                    sbRevertMessage.AppendFormat("{0}<br />", template.Workflow.RetroRevertMessage.Text);
                    List<string> loggingInfo = GetManagedItemLoggingInfo(templateCounter.RevertedManagedItemNumbers, false, 10);
                    foreach (string logInfo in loggingInfo)
                        sbRevertMessage.AppendFormat("{0}<br />", logInfo);
                    sbRevertMessage.Append("<br /><br />End of list<br /><br />");

                    if (template.Workflow.RetroRevertMessage.Recipients.Count == 0)
                    {
                        log.Debug(string.Format("No message sent for template '{0}' as no recipients defined.  Message text = {1}", template.Name, sbRevertMessage.ToString()));
                    }
                    else
                    {
                        Business.EmailHelper.SendNotificationToRoles(itatSystem, template.Workflow.RetroRevertMessage.Subject, sbRevertMessage.ToString(), template.Workflow.RetroRevertMessage.Recipients);
                    }
                }
            }
            else
            {
                log.Info(string.Format("For system {0} template {1} - no manageditems to be processed, {2:D} orphaned manageditem(s)", itatSystem.Name, template.Name, orphanedManagedItems.Count));
                if (orphanedManagedItems.Count > 0)
                {
                    orphanedManagedItems.Sort();
                    List<string> loggingInfo = GetManagedItemLoggingInfo(orphanedManagedItems, true, 20);
                    foreach (string logInfo in loggingInfo)
                        log.Info(logInfo);
                }
            }

            return errors;
        }
        private List<string> ProcessManagedItem(
                                ILog log, 
                                Business.ITATSystem itatSystem, 
                                Business.Template template, 
                                Stopwatch stopWatch, 
                                TemplateCounter templateCounter,
                                ref int managedItemsProcessed,
                                Guid managedItemID,
                                Business.Retro.AuditType auditType,
                                List<string> processedManagedItemNumbers,
                                List<string> failedManagedItemIDs,
                                List<string> failedManagedItemNumbers)
        {
            List<string> sErrors = new List<string>();

            stopWatch.Start();
            string managedItemNumber = null;
            try
            {
                bool returnToDraft;
                Business.ManagedItem newManagedItem = Business.ManagedItem.CreateRetro(template, false, managedItemID, itatSystem.HasOwningFacility.Value, itatSystem.DocumentStorageType, out returnToDraft);
                managedItemNumber = newManagedItem.ItemNumber;
                if (returnToDraft)
                {
                    templateCounter.RevertedManagedItemNumbers.Add(newManagedItem.ItemNumber);
                }
                newManagedItem.Update(false, auditType, true);    //Also calls UpdateManagedItemStateRole
                newManagedItem.UpdateScheduledEvents(Business.ScheduledEvent.ExecutedCalculationType.UseGracePeriod);
                processedManagedItemNumbers.Add(newManagedItem.ItemNumber);
                templateCounter.RetroedManagedItemNumbers.Add(newManagedItem.ItemNumber);
                newManagedItem = null;
            }
            catch (Exception ex)
            {
                log.Error(string.Format("Error Processing ManagedItem '{0}' ({1}) - {2}  Trace:{3}", string.IsNullOrEmpty(managedItemNumber) ? "" : managedItemNumber, managedItemID.ToString(), ex.Message, ex.StackTrace));
                templateCounter.FailedManagedItemIDs.Add(managedItemID.ToString());
                failedManagedItemIDs.Add(managedItemID.ToString());
                if (!string.IsNullOrEmpty(managedItemNumber))
                {
                    templateCounter.FailedManagedItemNumbers.Add(managedItemNumber);
                    failedManagedItemNumbers.Add(managedItemNumber);
                }
            }
            if (processedManagedItemNumbers.Count % 100 == 0)
            {
                log.Info(string.Format("Processed {0:D} manageditems...", processedManagedItemNumbers.Count));
            }
            stopWatch.Stop();
            managedItemsProcessed++;

            return sErrors;
        }