fe3113b1e3e7a31e58124e15b00d4bb1777a9f83
[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                 bool evaluated;
48
49                 public BuildItemGroup ()
50                         : this (null, null, null, false)
51                 {
52                 }
53
54                 internal BuildItemGroup (Project project)
55                         : this (null, project, null, false)
56                 {
57                 }
58
59                 internal BuildItemGroup (XmlElement xmlElement, Project project, ImportedProject importedProject, bool readOnly)
60                 {
61                         this.buildItems = new List <BuildItem> ();
62                         this.importedProject = importedProject;
63                         this.itemGroupElement = xmlElement;
64                         this.parentProject = project;
65                         this.read_only = readOnly;
66                         
67                         if (!FromXml)
68                                 return;
69
70                         foreach (XmlNode xn in xmlElement.ChildNodes) {
71                                 if (!(xn is XmlElement))
72                                         continue;
73                                         
74                                 XmlElement xe = (XmlElement) xn;
75                                 BuildItem bi = new BuildItem (xe, this);
76                                 buildItems.Add (bi);
77                                 project.LastItemGroupContaining [bi.Name] = this;
78                         }
79                 }
80
81                 public BuildItem AddNewItem (string itemName,
82                                              string itemInclude)
83                 {
84                         return AddNewItem (itemName, itemInclude, false);
85                 }
86                 
87                 [MonoTODO]
88                 public BuildItem AddNewItem (string itemName,
89                                              string itemInclude,
90                                              bool treatItemIncludeAsLiteral)
91                 {
92                         BuildItem item;
93
94                         if (treatItemIncludeAsLiteral)
95                                 itemInclude = Utilities.Escape (itemInclude);
96
97                         if (FromXml) {
98                                 XmlElement element = itemGroupElement.OwnerDocument.CreateElement (itemName, Project.XmlNamespace);
99                                 itemGroupElement.AppendChild (element);
100                                 element.SetAttribute ("Include", itemInclude);
101                                 item = new BuildItem (element, this);
102                         } else {
103                                 item = new BuildItem (itemName, itemInclude);
104                                 item.ParentItemGroup = this;
105                         }
106
107                         item.Evaluate (null, true);
108
109                         if (!read_only)
110                                 buildItems.Add (item);
111
112                         if (parentProject != null) {
113                                 parentProject.MarkProjectAsDirty ();
114                                 parentProject.NeedToReevaluate ();
115                         }
116
117                         return item;
118                 }
119                 
120                 public void Clear ()
121                 {
122                         if (FromXml)
123                                 itemGroupElement.RemoveAll ();
124                         
125                         buildItems = new List <BuildItem> ();
126
127                         if (parentProject != null) {
128                                 parentProject.MarkProjectAsDirty ();
129                                 parentProject.NeedToReevaluate ();
130                         }
131                 }
132
133                 [MonoTODO]
134                 public BuildItemGroup Clone (bool deepClone)
135                 {
136                         if (deepClone) {
137                                 if (FromXml)
138                                         throw new NotImplementedException ();
139                                 else
140                                         throw new NotImplementedException ();
141                         } else {
142                                 if (FromXml)
143                                         throw new InvalidOperationException ("A shallow clone of this object cannot be created.");
144                                 else
145                                         throw new NotImplementedException ();
146                         }
147                 }
148
149                 public IEnumerator GetEnumerator ()
150                 {
151                         return buildItems.GetEnumerator ();
152                 }
153
154                 public void RemoveItem (BuildItem itemToRemove)
155                 {
156                         if (itemToRemove == null)
157                                 return;
158
159                         itemToRemove.Detach ();
160
161                         buildItems.Remove (itemToRemove);
162                 }
163
164                 public void RemoveItemAt (int index)
165                 {
166                         BuildItem item = buildItems [index];
167
168                         RemoveItem (item);
169                 }
170
171                 public BuildItem[] ToArray ()
172                 {
173                         return buildItems.ToArray ();
174                 }
175
176                 internal void AddItem (BuildItem buildItem)
177                 {
178                         buildItems.Add (buildItem);
179                 }
180
181                 internal void AddItem (string name, ITaskItem taskItem)
182                 {
183                         BuildItem buildItem;
184                         buildItem = new BuildItem (name, taskItem);
185                         buildItem.ParentItemGroup = this;
186                         buildItems.Add (buildItem);
187                 }
188
189                 // In eval phase, any ref'ed item would've already been expanded
190                 // or it doesnt exist, so dont expand again
191                 // In non-eval, items have _already_ been expanded, so dont expand again
192                 // So, ignore @options
193                 internal string ConvertToString (Expression transform,
194                                                  Expression separator, ExpressionOptions options)
195                 {
196                         string separatorString;
197                         
198                         // Item refs are not expanded for separator or transform
199                         if (separator == null)
200                                 separatorString = ";";
201                         else
202                                 separatorString = (string) separator.ConvertTo (parentProject, typeof (string),
203                                                                 ExpressionOptions.DoNotExpandItemRefs);
204                 
205                         string[] items = new string [buildItems.Count];
206                         int i = 0;
207                         foreach (BuildItem bi in  buildItems)
208                                 items [i++] = bi.ConvertToString (transform, ExpressionOptions.DoNotExpandItemRefs);
209                         return String.Join (separatorString, items);
210                 }
211
212                 // In eval phase, any ref'ed item would've already been expanded
213                 // or it doesnt exist, so dont expand again
214                 // In non-eval, items have _already_ been expanded, so dont expand again
215                 // So, ignore @options
216                 internal ITaskItem[] ConvertToITaskItemArray (Expression transform, Expression separator, ExpressionOptions options)
217                 {
218                         if (separator != null)
219                                 // separator present, so return as a single "join'ed" string
220                                 return new ITaskItem [] {
221                                         new TaskItem (ConvertToString (transform, separator, options))
222                                 };
223
224                         ITaskItem[] array = new ITaskItem [buildItems.Count];
225                         int i = 0;
226                         foreach (BuildItem item in buildItems)
227                                 array [i++] = item.ConvertToITaskItem (transform, ExpressionOptions.DoNotExpandItemRefs);
228                         return array;
229                 }
230
231                 internal void Detach ()
232                 {
233                         if (!FromXml)
234                                 throw new InvalidOperationException ();
235
236                         itemGroupElement.ParentNode.RemoveChild (itemGroupElement);
237                 }
238
239                 internal void Evaluate ()
240                 {
241                         if (evaluated)
242                                 return;
243                         foreach (BuildItem bi in buildItems) {
244                                 if (bi.Condition == String.Empty)
245                                         bi.Evaluate (parentProject, true);
246                                 else {
247                                         ConditionExpression ce = ConditionParser.ParseCondition (bi.Condition);
248                                         bi.Evaluate (parentProject, ce.BoolEvaluate (parentProject));
249                                 }
250                         }
251                         evaluated = true;
252                 }               
253
254                 internal void ReplaceWith (BuildItem item, List <BuildItem> list)
255                 {
256                         int index = buildItems.IndexOf (item);
257                         buildItems.RemoveAt (index);
258                         buildItems.InsertRange (index, list);
259                 }
260                 
261                 public string Condition {
262                         get {
263                                 if (FromXml)
264                                         return itemGroupElement.GetAttribute ("Condition");
265                                 else
266                                         return String.Empty;
267                         }
268                         set {
269                                 if (FromXml)
270                                         itemGroupElement.SetAttribute ("Condition", value);
271                                 else
272                                         throw new InvalidOperationException ("Cannot set a condition on an object not represented by an XML element in the project file.");
273                         }
274                 }
275
276                 public int Count {
277                         get { return buildItems.Count; }
278                 }
279
280                 public bool IsImported {
281                         get { return importedProject != null; }
282                 }
283
284                 
285                 [MonoTODO]
286                 public BuildItem this [int index] {
287                         get {
288                                 return buildItems [index];
289                         }
290                 }
291                 
292                 internal GroupingCollection GroupingCollection {
293                         get { return parentCollection; }
294                         set { parentCollection = value; }
295                 }
296                 
297                 internal Project ParentProject {
298                         get { return parentProject; }
299                         set {
300                                 if (parentProject != null)
301                                         throw new InvalidOperationException ("parentProject is already set");
302                                 parentProject = value;
303                         }
304                 }
305
306                 internal bool FromXml {
307                         get {
308                                 return itemGroupElement != null;
309                         }
310                 }
311
312                 internal XmlElement XmlElement {
313                         get {
314                                 return itemGroupElement;
315                         }       
316                 }
317         }
318 }
319
320 #endif