35b321d281626ef646b35fcb64bdf2a46061cf33
[mono.git] / mcs / class / Microsoft.Build.Engine / Microsoft.Build.BuildEngine / GroupingCollection.cs
1 //
2 // GroupingCollection.cs: Represents group of BuildItemGroup,
3 // BuildPropertyGroup and BuildChoose.
4 //
5 // Author:
6 //   Marek Sieradzki (marek.sieradzki@gmail.com)
7 // 
8 // (C) 2005 Marek Sieradzki
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 //
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 //
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
29 #if NET_2_0
30
31 using System;
32 using System.Collections;
33 using System.Collections.Generic;
34
35 namespace Microsoft.Build.BuildEngine {
36         internal class GroupingCollection : IEnumerable {
37                 
38                 int     imports;
39                 int     itemGroups;
40                 Project project;
41                 int     propertyGroups;
42                 int     chooses;
43
44                 LinkedList <object>     list;
45                 LinkedListNode <object> add_iterator;
46         
47                 public GroupingCollection (Project project)
48                 {
49                         list = new LinkedList <object> ();
50                         add_iterator = null;
51                         this.project = project;
52                 }
53
54                 public IEnumerator GetChooseEnumerator ()
55                 {
56                         foreach (object o in list)
57                                 if (o is BuildChoose)
58                                         yield return o;
59                 }
60
61                 public IEnumerator GetEnumerator ()
62                 {
63                         return list.GetEnumerator ();
64                 }
65
66                 public IEnumerator GetImportEnumerator ()
67                 {
68                         foreach (object o in list)
69                                 if (o is Import)
70                                         yield return o;
71                 }
72
73                 public IEnumerator GetItemGroupAndChooseEnumerator ()
74                 {
75                         foreach (object o in list)
76                                 if (o is BuildItemGroup || o is BuildPropertyGroup)
77                                         yield return o;
78                 }
79
80                 public IEnumerator GetItemGroupEnumerator ()
81                 {
82                         foreach (object o in list)
83                                 if (o is BuildItemGroup)
84                                         yield return o;
85                 }
86
87                 public IEnumerator GetPropertyGroupAndChooseEnumerator ()
88                 {
89                         foreach (object o in list)
90                                 if (o is BuildPropertyGroup || o is BuildChoose)
91                                         yield return o;
92                 }
93
94                 public IEnumerator GetPropertyGroupEnumerator ()
95                 {
96                         foreach (object o in list)
97                                 if (o is BuildPropertyGroup)
98                                         yield return o;
99                 }
100                 
101                 internal void Add (BuildPropertyGroup bpg)
102                 {
103                         bpg.GroupingCollection = this;
104                         propertyGroups++;
105                         if (add_iterator == null)
106                                 list.AddLast (bpg);
107                         else {
108                                 list.AddAfter (add_iterator, bpg);
109                                 add_iterator = add_iterator.Next;
110                         }
111                 }
112                 
113                 internal void Add (BuildItemGroup big)
114                 {
115                         itemGroups++;
116                         if (add_iterator == null)
117                                 list.AddLast (big);
118                         else {
119                                 list.AddAfter (add_iterator, big);
120                                 add_iterator = add_iterator.Next;
121                         }
122                 }
123                 
124                 internal void Add (BuildChoose bc)
125                 {
126                         chooses++;
127                         if (add_iterator == null)
128                                 list.AddLast (bc);
129                         else {
130                                 list.AddAfter (add_iterator, bc);
131                                 add_iterator = add_iterator.Next;
132                         }
133                 }
134
135                 internal void Add (Import import)
136                 {
137                         imports++;
138                         if (add_iterator == null)
139                                 list.AddLast (import);
140                         else {
141                                 list.AddAfter (add_iterator, import);
142                                 add_iterator = add_iterator.Next;
143                         }
144                 }
145
146                 internal void Remove (BuildItemGroup big)
147                 {
148                         if (big.ParentProject != project)
149                                 throw new InvalidOperationException (
150                                         "The \"BuildItemGroup\" object specified does not belong to the correct \"Project\" object.");
151
152                         big.Detach ();
153                         list.Remove (big);
154                 }
155
156                 internal void Remove (BuildPropertyGroup bpg)
157                 {
158                         // FIXME: add bpg.Detach ();
159                         bpg.XmlElement.ParentNode.RemoveChild (bpg.XmlElement);
160                         list.Remove (bpg);
161                 }
162
163                 internal void Evaluate ()
164                 {
165                         Evaluate (EvaluationType.Property);
166                         Evaluate (EvaluationType.Item);
167                         Evaluate (EvaluationType.Choose);
168                 }
169
170                 internal void Evaluate (EvaluationType type)
171                 {
172                         BuildItemGroup big;
173                         BuildPropertyGroup bpg;
174                         LinkedListNode <object> evaluate_iterator;
175
176                         if (type == EvaluationType.Property) {
177                                 evaluate_iterator = list.First;
178                                 add_iterator = list.First;
179
180                                 while (evaluate_iterator != null) {
181                                         if (evaluate_iterator.Value is BuildPropertyGroup) {
182                                                 bpg = (BuildPropertyGroup) evaluate_iterator.Value;
183                                                 if (ConditionParser.ParseAndEvaluate (bpg.Condition, project))
184                                                         bpg.Evaluate ();
185                                         }
186
187                                         // if it wasn't moved by adding anything because of evaluating a Import shift it
188                                         if (add_iterator == evaluate_iterator)
189                                                 add_iterator = add_iterator.Next;
190
191                                         evaluate_iterator = evaluate_iterator.Next;
192                                 }
193                         } else if (type == EvaluationType.Item) {
194                                 evaluate_iterator = list.First;
195                                 add_iterator = list.First;
196
197                                 while (evaluate_iterator != null) {
198                                         if (evaluate_iterator.Value is BuildItemGroup) {
199                                                 big = (BuildItemGroup) evaluate_iterator.Value;
200                                                 if (ConditionParser.ParseAndEvaluate (big.Condition, project))
201                                                         big.Evaluate ();
202                                         }
203
204                                         evaluate_iterator = evaluate_iterator.Next;
205                                 }
206                         } else if (type == EvaluationType.Choose) {
207                                 evaluate_iterator = list.First;
208                                 add_iterator = list.First;
209
210                                 while (evaluate_iterator != null) {
211                                         if (evaluate_iterator.Value is BuildChoose) {
212                                                 BuildChoose bc = (BuildChoose)evaluate_iterator.Value;
213                                                 bool whenUsed = false;
214                                                 foreach (BuildWhen bw in bc.Whens) {
215                                                         if (ConditionParser.ParseAndEvaluate (bw.Condition, project)) {
216                                                                 bw.Evaluate ();
217                                                                 whenUsed = true;
218                                                                 break;
219                                                         }
220                                                 }
221                                                 if (!whenUsed && bc.Otherwise != null &&
222                                                         ConditionParser.ParseAndEvaluate (bc.Otherwise.Condition, project)) {
223                                                         bc.Otherwise.Evaluate ();
224                                                 }
225                                         }
226
227                                         evaluate_iterator = evaluate_iterator.Next;
228                                 }
229                         }
230
231                         add_iterator = null;
232                 }
233
234                 internal int Imports {
235                         get { return this.imports; }
236                 }
237                 
238                 internal int ItemGroups {
239                         get { return this.itemGroups; }
240                 }
241                 
242                 internal int PropertyGroups {
243                         get { return this.propertyGroups; }
244                 }
245                 
246                 internal int Chooses {
247                         get { return this.chooses; }
248                 } 
249         }
250
251         enum EvaluationType {
252                 Property,
253                 Item,
254                 Choose
255         }
256 }
257
258 #endif