merge -r 61110:61111
[mono.git] / mcs / class / Microsoft.Build.Engine / Microsoft.Build.BuildEngine / BuildItem.cs
1 //
2 // BuildItem.cs:
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.Collections;
32 using System.Collections.Specialized;
33 using System.IO;
34 using System.Text;
35 using System.Xml;
36 using Microsoft.Build.Framework;
37 using Microsoft.Build.Utilities;
38 using Mono.XBuild.Utilities;
39
40 namespace Microsoft.Build.BuildEngine {
41         public class BuildItem {
42
43                 XmlElement      itemElement;
44                 string          finalItemSpec;
45                 bool            isImported;
46                 string          name;
47                 BuildItemGroup  parentItemGroup;
48                 string          recursiveDir;
49                 IDictionary     evaluatedMetadata;
50                 IDictionary     unevaluatedMetadata;
51
52                 private BuildItem ()
53                 {
54                 }
55                 
56                 public BuildItem (string itemName, ITaskItem taskItem)
57                 {
58                         this.name = itemName;
59                         this.finalItemSpec = taskItem.ItemSpec;
60                         this.evaluatedMetadata = (Hashtable) taskItem.CloneCustomMetadata ();
61                         this.unevaluatedMetadata = (Hashtable) taskItem.CloneCustomMetadata ();
62                 }
63
64                 public BuildItem (string itemName, string itemInclude)
65                 {
66                         this.name = itemName;
67                         this.finalItemSpec = itemInclude;
68                         this.unevaluatedMetadata = CollectionsUtil.CreateCaseInsensitiveHashtable ();
69                         this.evaluatedMetadata = CollectionsUtil.CreateCaseInsensitiveHashtable ();
70                 }
71                 
72                 internal BuildItem (XmlElement itemElement, BuildItemGroup parentItemGroup)
73                 {
74                         this.isImported = false;
75                         this.unevaluatedMetadata = CollectionsUtil.CreateCaseInsensitiveHashtable ();
76                         this.evaluatedMetadata = CollectionsUtil.CreateCaseInsensitiveHashtable ();
77                         this.parentItemGroup = parentItemGroup;
78                         BindToXml (itemElement);
79                 }
80                 
81                 private BuildItem (BuildItem parent)
82                 {
83                         this.isImported = parent.isImported;
84                         this.name = parent.name;
85                         this.parentItemGroup = parent.parentItemGroup;
86                         this.unevaluatedMetadata = CollectionsUtil.CreateCaseInsensitiveHashtable (parent.unevaluatedMetadata);
87                         this.evaluatedMetadata = CollectionsUtil.CreateCaseInsensitiveHashtable (parent.evaluatedMetadata);
88                 }
89                 
90                 public void CopyCustomMetadataTo (BuildItem destinationItem)
91                 {
92                         foreach (DictionaryEntry de in unevaluatedMetadata)
93                                 destinationItem.SetMetadata ((string) de.Key, (string) de.Value);
94                 }
95                 
96                 [MonoTODO]
97                 public BuildItem Clone ()
98                 {
99                         return (BuildItem) this.MemberwiseClone ();
100                 }
101
102                 public string GetEvaluatedMetadata (string metadataName)
103                 {
104                         if (evaluatedMetadata.Contains (metadataName))
105                                 return (string) evaluatedMetadata [metadataName];
106                         else
107                                 return String.Empty;
108                 }
109
110                 public string GetMetadata (string metadataName)
111                 {
112                         if (ReservedNameUtils.IsReservedMetadataName (metadataName))
113                                 return ReservedNameUtils.GetReservedMetadata (FinalItemSpec, metadataName);
114                         else if (evaluatedMetadata.Contains (metadataName) == true)
115                                 return (string) evaluatedMetadata [metadataName];
116                         else
117                                 return String.Empty;
118                 }
119                 
120                 public bool HasMetadata (string metadataName)
121                 {
122                         return evaluatedMetadata.Contains (metadataName);
123                 }
124
125                 public void RemoveMetadata (string metadataName)
126                 {
127                         if (metadataName == null)
128                                 throw new ArgumentNullException ("metadataName");
129                         
130                         if (ReservedNameUtils.IsReservedMetadataName (metadataName))
131                                 throw new ArgumentException ("Can't remove reserved metadata.");
132                         
133                         if (evaluatedMetadata.Contains (metadataName))
134                                 evaluatedMetadata.Remove (metadataName);
135                         
136                         if (unevaluatedMetadata.Contains (metadataName))
137                                 unevaluatedMetadata.Remove (metadataName);
138                 }
139
140                 public void SetMetadata (string metadataName,
141                                          string metadataValue)
142                 {
143                         SetMetadata (metadataName, metadataValue, false);
144                 }
145                 
146                 // FIXME: don't use expression when we treat it as literal
147                 [MonoTODO]
148                 public void SetMetadata (string metadataName,
149                                          string metadataValue,
150                                          bool treatMetadataValueAsLiteral)
151                 {
152                         if (metadataName == null)
153                                 throw new ArgumentNullException ("metadataName");
154                         
155                         if (metadataValue == null)
156                                 throw new ArgumentNullException ("metadataValue");
157                         
158                         if (ReservedNameUtils.IsReservedMetadataName (metadataName))
159                                 throw new ArgumentException ("Can't modify reserved metadata.");
160                         
161                         RemoveMetadata (metadataName);
162                         
163                         unevaluatedMetadata.Add (metadataName, metadataValue);
164                         OldExpression finalValue = new OldExpression (parentItemGroup.Project);
165                         finalValue.ParseSource (metadataValue);
166                         evaluatedMetadata.Add (metadataName, (string) finalValue.ConvertTo (typeof (string)));
167                 }
168                 
169                 private void BindToXml (XmlElement xmlElement)
170                 {
171                         if (xmlElement == null)
172                                 throw new ArgumentNullException ("xmlElement");
173                         
174                         this.itemElement = xmlElement;
175                         this.name = xmlElement.Name;
176                         
177                         if (Include == String.Empty)
178                                 throw new InvalidProjectFileException ("Item must have Include attribute.");
179                         
180                         foreach (XmlElement xe in xmlElement.ChildNodes) {
181                                 this.SetMetadata (xe.Name, xe.InnerText);
182                         }
183                 }
184
185                 internal void Evaluate ()
186                 {
187                         DirectoryScanner directoryScanner;
188                         OldExpression includeExpr, excludeExpr;
189                         string includes, excludes;
190
191                         includeExpr = new OldExpression (parentItemGroup.Project);
192                         includeExpr.ParseSource (Include);
193                         excludeExpr = new OldExpression (parentItemGroup.Project);
194                         excludeExpr.ParseSource (Exclude);
195                         
196                         includes = (string) includeExpr.ConvertTo (typeof (string));
197                         excludes = (string) excludeExpr.ConvertTo (typeof (string));
198
199                         this.finalItemSpec = includes;
200                         
201                         directoryScanner = new DirectoryScanner ();
202                         
203                         directoryScanner.Includes = includes;
204                         directoryScanner.Excludes = excludes;
205                         if (parentItemGroup.Project.FullFileName != String.Empty) {
206                                 directoryScanner.BaseDirectory = new DirectoryInfo (Path.GetDirectoryName (parentItemGroup.Project.FullFileName));
207                         } else {
208                                 directoryScanner.BaseDirectory = new DirectoryInfo (Directory.GetCurrentDirectory ());
209                         }
210                         
211                         directoryScanner.Scan ();
212                         
213                         foreach (string matchedFile in directoryScanner.MatchedFilenames) {
214                                 AddEvaluatedItem (matchedFile);
215                         }
216                 }
217                 
218                 private void AddEvaluatedItem (string itemSpec)
219                 {
220                         Project project = this.parentItemGroup.Project;
221                         
222                         BuildItem bi = new BuildItem (this);
223                         bi.finalItemSpec = itemSpec;
224                         project.EvaluatedItems.AddItem (bi);
225                         if (project.EvaluatedItemsByName.Contains (bi.name) == false) {
226                                 BuildItemGroup big = new BuildItemGroup (null, project);
227                                 project.EvaluatedItemsByName.Add (bi.name, big);
228                                 big.AddItem (bi);
229                         } else {
230                                 ((BuildItemGroup) project.EvaluatedItemsByName [bi.name]).AddItem (bi);
231                         }
232                 }
233                 
234                 internal string ConvertToString (OldExpression transform)
235                 {
236                         return GetItemSpecFromTransform (transform);
237                 }
238                 
239                 internal ITaskItem ConvertToITaskItem (OldExpression transform)
240                 {
241                         TaskItem taskItem;
242                         taskItem = new TaskItem (GetItemSpecFromTransform (transform), evaluatedMetadata);
243                         return taskItem;
244                 }
245
246                 private string GetItemSpecFromTransform (OldExpression transform)
247                 {
248                         StringBuilder sb;
249                 
250                         if (transform == null)
251                                 return finalItemSpec;
252                         else {
253                                 sb = new StringBuilder ();
254                                 foreach (object o in transform.Collection) {
255                                         if (o is string) {
256                                                 sb.Append ((string)o);
257                                         } else if (o is PropertyReference) {
258                                                 sb.Append (((PropertyReference)o).ConvertToString ());
259                                         } else if (o is ItemReference) {
260                                                 sb.Append (((ItemReference)o).ConvertToString ());
261                                         } else if (o is MetadataReference) {
262                                                 sb.Append (GetMetadata (((MetadataReference)o).MetadataName));
263                                         }
264                                 }
265                                 return sb.ToString ();
266                         }
267                 }
268
269                 public string Condition {
270                         get { return itemElement.GetAttribute ("Condition"); }
271                         set { itemElement.SetAttribute ("Condition", value); }
272                 }
273
274                 public string Exclude {
275                         get { return itemElement.GetAttribute ("Exclude"); }
276                         set { itemElement.SetAttribute ("Exclude", value); }
277                 }
278
279                 public string FinalItemSpec {
280                         get { return finalItemSpec; }
281                 }
282
283                 public string Include {
284                         get { return itemElement.GetAttribute ("Include"); }
285                         set { itemElement.SetAttribute ("Include", value); }
286                 }
287
288                 public bool IsImported {
289                         get { return isImported; }
290                 }
291
292                 public string Name {
293                         get { return name; }
294                         set { name = value; }
295                 }
296                 
297                 internal bool FromXml {
298                         get {
299                                 return itemElement != null;
300                         }
301                 }
302         }
303 }
304
305 #endif