2006-02-26 Marek Sieradzki <marek.sieradzki@gmail.com>
[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
39 namespace Microsoft.Build.BuildEngine {
40         public class BuildItem {
41
42                 BuildItemGroup  childs;
43                 XmlAttribute    condition;
44                 XmlAttribute    exclude;
45                 string          evaluatedItemSpec;
46                 Hashtable       evaluatedMetadata;
47                 string          finalItemSpec;
48                 XmlAttribute    include;
49                 bool            isImported;
50                 XmlElement      itemElement;
51                 string          name;
52                 BuildItem       parentItem;
53                 BuildItemGroup  parentItemGroup;
54                 string          recursiveDir;
55                 Hashtable       unevaluatedMetadata;
56         
57                 public BuildItem ()
58                 {
59                         this.isImported = false;
60                         unevaluatedMetadata = CollectionsUtil.CreateCaseInsensitiveHashtable ();
61                         evaluatedMetadata = CollectionsUtil.CreateCaseInsensitiveHashtable ();
62                 }
63
64                 public BuildItem (string itemName, ITaskItem taskItem)
65                         : this ()
66                 {
67                         this.name = itemName;
68                 }
69
70                 public BuildItem (string itemName, string itemInclude)
71                         : this ()
72                 {
73                         this.name = itemName;
74                         this.finalItemSpec = itemInclude;
75                         this.evaluatedItemSpec = itemInclude;
76                 }
77
78                 public BuildItem (XmlDocument ownerDocument, string itemName,
79                                   string itemInclude)
80                         : this ()
81                 {
82                         this.name = itemName;
83                         this.finalItemSpec = itemInclude;
84                         this.evaluatedItemSpec = itemInclude;
85                 }
86                 
87                 internal BuildItem (string name, BuildItemGroup parentItemGroup)
88                         : this ()
89                 {
90                         this.name = name;
91                         this.parentItemGroup = parentItemGroup;
92                 }
93                 
94                 internal BuildItem (BuildItem parent)
95                 {
96                         this.isImported = parent.isImported;
97                         this.name = parent.name;
98                         this.parentItem = parent;
99                         this.parentItemGroup = parent.parentItemGroup;
100                         this.unevaluatedMetadata = (Hashtable) parent.unevaluatedMetadata.Clone ();
101                         this.evaluatedMetadata = (Hashtable) parent.evaluatedMetadata.Clone ();
102                         this.include = parent.include;
103                         this.exclude = parent.exclude;
104                 }
105                 
106                 internal BuildItem (string name, ITaskItem item,
107                                     BuildItemGroup parentItemGroup)
108                 {
109                         this.isImported = false;
110                         this.name = name;
111                         this.finalItemSpec = item.ItemSpec;
112                         this.evaluatedMetadata = (Hashtable) item.CloneCustomMetadata ();
113                         this.unevaluatedMetadata = (Hashtable) item.CloneCustomMetadata ();
114                 }
115                 
116                 public void CopyCustomMetadataTo (BuildItem destinationItem)
117                 {
118                         foreach (DictionaryEntry de in unevaluatedMetadata)
119                                 destinationItem.SetMetadata ((string) de.Key, (string) de.Value);
120                 }
121
122                 public string GetEvaluatedMetadata (string metadataName)
123                 {
124                         if (evaluatedMetadata.Contains (metadataName))
125                                 return (string) evaluatedMetadata [metadataName];
126                         else
127                                 return null;
128                 }
129
130                 public string GetMetadata (string metadataName)
131                 {
132                         if (evaluatedMetadata.Contains (metadataName) == true)
133                                 return (string) evaluatedMetadata [metadataName];
134                         else
135                                 return CheckBuiltinMetadata (metadataName);
136                 }
137                 
138                 private string CheckBuiltinMetadata (string metadataName)
139                 {
140                         if (File.Exists (finalItemSpec)) {
141                                 switch (metadataName.ToLower ()) {
142                                 case "fullpath":
143                                         return Path.GetFullPath (finalItemSpec);
144                                 case "rootdir":
145                                         return "/";
146                                 case "filename":
147                                         return Path.GetFileNameWithoutExtension (finalItemSpec);
148                                 case "extension":
149                                         return Path.GetExtension (finalItemSpec);
150                                 case "relativedir":
151                                         return Path.GetDirectoryName (finalItemSpec);
152                                 case "directory":
153                                         return Path.GetDirectoryName (Path.GetFullPath (finalItemSpec));
154                                 case "recursivedir":
155                                         return recursiveDir;
156                                 case "identity":
157                                         return Path.Combine (Path.GetDirectoryName (finalItemSpec), Path.GetFileName (finalItemSpec));
158                                 case "modifiedtime":
159                                         return File.GetLastWriteTime (finalItemSpec).ToString ();
160                                 case "createdtime":
161                                         return File.GetCreationTime (finalItemSpec).ToString ();
162                                 case "accessedtime":
163                                         return File.GetLastAccessTime (finalItemSpec).ToString ();
164                                 default:
165                                         return String.Empty;
166                                 }
167                         } else
168                                 return String.Empty;
169                 }
170
171                 public bool HasMetadata (string metadataName)
172                 {
173                         return evaluatedMetadata.Contains (metadataName);
174                 }
175
176                 public void RemoveMetadata (string metadataName)
177                 {
178                         if (evaluatedMetadata.Contains (metadataName))
179                                 evaluatedMetadata.Remove (metadataName);
180                         if (unevaluatedMetadata.Contains (metadataName))
181                                 unevaluatedMetadata.Remove (metadataName);
182                 }
183
184                 public void SetMetadata (string metadataName,
185                                          string metadataValue)
186                 {
187                         RemoveMetadata (metadataName);
188                         unevaluatedMetadata.Add (metadataName, metadataValue);
189                         Expression finalValue = new Expression (parentItemGroup.Project, metadataValue);
190                         evaluatedMetadata.Add (metadataName, (string) finalValue.ToNonArray (typeof (string)));
191                 }
192                 
193                 internal void BindToXml (XmlElement xmlElement)
194                 {
195                         DirectoryScanner directoryScanner;
196                         Expression includeExpr, excludeExpr;
197                         string includes, excludes;
198                         
199                         if (xmlElement == null)
200                                 throw new ArgumentNullException ("xmlElement");
201                         this.itemElement = xmlElement;
202                         this.condition = xmlElement.GetAttributeNode ("Condition");
203                         this.exclude = xmlElement.GetAttributeNode ("Exclude");
204                         this.include = xmlElement.GetAttributeNode ("Include"); 
205                         if (include == null)
206                                 throw new InvalidProjectFileException ("Item must have Include attribute.");
207                         foreach (XmlElement xe in xmlElement.ChildNodes) {
208                                 this.SetMetadata (xe.Name, xe.InnerText);
209                         }
210                         
211                         includeExpr = new Expression (parentItemGroup.Project, Include);
212                         excludeExpr = new Expression (parentItemGroup.Project, Exclude);
213                         
214                         includes = (string) includeExpr.ToNonArray (typeof (string));
215                         excludes = (string) excludeExpr.ToNonArray (typeof (string));
216                         
217                         this.evaluatedItemSpec = includes;
218                         this.finalItemSpec = includes;
219                         
220                         directoryScanner = new DirectoryScanner ();
221                         
222                         directoryScanner.Includes = includes;
223                         directoryScanner.Excludes = excludes;
224                         directoryScanner.BaseDirectory = new DirectoryInfo (Path.GetDirectoryName (parentItemGroup.Project.FullFileName));
225                         
226                         directoryScanner.Scan ();
227                         
228                         foreach (string matchedFile in directoryScanner.MatchedFilenames) {
229                                 AddChildItem (matchedFile);
230                         }
231                 }
232                 
233                 private void AddChildItem (string itemSpec)
234                 {
235                         Project project = this.parentItemGroup.Project;
236                         
237                         if (this.childs == null)
238                                 childs = new BuildItemGroup (project);
239                         BuildItem bi = childs.AddFromParentItem (this);
240                         bi.finalItemSpec = itemSpec;
241                         bi.evaluatedItemSpec = itemSpec;
242                         project.EvaluatedItems.AddItem (bi);
243                         if (project.EvaluatedItemsByName.Contains (bi.name) == false) {
244                                 BuildItemGroup big = new BuildItemGroup (project);
245                                 project.EvaluatedItemsByName.Add (bi.name, big);
246                                 big.AddItem (bi);
247                         } else {
248                                 ((BuildItemGroup) project.EvaluatedItemsByName [bi.name]).AddItem (bi);
249                         }
250                 }
251                 
252                 internal string ToString (Expression transform)
253                 {
254                         return GetItemSpecFromTransform (transform);
255                 }
256                 
257                 internal ITaskItem ToITaskItem (Expression transform)
258                 {
259                         TaskItem taskItem;
260                         taskItem = new TaskItem (GetItemSpecFromTransform (transform), (IDictionary) evaluatedMetadata.Clone ());
261                         return taskItem;
262                 }
263
264                 private string GetItemSpecFromTransform (Expression transform)
265                 {
266                         StringBuilder sb;
267                 
268                         if (transform == null)
269                                 return finalItemSpec;
270                         else {
271                                 sb = new StringBuilder ();
272                                 foreach (object o in transform) {
273                                         if (o is string) {
274                                                 sb.Append ((string)o);
275                                         } else if (o is PropertyReference) {
276                                                 sb.Append (((PropertyReference)o).ToString ());
277                                         } else if (o is ItemReference) {
278                                                 sb.Append (((ItemReference)o).ToString ());
279                                         } else if (o is MetadataReference) {
280                                                 sb.Append (GetMetadata (((MetadataReference)o).MetadataName));
281                                         }
282                                 }
283                                 return sb.ToString ();
284                         }
285                 }
286
287                 public string Condition {
288                         get {
289                                 if (condition == null)
290                                         return null;
291                                 else
292                                         return condition.Value;
293                         }
294                         set {
295                                 if (condition != null)
296                                         condition.Value = value;
297                         }
298                 }
299
300                 public string Exclude {
301                         get {
302                                 if (exclude == null)
303                                         return String.Empty;
304                                 else
305                                         return exclude.Value;
306                         }
307                         set {
308                                 if (exclude != null)
309                                         exclude.Value = value;
310                         }
311                 }
312
313                 public string FinalItemSpec {
314                         get {
315                                 return finalItemSpec;
316                         }
317                 }
318
319                 public string Include {
320                         get {
321                                 if (include == null)
322                                         return String.Empty;
323                                 else
324                                         return include.Value;
325                         }
326                         set {
327                                 if (include != null)
328                                         include.Value = value;
329                         }
330                 }
331
332                 public bool IsImported {
333                         get {
334                                 return isImported;
335                         }
336                 }
337
338                 public string Name {
339                         get {
340                                 return name;
341                         }
342                         set {
343                                 name = value;
344                         }
345                 }
346         }
347 }
348
349 #endif