// the following gets a flattened list of ComparisonUnitAtoms, with status indicated in each ComparisonUnitAtom: Deleted, Inserted, or Equal

        // for any deleted or inserted rows, we go into the w:trPr properties, and add the appropriate w:ins or w:del element, and therefore
        // when generating the document, the appropriate row will be marked as deleted or inserted.

        public static List <WmlComparerRevision> GetRevisions(WmlDocument source, WmlComparerSettings settings)
        {
            using (var ms = new MemoryStream())
            {
                ms.Write(source.DocumentByteArray, 0, source.DocumentByteArray.Length);
                using (WordprocessingDocument wDoc = WordprocessingDocument.Open(ms, true))
                {
                    TestForInvalidContent(wDoc);
                    RemoveExistingPowerToolsMarkup(wDoc);

                    XElement             contentParent = wDoc.MainDocumentPart.GetXDocument().Root?.Element(W.body);
                    ComparisonUnitAtom[] atomList      =
                        CreateComparisonUnitAtomList(wDoc.MainDocumentPart, contentParent, settings).ToArray();

                    if (False)
                    {
                        var sb = new StringBuilder();
                        foreach (ComparisonUnitAtom item in atomList)
                        {
                            sb.Append(item + Environment.NewLine);
                        }
                        string sbs = sb.ToString();
                        TestUtil.NotePad(sbs);
                    }

                    List <IGrouping <string, ComparisonUnitAtom> > grouped = atomList
                                                                             .GroupAdjacent(a =>
                    {
                        string key = a.CorrelationStatus.ToString();
                        if (a.CorrelationStatus != CorrelationStatus.Equal)
                        {
                            var rt = new XElement(a.RevTrackElement.Name,
                                                  new XAttribute(XNamespace.Xmlns + "w",
                                                                 "http://schemas.openxmlformats.org/wordprocessingml/2006/main"),
                                                  a.RevTrackElement.Attributes().Where(a2 => a2.Name != W.id && a2.Name != PtOpenXml.Unid));
                            key += rt.ToString(SaveOptions.DisableFormatting);
                        }

                        return(key);
                    })
                                                                             .ToList();

                    List <IGrouping <string, ComparisonUnitAtom> > revisions = grouped
                                                                               .Where(k => k.Key != "Equal")
                                                                               .ToList();

                    if (False)
                    {
                        var sb = new StringBuilder();
                        foreach (IGrouping <string, ComparisonUnitAtom> item in revisions)
                        {
                            sb.Append(item.Key + Environment.NewLine);
                        }

                        string sbs = sb.ToString();
                        TestUtil.NotePad(sbs);
                    }

                    List <WmlComparerRevision> mainDocPartRevisionList = revisions
                                                                         .Select(rg =>
                    {
                        var rev = new WmlComparerRevision();
                        if (rg.Key.StartsWith("Inserted"))
                        {
                            rev.RevisionType = WmlComparerRevisionType.Inserted;
                        }
                        else if (rg.Key.StartsWith("Deleted"))
                        {
                            rev.RevisionType = WmlComparerRevisionType.Deleted;
                        }

                        XElement revTrackElement = rg.First().RevTrackElement;
                        rev.RevisionXElement     = revTrackElement;
                        rev.Author          = (string)revTrackElement.Attribute(W.author);
                        rev.ContentXElement = rg.First().ContentElement;
                        rev.Date            = (string)revTrackElement.Attribute(W.date);
                        rev.PartUri         = wDoc.MainDocumentPart.Uri;
                        rev.PartContentType = wDoc.MainDocumentPart.ContentType;

                        if (!RevElementsWithNoText.Contains(rev.ContentXElement.Name))
                        {
                            rev.Text = rg
                                       .Select(rgc => rgc.ContentElement.Name == W.pPr ? NewLine : rgc.ContentElement.Value)
                                       .StringConcatenate();
                        }

                        return(rev);
                    })
                                                                         .ToList();

                    IEnumerable <WmlComparerRevision> footnotesRevisionList =
                        GetFootnoteEndnoteRevisionList(wDoc.MainDocumentPart.FootnotesPart, W.footnote, settings);
                    IEnumerable <WmlComparerRevision> endnotesRevisionList =
                        GetFootnoteEndnoteRevisionList(wDoc.MainDocumentPart.EndnotesPart, W.endnote, settings);

                    List <WmlComparerRevision> finalRevisionList = mainDocPartRevisionList
                                                                   .Concat(footnotesRevisionList)
                                                                   .Concat(endnotesRevisionList)
                                                                   .ToList();

                    return(finalRevisionList);
                }
            }
        }
        private static IEnumerable <WmlComparerRevision> GetFootnoteEndnoteRevisionList(
            OpenXmlPart footnotesEndnotesPart,
            XName footnoteEndnoteElementName,
            WmlComparerSettings settings)
        {
            if (footnotesEndnotesPart == null)
            {
                return(Enumerable.Empty <WmlComparerRevision>());
            }

            XDocument xDoc = footnotesEndnotesPart.GetXDocument();
            IEnumerable <XElement> footnotesEndnotes =
                xDoc.Root?.Elements(footnoteEndnoteElementName) ?? throw new OpenXmlPowerToolsException("Invalid document.");

            var revisionsForPart = new List <WmlComparerRevision>();

            foreach (XElement fn in footnotesEndnotes)
            {
                ComparisonUnitAtom[] atomList = CreateComparisonUnitAtomList(footnotesEndnotesPart, fn, settings).ToArray();

                if (False)
                {
                    var sb = new StringBuilder();
                    foreach (ComparisonUnitAtom item in atomList)
                    {
                        sb.Append(item + Environment.NewLine);
                    }

                    string sbs = sb.ToString();
                    TestUtil.NotePad(sbs);
                }

                List <IGrouping <string, ComparisonUnitAtom> > grouped = atomList
                                                                         .GroupAdjacent(a =>
                {
                    string key = a.CorrelationStatus.ToString();
                    if (a.CorrelationStatus != CorrelationStatus.Equal)
                    {
                        var rt = new XElement(a.RevTrackElement.Name,
                                              new XAttribute(XNamespace.Xmlns + "w",
                                                             "http://schemas.openxmlformats.org/wordprocessingml/2006/main"),
                                              a.RevTrackElement.Attributes().Where(a2 => a2.Name != W.id && a2.Name != PtOpenXml.Unid));

                        key += rt.ToString(SaveOptions.DisableFormatting);
                    }

                    return(key);
                })
                                                                         .ToList();

                List <IGrouping <string, ComparisonUnitAtom> > revisions = grouped
                                                                           .Where(k => k.Key != "Equal")
                                                                           .ToList();

                IEnumerable <WmlComparerRevision> thisNoteRevisionList = revisions
                                                                         .Select(rg =>
                {
                    var rev = new WmlComparerRevision();
                    if (rg.Key.StartsWith("Inserted"))
                    {
                        rev.RevisionType = WmlComparerRevisionType.Inserted;
                    }
                    else if (rg.Key.StartsWith("Deleted"))
                    {
                        rev.RevisionType = WmlComparerRevisionType.Deleted;
                    }

                    XElement revTrackElement = rg.First().RevTrackElement;
                    rev.RevisionXElement     = revTrackElement;
                    rev.Author          = (string)revTrackElement.Attribute(W.author);
                    rev.ContentXElement = rg.First().ContentElement;
                    rev.Date            = (string)revTrackElement.Attribute(W.date);
                    rev.PartUri         = footnotesEndnotesPart.Uri;
                    rev.PartContentType = footnotesEndnotesPart.ContentType;

                    if (!RevElementsWithNoText.Contains(rev.ContentXElement.Name))
                    {
                        rev.Text = rg
                                   .Select(rgc => rgc.ContentElement.Name == W.pPr ? NewLine : rgc.ContentElement.Value)
                                   .StringConcatenate();
                    }

                    return(rev);
                });

                revisionsForPart.AddRange(thisNoteRevisionList);
            }

            return(revisionsForPart);
        }