In class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine:
[mono.git] / mcs / class / Microsoft.Build.Engine / Microsoft.Build.BuildEngine / BuildItemGroup.cs
1 //
2 // BuildItemGroup.cs: Represents a group of build items.
3 //
4 // Author:
5 //   Marek Sieradzki (marek.sieradzki@gmail.com)
6 // 
7 // (C) 2005 Marek Sieradzki
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
28 #if NET_2_0
29
30 using System;
31 using System.Reflection;
32 using System.Collections;
33 using System.Collections.Generic;
34 using System.Xml;
35 using Microsoft.Build.Framework;
36 using Microsoft.Build.Utilities;
37
38 namespace Microsoft.Build.BuildEngine {
39         public class BuildItemGroup : IEnumerable {
40         
41                 List <BuildItem>        buildItems;
42                 ImportedProject         importedProject;
43                 XmlElement              itemGroupElement;
44                 GroupingCollection      parentCollection;
45                 Project                 parentProject;
46                 bool                    read_only;
47
48                 public BuildItemGroup ()
49                         : this (null, null, null, false)
50                 {
51                 }
52
53                 internal BuildItemGroup (Project project)
54                         : this (null, project, null, false)
55                 {
56                 }
57
58                 internal BuildItemGroup (XmlElement xmlElement, Project project, ImportedProject importedProject, bool readOnly)
59                 {
60                         this.buildItems = new List <BuildItem> ();
61                         this.importedProject = importedProject;
62                         this.itemGroupElement = xmlElement;
63                         this.parentProject = project;
64                         this.read_only = readOnly;
65                         
66                         if (!FromXml)
67                                 return;
68
69                         foreach (XmlNode xn in xmlElement.ChildNodes) {
70                                 if (!(xn is XmlElement))
71                                         continue;
72                                         
73                                 XmlElement xe = (XmlElement) xn;
74                                 BuildItem bi = new BuildItem (xe, this);
75                                 buildItems.Add (bi);
76                                 project.LastItemGroupContaining [bi.Name] = this;
77                         }
78                 }
79
80                 public BuildItem AddNewItem (string itemName,
81                                              string itemInclude)
82                 {
83                         return AddNewItem (itemName, itemInclude, false);
84                 }
85                 
86                 [MonoTODO]
87                 public BuildItem AddNewItem (string itemName,
88                                              string itemInclude,
89                                              bool treatItemIncludeAsLiteral)
90                 {
91                         BuildItem item;
92
93                         if (treatItemIncludeAsLiteral)
94                                 itemInclude = Utilities.Escape (itemInclude);
95
96                         if (FromXml) {
97                                 XmlElement element = itemGroupElement.OwnerDocument.CreateElement (itemName, Project.XmlNamespace);
98                                 itemGroupElement.AppendChild (element);
99                                 element.SetAttribute ("Include", itemInclude);
100                                 item = new BuildItem (element, this);
101                         } else {
102                                 item = new BuildItem (itemName, itemInclude);
103                                 item.ParentItemGroup = this;
104                         }
105
106                         item.Evaluate (null, true);
107
108                         if (!read_only)
109                                 buildItems.Add (item);
110
111                         if (parentProject != null) {
112                                 parentProject.MarkProjectAsDirty ();
113                                 parentProject.NeedToReevaluate ();
114                         }
115
116                         return item;
117                 }
118                 
119                 public void Clear ()
120                 {
121                         if (FromXml)
122                                 itemGroupElement.RemoveAll ();
123                         
124                         buildItems = new List <BuildItem> ();
125
126                         if (parentProject != null) {
127                                 parentProject.MarkProjectAsDirty ();
128                                 parentProject.NeedToReevaluate ();
129                         }
130                 }
131
132                 [MonoTODO]
133                 public BuildItemGroup Clone (bool deepClone)
134                 {
135                         if (deepClone) {
136                                 if (FromXml)
137                                         throw new NotImplementedException ();
138                                 else
139                                         throw new NotImplementedException ();
140                         } else {
141                                 if (FromXml)
142                                         throw new InvalidOperationException ("A shallow clone of this object cannot be created.");
143                                 else
144                                         throw new NotImplementedException ();
145                         }
146                 }
147
148                 public IEnumerator GetEnumerator ()
149                 {
150                         return buildItems.GetEnumerator ();
151                 }
152
153                 public void RemoveItem (BuildItem itemToRemove)
154                 {
155                         if (itemToRemove == null)
156                                 return;
157
158                         itemToRemove.Detach ();
159
160                         buildItems.Remove (itemToRemove);
161                 }
162
163                 public void RemoveItemAt (int index)
164                 {
165                         BuildItem item = buildItems [index];
166
167                         RemoveItem (item);
168                 }
169
170                 public BuildItem[] ToArray ()
171                 {
172                         return buildItems.ToArray ();
173                 }
174
175                 internal void AddItem (BuildItem buildItem)
176                 {
177                         buildItems.Add (buildItem);
178                 }
179
180                 internal void AddItem (string name, ITaskItem taskItem)
181                 {
182                         BuildItem buildItem;
183                         buildItem = new BuildItem (name, taskItem);
184                         buildItem.ParentItemGroup = this;
185                         buildItems.Add (buildItem);
186                 }
187
188                 // In eval phase, any ref'ed item would've already been expanded
189                 // or it doesnt exist, so dont expand again
190                 // In non-eval, items have _already_ been expanded, so dont expand again
191                 // So, ignore @options
192                 internal string ConvertToString (Expression transform,
193                                                  Expression separator, ExpressionOptions options)
194                 {
195                         string separatorString;
196                         
197                         // Item refs are not expanded for separator or transform
198                         if (separator == null)
199                                 separatorString = ";";
200                         else
201                                 separatorString = (string) separator.ConvertTo (parentProject, typeof (string),
202                                                                 ExpressionOptions.DoNotExpandItemRefs);
203                 
204                         string[] items = new string [buildItems.Count];
205                         int i = 0;
206                         foreach (BuildItem bi in  buildItems)
207                                 items [i++] = bi.ConvertToString (transform, ExpressionOptions.DoNotExpandItemRefs);
208                         return String.Join (separatorString, items);
209                 }
210
211                 // In eval phase, any ref'ed item would've already been expanded
212                 // or it doesnt exist, so dont expand again
213                 // In non-eval, items have _already_ been expanded, so dont expand again
214                 // So, ignore @options
215                 internal ITaskItem[] ConvertToITaskItemArray (Expression transform, ExpressionOptions options)
216                 {
217                         ITaskItem[] array = new ITaskItem [buildItems.Count];
218                         int i = 0;
219                         foreach (BuildItem item in buildItems)
220                                 array [i++] = item.ConvertToITaskItem (transform, ExpressionOptions.DoNotExpandItemRefs);
221                         return array;
222                 }
223
224                 internal void Detach ()
225                 {
226                         if (!FromXml)
227                                 throw new InvalidOperationException ();
228
229                         itemGroupElement.ParentNode.RemoveChild (itemGroupElement);
230                 }
231
232                 internal void Evaluate ()
233                 {
234                         foreach (BuildItem bi in buildItems) {
235                                 if (bi.Condition == String.Empty)
236                                         bi.Evaluate (parentProject, true);
237                                 else {
238                                         ConditionExpression ce = ConditionParser.ParseCondition (bi.Condition);
239                                         bi.Evaluate (parentProject, ce.BoolEvaluate (parentProject));
240                                 }
241                         }
242                 }               
243
244                 internal void ReplaceWith (BuildItem item, List <BuildItem> list)
245                 {
246                         int index = buildItems.IndexOf (item);
247                         buildItems.RemoveAt (index);
248                         buildItems.InsertRange (index, list);
249                 }
250                 
251                 public string Condition {
252                         get {
253                                 if (FromXml)
254                                         return itemGroupElement.GetAttribute ("Condition");
255                                 else
256                                         return String.Empty;
257                         }
258                         set {
259                                 if (FromXml)
260                                         itemGroupElement.SetAttribute ("Condition", value);
261                                 else
262                                         throw new InvalidOperationException ("Cannot set a condition on an object not represented by an XML element in the project file.");
263                         }
264                 }
265
266                 public int Count {
267                         get { return buildItems.Count; }
268                 }
269
270                 public bool IsImported {
271                         get { return importedProject != null; }
272                 }
273
274                 
275                 [MonoTODO]
276                 public BuildItem this [int index] {
277                         get {
278                                 return buildItems [index];
279                         }
280                 }
281                 
282                 internal GroupingCollection GroupingCollection {
283                         get { return parentCollection; }
284                         set { parentCollection = value; }
285                 }
286                 
287                 internal Project ParentProject {
288                         get { return parentProject; }
289                         set {
290                                 if (parentProject != null)
291                                         throw new InvalidOperationException ("parentProject is already set");
292                                 parentProject = value;
293                         }
294                 }
295
296                 internal bool FromXml {
297                         get {
298                                 return itemGroupElement != null;
299                         }
300                 }
301
302                 internal XmlElement XmlElement {
303                         get {
304                                 return itemGroupElement;
305                         }       
306                 }
307         }
308 }
309
310 #endif