public static List <BookScript> ParseBooks(IEnumerable <UsxDocument> books, IStylesheet stylesheet, Action <int> reportProgressAsPercent)
        {
            var numBlocksPerBook = new ConcurrentDictionary <string, int>();
            var blocksInBook     = new ConcurrentDictionary <string, XmlNodeList>();

            Parallel.ForEach(books, usxDoc =>
            {
                var nodeList = usxDoc.GetChaptersAndParas();
                blocksInBook.AddOrUpdate(usxDoc.BookId, nodeList, (s, list) => nodeList);
                numBlocksPerBook.AddOrUpdate(usxDoc.BookId, nodeList.Count, (s, i) => nodeList.Count);
            });
            int allBlocks = numBlocksPerBook.Values.Sum();

            int completedBlocks = 0;
            var bookScripts     = new List <BookScript>(blocksInBook.Count);

            Parallel.ForEach(blocksInBook, book =>
            {
                var bookId     = book.Key;
                var bookScript = new UsxParser(bookId, stylesheet, book.Value).CreateBookScript();
                lock (bookScripts)
                    bookScripts.Add(bookScript);
                Logger.WriteEvent("Added bookScript ({0}, {1})", bookId, bookScript.BookId);
                completedBlocks += numBlocksPerBook[bookId];
                reportProgressAsPercent?.Invoke(MathUtilities.Percent(completedBlocks, allBlocks, 99));
            });

            // This code is an attempt to figure out how we are getting null reference exceptions on the Sort call (See PG-275 & PG-287)
            // The above call to lock bookScripts probably fixes the problem!!! :-) We hope...
            foreach (var bookScript in bookScripts)
            {
                if (bookScript?.BookId == null)
                {
                    var nonNullBookScripts    = bookScripts.Where(b => b != null).Select(b => b.BookId);
                    var nonNullBookScriptsStr = Join(";", nonNullBookScripts);
                    var initialMessage        = bookScript == null ? "BookScript is null." : "BookScript has null BookId.";
                    throw new ApplicationException($"{initialMessage} Number of BookScripts: {bookScripts.Count}. " +
                                                   $"BookScripts which are NOT null: {nonNullBookScriptsStr}");
                }
            }

            try
            {
                bookScripts.Sort((a, b) => BCVRef.BookToNumber(a.BookId).CompareTo(BCVRef.BookToNumber(b.BookId)));
            }
            catch (NullReferenceException n)
            {
                // This code is an attempt to figure out how we are getting null reference exceptions on the Sort call (See PG-275 & PG-287)
                StringBuilder sb = new StringBuilder();
                foreach (var bookScript in bookScripts)
                {
                    sb.Append(Environment.NewLine).Append(bookScript.BookId).Append("(").Append(BCVRef.BookToNumber(bookScript.BookId)).Append(")");
                }
                throw new NullReferenceException("Null reference exception while sorting books." + sb, n);
            }

            reportProgressAsPercent?.Invoke(100);
            return(bookScripts);
        }
Example #2
0
        public static List <BookScript> ParseProject(IEnumerable <UsxDocument> books, IStylesheet stylesheet, BackgroundWorker projectWorker)
        {
            var numBlocksPerBook = new ConcurrentDictionary <string, int>();
            var blocksInBook     = new ConcurrentDictionary <string, XmlNodeList>();

            Parallel.ForEach(books, bookScript =>
            {
                var nodeList = bookScript.GetChaptersAndParas();
                blocksInBook.AddOrUpdate(bookScript.BookId, nodeList, (s, list) => nodeList);
                numBlocksPerBook.AddOrUpdate(bookScript.BookId, nodeList.Count, (s, i) => nodeList.Count);
            });
            int allProjectBlocks = numBlocksPerBook.Values.Sum();

            int completedProjectBlocks = 0;
            var bookScripts            = new List <BookScript>(blocksInBook.Count);

            Parallel.ForEach(blocksInBook, book =>
            {
                var bookId = book.Key;
                Logger.WriteEvent("Creating bookScript ({0})", bookId);
                var parser     = new UsxParser(bookId, stylesheet, book.Value);
                var bookScript = new BookScript(bookId, parser.Parse());
                SingleVoiceReason singleVoiceReason;
                bookScript.SingleVoice = BookMetadata.DefaultToSingleVoice(bookId, out singleVoiceReason);
                bookScript.PageHeader  = parser.PageHeader;
                bookScript.MainTitle   = parser.MainTitle;
                Logger.WriteEvent("Created bookScript ({0}, {1})", bookId, bookScript.BookId);
                lock (bookScripts)
                    bookScripts.Add(bookScript);
                Logger.WriteEvent("Added bookScript ({0}, {1})", bookId, bookScript.BookId);
                completedProjectBlocks += numBlocksPerBook[bookId];
                projectWorker.ReportProgress(MathUtilities.Percent(completedProjectBlocks, allProjectBlocks, 99));
            });

            // This code is an attempt to figure out how we are getting null reference exceptions on the Sort call (See PG-275 & PG-287)
            // The above call to lock bookScripts probably fixes the problem!!! :-) We hope...
            foreach (var bookScript in bookScripts)
            {
                if (bookScript == null || bookScript.BookId == null)
                {
                    var nonNullBookScripts    = bookScripts.Where(b => b != null).Select(b => b.BookId);
                    var nonNullBookScriptsStr = string.Join(";", nonNullBookScripts);
                    var initialMessage        = bookScript == null ? "BookScript is null." : "BookScript has null BookId.";
                    throw new ApplicationException(string.Format("{0} Number of BookScripts: {1}. BookScripts which are NOT null: {2}", initialMessage, bookScripts.Count, nonNullBookScriptsStr));
                }
            }

            try
            {
                bookScripts.Sort((a, b) => BCVRef.BookToNumber(a.BookId).CompareTo(BCVRef.BookToNumber(b.BookId)));
            }
            catch (NullReferenceException n)
            {
                // This code is an attempt to figure out how we are getting null reference exceptions on the Sort call (See PG-275 & PG-287)
                StringBuilder sb = new StringBuilder();
                foreach (var bookScript in bookScripts)
                {
                    sb.Append(Environment.NewLine).Append(bookScript.BookId).Append("(").Append(BCVRef.BookToNumber(bookScript.BookId)).Append(")");
                }
                throw new NullReferenceException("Null reference exception while sorting books." + sb, n);
            }

            projectWorker.ReportProgress(100);
            return(bookScripts);
        }