Update mcs/class/Commons.Xml.Relaxng/Commons.Xml.Relaxng/RelaxngPattern.cs
[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                                                 project.PushThisFileProperty (bpg.DefinedInFileName);
184                                                 try {
185                                                         if (ConditionParser.ParseAndEvaluate (bpg.Condition, project))
186                                                                 bpg.Evaluate ();
187                                                 } finally {
188                                                         project.PopThisFileProperty ();
189                                                 }
190                                         }
191
192                                         // if it wasn't moved by adding anything because of evaluating a Import shift it
193                                         if (add_iterator == evaluate_iterator)
194                                                 add_iterator = add_iterator.Next;
195
196                                         evaluate_iterator = evaluate_iterator.Next;
197                                 }
198                         } else if (type == EvaluationType.Item) {
199                                 evaluate_iterator = list.First;
200                                 add_iterator = list.First;
201
202                                 while (evaluate_iterator != null) {
203                                         if (evaluate_iterator.Value is BuildItemGroup) {
204                                                 big = (BuildItemGroup) evaluate_iterator.Value;
205                                                 project.PushThisFileProperty (big.DefinedInFileName);
206                                                 try {
207                                                         if (ConditionParser.ParseAndEvaluate (big.Condition, project))
208                                                                 big.Evaluate ();
209                                                 } finally {
210                                                         project.PopThisFileProperty ();
211                                                 }
212                                         }
213
214                                         evaluate_iterator = evaluate_iterator.Next;
215                                 }
216                         } else if (type == EvaluationType.Choose) {
217                                 evaluate_iterator = list.First;
218                                 add_iterator = list.First;
219
220                                 while (evaluate_iterator != null) {
221                                         if (evaluate_iterator.Value is BuildChoose) {
222                                                 BuildChoose bc = (BuildChoose)evaluate_iterator.Value;
223                                                 project.PushThisFileProperty (bc.DefinedInFileName);
224                                                 try {
225                                                         bool whenUsed = false;
226                                                         foreach (BuildWhen bw in bc.Whens) {
227                                                                 if (ConditionParser.ParseAndEvaluate (bw.Condition, project)) {
228                                                                         bw.Evaluate ();
229                                                                         whenUsed = true;
230                                                                         break;
231                                                                 }
232                                                         }
233                                                         if (!whenUsed && bc.Otherwise != null &&
234                                                                 ConditionParser.ParseAndEvaluate (bc.Otherwise.Condition, project)) {
235                                                                 bc.Otherwise.Evaluate ();
236                                                         }
237                                                 } finally {
238                                                         project.PopThisFileProperty ();
239                                                 }
240                                         }
241
242                                         evaluate_iterator = evaluate_iterator.Next;
243                                 }
244                         }
245
246                         add_iterator = null;
247                 }
248
249                 internal int Imports {
250                         get { return this.imports; }
251                 }
252                 
253                 internal int ItemGroups {
254                         get { return this.itemGroups; }
255                 }
256                 
257                 internal int PropertyGroups {
258                         get { return this.propertyGroups; }
259                 }
260                 
261                 internal int Chooses {
262                         get { return this.chooses; }
263                 } 
264         }
265
266         enum EvaluationType {
267                 Property,
268                 Item,
269                 Choose
270         }
271 }
272
273 #endif