A document, consisting of a set of paragraphs
        /// <summary>
        ///     Fills the document whith the result of the import
        /// </summary>
        /// <param name="importResult"></param>
        public void CreateDocument(ImporterDocument importResult)
        {
            AddParagraph(
                "This document lists the changes that have been applied during the imporation of a new release of the specification");

            AddSubParagraph("Summary");
            AddParagraph("This section presents the summary of the document importation");
            AddTable(new string[] {"Item", "Count", "Comment"}, new int[] {40, 40, 60});
            AddRow("Paragraph count", importResult.Paragraphs.Count.ToString(),
                "This is the number of paragraphs processed during the importation of the document");
            AddRow("Modified paragraphs", importResult.ChangedParagraphs.Count.ToString(),
                "This is the number of paragraphs that have been changed between the two revisions");
            AddRow("New paragraphs", importResult.NewParagraphs.Count.ToString(),
                "The is the number of new paragraphs in this new revision");
            AddRow("Moved paragraphs", importResult.MovedParagraphs.Count.ToString(),
                "The is the number of paragraphs that have been moved around in this new revision");
            AddRow("Deleted paragraphs", importResult.RemovedParagraphs.Count.ToString(),
                "This is the number of paragraphs that have been deleted in this new revision");
            CloseSubParagraph();

            AddSubParagraph("Modified paragraphs");
            AddParagraph("This section lists the paragraphs that have been modified during the importation");
            foreach (Paragraph paragraph in importResult.ChangedParagraphs)
            {
                AddSubParagraph(paragraph.Id);
                AddSubParagraph("Original contents");
                AddParagraph(ValidText(paragraph.OriginalText));
                CloseSubParagraph();
                AddSubParagraph("New contents");
                AddParagraph(ValidText(paragraph.Text));
                CloseSubParagraph();
                CloseSubParagraph();
            }
            CloseSubParagraph();

            AddSubParagraph("New paragraphs");
            AddParagraph("This section lists the paragraphs that have been added during the importation");
            AddTable(new string[] {"Paragraph", "Contents"}, new int[] {40, 100});
            foreach (Paragraph paragraph in importResult.NewParagraphs)
            {
                AddRow(paragraph.Id, paragraph.Text);
            }
            CloseSubParagraph();
            AddSubParagraph("Removed paragraphs");
            AddParagraph("This section lists the paragraphs that have been removed during the importation");
            AddTable(new string[] {"Paragraph", "Contents"}, new int[] {40, 100});
            foreach (Paragraph paragraph in importResult.RemovedParagraphs)
            {
                AddRow(paragraph.Id, paragraph.Text);
            }
            CloseSubParagraph();

            AddSubParagraph("Moved paragraphs");
            AddParagraph(
                "This section lists the paragraphs that have been moved during the importation. No change has been performed in the model. Review should be performed manually.");
            AddTable(new string[] {"Paragraph", "Contents", "Initial position"}, new int[] {40, 100, 40});
            foreach (Paragraph paragraph in importResult.MovedParagraphs)
            {
                AddRow(paragraph.Id, paragraph.Text, paragraph.OriginalText);
            }
            CloseSubParagraph();

            AddSubParagraph("Errors during importation");
            AddParagraph(
                "This section lists the errors encountered during importation. No change has been performed in the model. Review should be performed manually.");
            AddTable(new string[] {"Paragraph", "Text", "Error"}, new int[] {30, 80, 80});
            foreach (ImportationError error in importResult.Errors)
            {
                AddRow(error.Paragraph.Id, error.Paragraph.Text, error.Message);
            }
            CloseSubParagraph();

            AddSubParagraph("List of paragraphs");
            AddParagraph("This section lists the paragraphs that have been processed during the importation");
            AddTable(new string[] {"Paragraph", "", "", "", ""}, new int[] {30, 30, 30, 30, 30});
            int i = 0;
            string[] data = new string[5] {"", "", "", "", ""};
            foreach (Paragraph paragraph in importResult.Paragraphs.Values)
            {
                data[i] = paragraph.Id;
                i += 1;

                if (i == data.Length)
                {
                    AddRow(data);
                    i = 0;
                    data = new string[5] {"", "", "", "", ""};
                }
            }

            if (i > 0)
            {
                AddRow(data);
            }
            CloseSubParagraph();
        }
        /// <summary>
        ///     Updates the state of the paragraphs located in source according to the original content, located in original
        /// </summary>
        /// <param name="original">The original file content</param>
        public void UpdateState(Document original)
        {
            // Find paragraphs that have been inserted and those that have been modified
            foreach (Paragraph p in Paragraphs.Values)
            {
                Paragraph originalParagraph = original.FindParagraph(p.Id);
                if (originalParagraph != null)
                {
                    if (originalParagraph.Text.Equals(p.Text))
                    {
                        p.State = Paragraph.ParagraphState.NoChange;
                    }
                    else
                    {
                        p.OriginalText = originalParagraph.Text;
                        p.State = Paragraph.ParagraphState.Changed;

                        // Maybe the row has been moved (new row inserted before), or this is a new row
                        TableRow row = p as TableRow;
                        TableRow originalRow = originalParagraph as TableRow;
                        if (originalRow != null)
                        {
                            // Try to determine if the paragraph as been moved (instead of changed)
                            // The paragraph has been moved when we can find it, at another location in the original table
                            foreach (Paragraph otherParagraph in original.Paragraphs.Values)
                            {
                                TableRow otherRow = otherParagraph as TableRow;
                                if (otherRow != null && otherRow.EnclosingParagraph == originalRow.EnclosingParagraph)
                                {
                                    if (otherRow.Text.Equals(p.Text))
                                    {
                                        p.State = Paragraph.ParagraphState.Moved;
                                        p.OriginalText = otherRow.Id;
                                        break;
                                    }
                                }
                            }
                            if (p.State == Paragraph.ParagraphState.Changed)
                            {
                                // If the paragraph has not been moved, try to determine if the paragraph has been inserted
                                // The paragraph has been inserted if the corresponding paragraph in the original table
                                // can be found at another location of this table
                                foreach (Paragraph otherParagraph in Paragraphs.Values)
                                {
                                    TableRow otherRow = otherParagraph as TableRow;
                                    if (otherRow != null && otherRow.EnclosingParagraph == row.EnclosingParagraph)
                                    {
                                        if (otherRow.Text.Equals(originalRow.Text))
                                        {
                                            p.State = Paragraph.ParagraphState.Inserted;
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                    // Original paragraph could not be found => This is a new paragraph
                    p.State = Paragraph.ParagraphState.Inserted;

                    TableRow originalRow = originalParagraph as TableRow;
                    if (originalRow != null)
                    {
                        // Try to determine if the paragraph as been moved (instead of changed)
                        // The paragraph has been moved when we can find it, at another location in the original table
                        foreach (Paragraph otherParagraph in original.Paragraphs.Values)
                        {
                            TableRow otherRow = otherParagraph as TableRow;
                            if (otherRow != null && otherRow.EnclosingParagraph == originalRow.EnclosingParagraph)
                            {
                                if (otherRow.Text.Equals(p.Text))
                                {
                                    p.State = Paragraph.ParagraphState.Moved;
                                    p.OriginalText = otherRow.Id;
                                    break;
                                }
                            }
                        }
                    }
                }
            }

            // Find paragraphs that have been deleted
            foreach (Paragraph p in original.Paragraphs.Values)
            {
                Paragraph newParagraph = FindParagraph(p.Id);
                if (newParagraph == null)
                {
                    p.State = Paragraph.ParagraphState.Deleted;
                    Paragraphs.Add(p.Id, p);
                }
            }
        }