< Summary

Class:MUNity.Extensions.ResolutionExtensions.OperativeParagraphTools
Assembly:MUNity.Schema
File(s):C:\Users\aeuke\source\repos\PeerConradi\munity\src\MUNitySchema\Extensions\ResolutionExtensions\OperativeParagraphTools.cs
Covered lines:0
Uncovered lines:255
Coverable lines:255
Total lines:481
Line coverage:0% (0 of 255)
Covered branches:0
Total branches:112
Branch coverage:0% (0 of 112)
Covered methods:0
Total methods:23
Method coverage:0% (0 of 23)

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
CreateOperativeParagraph(...)100%10%
CreateChildParagraph(...)0%20%
CreateChildParagraph(...)100%10%
FindOperativeParagraph(...)100%10%
FindOperativeParagraphPathRecursive(...)0%100%
GetOperativeParagraphPath(...)0%40%
RemoveOperativeParagraph(...)0%220%
GetRealOperativeParagraphsInfo(...)0%20%
AddRealOperativeParagraphInfoRec(...)0%140%
InsertIntoRealPosition(...)0%60%
GetIndexNameOfOperativeParagraph(...)0%80%
IndexOfParagraph(...)0%20%
GetAllOperativeParagraphIds(...)0%20%
WhereParagraph(...)0%20%
DeepWhere(...)0%60%
FirstOrDefault(...)0%60%
DeepFirstOrDefault(...)0%40%
GetIndexNameOfOperativeParagraph(...)100%10%
AddAllChildrenRecursive(...)0%60%
GetAllParagraphs(...)0%20%
TraverseParagraph(...)0%60%
GetOrderedAmendments(...)0%80%
GetAllAmendments(...)100%10%

File(s)

C:\Users\aeuke\source\repos\PeerConradi\munity\src\MUNitySchema\Extensions\ResolutionExtensions\OperativeParagraphTools.cs

#LineLine coverage
 1using MUNity.Extensions.Conversion;
 2using MUNity.Models.Resolution;
 3using System;
 4using System.Collections.Generic;
 5using System.Linq;
 6using System.Text;
 7
 8namespace MUNity.Extensions.ResolutionExtensions
 9{
 10
 11    /// <summary>
 12    /// This set of extension methods contains logic to work with operative paragraphs and the operative section.
 13    /// </summary>
 14    public static class OperativeParagraphTools
 15    {
 16
 17        /// <summary>
 18        /// Creates a new Operative paragraph inside a given OperativeSection.
 19        /// </summary>
 20        /// <param name="section"></param>
 21        /// <param name="text"></param>
 22        /// <returns></returns>
 23        public static OperativeParagraph CreateOperativeParagraph(this OperativeSection section, string text = "")
 024        {
 025            var paragraph = new OperativeParagraph
 026            {
 027                Text = text
 028            };
 029            section.Paragraphs.Add(paragraph);
 030            return paragraph;
 031        }
 32
 33        /// <summary>
 34        /// Creates a new Child paragraph in a given Resolution.
 35        /// </summary>
 36        /// <param name="section"></param>
 37        /// <param name="parentId"></param>
 38        /// <param name="text"></param>
 39        /// <returns></returns>
 40        public static OperativeParagraph CreateChildParagraph(this OperativeSection section, string parentId, string tex
 041        {
 042            var parentParagraph = section.FindOperativeParagraph(parentId);
 043            if (parentParagraph == null)
 044                throw new MUNity.Exceptions.Resolution.OperativeParagraphNotFoundException();
 45
 046            var newParagraph = new OperativeParagraph
 047            {
 048                Text = text
 049            };
 050            parentParagraph.Children.Add(newParagraph);
 051            return newParagraph;
 052        }
 53
 54        /// <summary>
 55        /// Will also create a Child paragraph by calling the CreateChildParagraph function and pass the Id to it.
 56        /// </summary>
 57        /// <param name="section"></param>
 58        /// <param name="parent"></param>
 59        /// <param name="text"></param>
 60        /// <returns></returns>
 61        public static OperativeParagraph CreateChildParagraph(this OperativeSection section, OperativeParagraph parent, 
 062            => section.CreateChildParagraph(parent.OperativeParagraphId, text);
 63
 64        /// <summary>
 65        /// Will search for an Operative Paragraph with the given id. Will return null if the paragraph was not found.
 66        /// </summary>
 67        /// <param name="section"></param>
 68        /// <param name="id"></param>
 69        /// <returns></returns>
 70        public static OperativeParagraph FindOperativeParagraph(this OperativeSection section, string id)
 071        {
 072            return section.FirstOrDefault(n => n.OperativeParagraphId == id);
 073        }
 74
 75        /// <summary>
 76        /// An internal function to go throw all operative paragraphs and their child paragraphs and get the path of the
 77        /// </summary>
 78        /// <param name="paragraph"></param>
 79        /// <param name="targetId"></param>
 80        /// <param name="path"></param>
 81        /// <returns></returns>
 82        private static OperativeParagraph FindOperativeParagraphPathRecursive(OperativeParagraph paragraph, string targe
 083        {
 084            if (paragraph.OperativeParagraphId == targetId)
 085            {
 086                path.Add(paragraph);
 087                return paragraph;
 88            }
 089            if (paragraph.Children != null && paragraph.Children.Any())
 090            {
 091                foreach (var child in paragraph.Children)
 092                {
 093                    var result = FindOperativeParagraphPathRecursive(child, targetId, path);
 094                    if (result != null)
 095                    {
 096                        path.Add(paragraph);
 097                        return result;
 98                    }
 99
 0100                }
 0101            }
 0102            return null;
 0103        }
 104
 105        /// <summary>
 106        /// Returns the Path of a Operative Paragraph as a List where every paragraph is an element to get to the last.
 107        /// For Example
 108        /// HeadParagraph > ChildParagraph1 > TargetParagraph.
 109        /// </summary>
 110        /// <param name="section"></param>
 111        /// <param name="id"></param>
 112        /// <returns></returns>
 113        public static List<OperativeParagraph> GetOperativeParagraphPath(this OperativeSection section, string id)
 0114        {
 0115            var path = new List<OperativeParagraph>();
 0116            foreach (var paragraph in section.Paragraphs)
 0117            {
 0118                var result = FindOperativeParagraphPathRecursive(paragraph, id, path);
 0119                if (result != null)
 0120                {
 0121                    path.Reverse();
 0122                    return path;
 123                }
 0124            }
 0125            return null;
 0126        }
 127
 128        /// <summary>
 129        /// Removes an Operative Paragraph from the Operative Section. Will also remove all the amendments that
 130        /// are targeting this paragraph.
 131        /// </summary>
 132        /// <param name="section"></param>
 133        /// <param name="paragraph"></param>
 134        public static void RemoveOperativeParagraph(this OperativeSection section, OperativeParagraph paragraph)
 0135        {
 0136            var path = section.GetOperativeParagraphPath(paragraph.OperativeParagraphId);
 0137            if (path == null || !path.Any())
 0138                throw new MUNity.Exceptions.Resolution.OperativeParagraphNotFoundException();
 139
 0140            if (path.Count == 1)
 0141            {
 0142                section.Paragraphs.Remove(paragraph);
 0143            }
 144            else
 0145            {
 0146                path[path.Count - 1].Children.Remove(paragraph);
 0147            }
 148
 149            // TODO: Remove all Amendments of this paragraph and all its child paragraphs!
 0150            foreach (var amendment in section.AddAmendments.Where(n => n.TargetSectionId == paragraph.OperativeParagraph
 0151            {
 0152                section.RemoveAmendment(amendment);
 0153            }
 154
 0155            foreach(var changeAmendment in section.ChangeAmendments.Where(n => n.TargetSectionId == paragraph.OperativeP
 0156            {
 0157                section.RemoveAmendment(changeAmendment);
 0158            }
 159
 0160            foreach(var deleteAmendment in section.DeleteAmendments.Where(n => n.TargetSectionId == paragraph.OperativeP
 0161            {
 0162                section.RemoveAmendment(deleteAmendment);
 0163            }
 164
 0165            foreach(var moveAmendment in section.MoveAmendments.Where(n => n.TargetSectionId == paragraph.OperativeParag
 0166            {
 0167                section.RemoveAmendment(moveAmendment);
 0168            }
 0169        }
 170
 171        /// <summary>
 172        /// Will return a list of suple with all information about the operative paragraphs.
 173        /// </summary>
 174        /// <param name="resolution"></param>
 175        /// <returns></returns>
 176        public static List<(string id, string path, string text)> GetRealOperativeParagraphsInfo(this Resolution resolut
 0177        {
 0178            var list = new List<(string id, string path, string text)>();
 0179            var realParagraphs = resolution.OperativeSection.Paragraphs.Where(n => !n.IsVirtual);
 0180            int index = 1;
 0181            foreach (var paragraph in realParagraphs)
 0182            {
 0183                string prePath = index.ToString();
 0184                AddRealOperativeParagraphInfoRec(prePath, paragraph, list);
 0185                index++;
 0186            }
 0187            return list;
 0188        }
 189
 190        /// <summary>
 191        /// Recursive function used by GetRealOperativeParagraphsInfo
 192        /// </summary>
 193        /// <param name="prePath"></param>
 194        /// <param name="paragraph"></param>
 195        /// <param name="list"></param>
 196        private static void AddRealOperativeParagraphInfoRec(string prePath, OperativeParagraph paragraph, List<(string 
 0197        {
 0198            var newElement = (id: paragraph.OperativeParagraphId, path: prePath, text: paragraph.Text);
 0199            list.Add(newElement);
 0200            if (paragraph.Children != null && paragraph.Children.Any())
 0201            {
 0202                var realParagraphs = paragraph.Children.Where(n => !n.IsVirtual);
 0203                int index = 1;
 0204                prePath += ".";
 0205                int level = prePath.Count(n => n == '.');
 0206                foreach (var childParagraph in realParagraphs)
 0207                {
 0208                    var newPath = prePath;
 0209                    if (level == 1 || level % 4 == 1) newPath += (index - 1).ToLetter();
 0210                    else if (level == 2 || level % 5 == 2) newPath += (index).ToRoman().ToLower();
 0211                    AddRealOperativeParagraphInfoRec(newPath, childParagraph, list);
 0212                    index++;
 0213                }
 0214            }
 0215        }
 216
 217        /// <summary>
 218        /// Inserts a paragraph into the real position. The index you give here is the one that you would get by blockin
 219        /// For example: 1, (2), (3), 4, (5) where paragraph 2,3 and 5 are virtual, then the assumption is that paragrap
 220        /// the case. You would pass 2 to this function if you want to add a paragraph between 4 but before 5.
 221        /// </summary>
 222        /// <param name="section"></param>
 223        /// <param name="paragraph"></param>
 224        /// <param name="targetIndex"></param>
 225        /// <param name="parentParagraph"></param>
 226        /// <returns></returns>
 227        public static int InsertIntoRealPosition(this OperativeSection section, OperativeParagraph paragraph, int target
 0228        {
 0229            if (parentParagraph == null)
 0230            {
 0231                if (targetIndex > section.Paragraphs.Count) targetIndex = section.Paragraphs.Count;
 0232                section.Paragraphs.Insert(targetIndex, paragraph);
 0233            }
 234            else
 0235            {
 0236                if (section.FindOperativeParagraph(parentParagraph.OperativeParagraphId) == null)
 0237                    throw new MUNity.Exceptions.Resolution.OperativeParagraphNotFoundException("Target parent Paragraph 
 238
 0239                parentParagraph.Children.Insert(targetIndex, paragraph);
 0240            }
 0241            return targetIndex;
 0242        }
 243
 244        /// <summary>
 245        /// Returns the displayed Index name of a Paragraph for example
 246        /// 1, 2, 2.a, 2.a.i etc.
 247        /// </summary>
 248        /// <param name="section"></param>
 249        /// <param name="paragraphId"></param>
 250        /// <returns></returns>
 251        public static string GetIndexNameOfOperativeParagraph(this OperativeSection section, string paragraphId)
 0252        {
 0253            if (string.IsNullOrEmpty(paragraphId) ||section == null)
 0254                return "";
 255
 0256            var path = section.GetOperativeParagraphPath(paragraphId);
 0257            var numbers = new List<int>();
 0258            OperativeParagraph parent = null;
 0259            foreach (var paragraph in path)
 0260            {
 0261                if (parent == null)
 0262                {
 0263                    numbers.Add(section.Paragraphs.Where(n => !n.IsVirtual).ToList().IndexOf(paragraph));
 0264                }
 265                else
 0266                {
 0267                    numbers.Add(parent.Children.Where(n => !n.IsVirtual).ToList().IndexOf(paragraph));
 0268                }
 0269                parent = paragraph;
 0270            }
 0271            return numbers.ToArray().ToPathname();
 0272        }
 273
 274        /// <summary>
 275        /// Returns the Index of a paragraph inside its parent.
 276        /// </summary>
 277        /// <param name="section"></param>
 278        /// <param name="paragraph"></param>
 279        /// <returns></returns>
 280        public static int IndexOfParagraph(this OperativeSection section, OperativeParagraph paragraph)
 0281        {
 0282            int index = section.Paragraphs.IndexOf(paragraph);
 0283            if (index != -1) return index;
 0284            var path = section.GetOperativeParagraphPath(paragraph.OperativeParagraphId);
 0285            var parentElement = path[path.Count - 1];
 0286            return parentElement.Children.IndexOf(paragraph);
 0287        }
 288
 289
 290        /// <summary>
 291        /// Returns a list of all Ids of all operative paragraphs that exist.
 292        /// </summary>
 293        /// <param name="section"></param>
 294        /// <returns></returns>
 295        public static List<string> GetAllOperativeParagraphIds(this OperativeSection section)
 0296        {
 0297            var list = new List<string>();
 0298            list.AddRange(section.Paragraphs.Select(n => n.OperativeParagraphId));
 0299            foreach(var paragraph in section.Paragraphs)
 0300            {
 0301                AddAllChildrenRecursive(paragraph, list);
 0302            }
 0303            return list;
 0304        }
 305
 306        /// <summary>
 307        /// Will execute a Linq Where inside all operative paragraphs including Child paragraphs.
 308        /// </summary>
 309        /// <param name="operativeSection"></param>
 310        /// <param name="predicate"></param>
 311        /// <returns></returns>
 312        public static List<OperativeParagraph> WhereParagraph(this OperativeSection operativeSection, Func<OperativePara
 0313        {
 0314            var list = new List<OperativeParagraph>();
 0315            list.AddRange(operativeSection.Paragraphs.Where(predicate));
 0316            foreach(var paragraph in operativeSection.Paragraphs)
 0317            {
 0318                DeepWhere(paragraph, predicate, list);
 0319            }
 0320            return list;
 0321        }
 322
 323        /// <summary>
 324        /// needed fore WhereParagraph.
 325        /// </summary>
 326        /// <param name="parentParagraph"></param>
 327        /// <param name="predicate"></param>
 328        /// <param name="resultList"></param>
 329        private static void DeepWhere(OperativeParagraph parentParagraph, Func<OperativeParagraph, bool> predicate, List
 0330        {
 0331            if (parentParagraph.Children != null && parentParagraph.Children.Any())
 0332            {
 0333                resultList.AddRange(parentParagraph.Children.Where(predicate));
 0334                foreach(var child in parentParagraph.Children)
 0335                {
 0336                    DeepWhere(child, predicate, resultList);
 0337                }
 0338            }
 0339        }
 340
 341        /// <summary>
 342        /// Will make a Linq FirstOrDefault in all operative paragraphs including child paragraphs.
 343        /// </summary>
 344        /// <param name="operativeSection"></param>
 345        /// <param name="predicate"></param>
 346        /// <returns></returns>
 347        public static OperativeParagraph FirstOrDefault(this OperativeSection operativeSection, Func<OperativeParagraph,
 0348        {
 0349            var result = operativeSection.Paragraphs.FirstOrDefault(predicate);
 0350            if (result != null) return result;
 0351            foreach (var s in operativeSection.Paragraphs)
 0352            {
 0353                result = DeepFirstOrDefault(s, predicate);
 0354                if (result != null) return result;
 0355            }
 0356            return null;
 0357        }
 358
 359        /// <summary>
 360        /// used by FirstOrDefault
 361        /// </summary>
 362        /// <param name="paragraph"></param>
 363        /// <param name="predicate"></param>
 364        /// <returns></returns>
 365        private static OperativeParagraph DeepFirstOrDefault(this OperativeParagraph paragraph, Func<OperativeParagraph,
 0366        {
 0367            var result = paragraph.Children.FirstOrDefault(predicate);
 0368            if (result != null) return result;
 0369            foreach (var child in paragraph.Children)
 0370            {
 0371                return DeepFirstOrDefault(child, predicate);
 372            }
 0373            return null;
 0374        }
 375
 376
 377        #region function linking
 378        /// <summary>
 379        /// Gets the Index/Pathname of an operative paragraph.
 380        /// </summary>
 381        /// <param name="section"></param>
 382        /// <param name="paragraph"></param>
 383        /// <returns></returns>
 0384        public static string GetIndexNameOfOperativeParagraph(this OperativeSection section, OperativeParagraph paragrap
 385        #endregion
 386
 387        #region internal
 388        /// <summary>
 389        /// Adds all children to a list to create one List of all paragraphIds.
 390        /// </summary>
 391        /// <param name="paragraph"></param>
 392        /// <param name="list"></param>
 393        private static void AddAllChildrenRecursive(OperativeParagraph paragraph, List<string> list)
 0394        {
 0395            if (paragraph.Children != null && paragraph.Children.Any())
 0396            {
 0397                list.AddRange(paragraph.Children.Select(n => n.OperativeParagraphId));
 0398                foreach(var child in paragraph.Children)
 0399                {
 0400                    AddAllChildrenRecursive(child, list);
 0401                }
 0402            }
 0403        }
 404        #endregion
 405
 406        /// <summary>
 407        /// Returns a Flat List of all the Operative Paragraphs in one Level, meaning all Child Paragraphs will also
 408        /// be part of this list!
 409        /// </summary>
 410        /// <param name="section"></param>
 411        /// <returns></returns>
 412        public static List<OperativeParagraph> GetAllParagraphs(this OperativeSection section)
 0413        {
 0414            var list = new List<OperativeParagraph>();
 0415            foreach(var paragraph in section.Paragraphs)
 0416            {
 0417                TraverseParagraph(paragraph, list);
 0418            }
 0419            return list;
 0420        }
 421
 422        private static void TraverseParagraph(OperativeParagraph paragraph, List<OperativeParagraph> targetList)
 0423        {
 0424            targetList.Add(paragraph);
 0425            if (paragraph.Children != null && paragraph.Children.Any())
 0426            {
 0427                targetList.AddRange(paragraph.Children);
 0428                foreach(var child in paragraph.Children)
 0429                {
 0430                    TraverseParagraph(child, targetList);
 0431                }
 0432            }
 0433        }
 434
 435        /// <summary>
 436        /// Returns all Amendments in order of
 437        /// </summary>
 438        /// <param name="section"></param>
 439        /// <returns></returns>
 440        public static IEnumerable<AbstractAmendment> GetOrderedAmendments(this OperativeSection section)
 0441        {
 0442            var list = new List<AbstractAmendment>();
 0443            var allParagraphs = section.GetAllParagraphs();
 0444            foreach (var paragraph in allParagraphs)
 0445            {
 0446                var deleteAmendments = section.DeleteAmendments.Where(n => n.TargetSectionId ==
 0447                paragraph.OperativeParagraphId).OrderBy(n => n.SubmitTime).ToList();
 0448                if (deleteAmendments.Any())
 0449                    list.AddRange(deleteAmendments);
 450
 0451                var changeAmendments = section.ChangeAmendments.Where(n => n.TargetSectionId ==
 0452                paragraph.OperativeParagraphId).OrderBy(n => n.SubmitTime).ToList();
 0453                if (changeAmendments.Any())
 0454                    list.AddRange(changeAmendments);
 455
 0456                var moveAmendments = section.MoveAmendments.Where(n => n.TargetSectionId ==
 0457                paragraph.OperativeParagraphId).OrderBy(n => n.SubmitTime).ToList();
 0458                if (moveAmendments.Any())
 0459                    list.AddRange(moveAmendments);
 0460            }
 461
 0462            list.AddRange(section.AddAmendments);
 0463            allParagraphs.Clear();
 0464            return list;
 0465        }
 466
 467        /// <summary>
 468        /// Returns all Amendments starting with the Add Amendments then ChangeAmendments, DeleteAmendments and MoveAmen
 469        /// </summary>
 470        /// <param name="section"></param>
 471        /// <returns></returns>
 472        public static IEnumerable<AbstractAmendment> GetAllAmendments(this OperativeSection section)
 0473        {
 474
 0475            return section.AddAmendments
 0476                .Union<AbstractAmendment>(section.ChangeAmendments)
 0477                .Union(section.DeleteAmendments)
 0478                .Union(section.MoveAmendments);
 0479        }
 480    }
 481}