1 //
2 // Copyright (c) 2010-2023 Antmicro
3 // Copyright (c) 2011-2015 Realtime Embedded
4 //
5 // This file is licensed under the MIT License.
6 // Full license text is available in 'licenses/MIT.txt'.
7 //
8 
9 using System;
10 using System.Collections.Generic;
11 using System.Collections.ObjectModel;
12 using System.Collections;
13 using System.Linq;
14 
15 namespace Antmicro.Renode.Utilities.Collections
16 {
17 
18     public abstract class TreeBase<TNode, TValue> : IEnumerable<TValue> where TNode : TreeBase<TNode, TValue>
19     {
TreeBase(TValue value)20         protected TreeBase(TValue value)
21         {
22             this.value = value;
23             ChildrenList = new List<TNode>();
24             ParentsList = new List<TNode>();
25         }
26 
27         public IEnumerable<TNode> Children
28         {
29             get
30             {
31                 return new ReadOnlyCollection<TNode>(ChildrenList);
32             }
33         }
34 
35         public IEnumerable<TNode> Parents
36         {
37             get
38             {
39                 return new ReadOnlyCollection<TNode>(ParentsList);
40             }
41         }
42 
43         public TValue Value
44         {
45             get
46             {
47                 return value;
48             }
49         }
50 
TraverseChildrenFirst(Action<TNode, List<TNode>, int> nodeHandler, int initialLevel)51         public void TraverseChildrenFirst(Action<TNode, List<TNode>, int> nodeHandler, int initialLevel)
52         {
53             foreach(var child in ChildrenList)
54             {
55                 child.TraverseChildrenFirst(nodeHandler, initialLevel + 1);
56             }
57 
58             nodeHandler((TNode)this, ChildrenList, initialLevel);
59         }
60 
TraverseParentFirst(Action<TValue, int> nodeHandler, int initialLevel)61         public void TraverseParentFirst(Action<TValue, int> nodeHandler, int initialLevel)
62         {
63             nodeHandler(value, initialLevel);
64             foreach (var child in ChildrenList)
65             {
66                 child.TraverseParentFirst(nodeHandler, initialLevel + 1);
67             }
68         }
69 
TryGetNode(Func<TValue, bool> predicate)70         public TNode TryGetNode(Func<TValue, bool> predicate)
71         {
72             if(predicate(value))
73             {
74                 return (TNode)this;
75             }
76             foreach (var child in ChildrenList)
77             {
78                 var node = child.TryGetNode(predicate);
79                 if (node != null)
80                 {
81                     return node;
82                 }
83             }
84             return null;
85         }
86 
IEnumerable.GetEnumerator()87         IEnumerator IEnumerable.GetEnumerator()
88         {
89             return GetEnumerator();
90         }
91 
GetEnumerator()92         public IEnumerator<TValue> GetEnumerator()
93         {
94             yield return Value;
95             foreach(var child in ChildrenList)
96             {
97                 foreach(var element in child)
98                 {
99                     yield return element;
100                 }
101             }
102         }
103 
AddChild(TValue value)104         public abstract TNode AddChild(TValue value);
105 
TryGetNode(TValue valueToFind)106         public TNode TryGetNode(TValue valueToFind)
107         {
108             return TryGetNode(val => valueToFind.Equals(val));
109         }
110 
RemoveChild(TValue value)111         public virtual void RemoveChild(TValue value)
112         {
113             var node = ChildrenList.FirstOrDefault(x => value.Equals(x.Value));
114             if(node == null)
115             {
116                 throw new InvalidOperationException($"Could not find child '{value}'.");
117             }
118             ChildrenList.Remove(node);
119         }
120 
121         protected readonly List<TNode> ParentsList;
122         protected readonly List<TNode> ChildrenList;
123         private readonly TValue value;
124     }
125 }
126