5 // Marek Sieradzki (marek.sieradzki@gmail.com)
7 // (C) 2005 Marek Sieradzki
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:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
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.
31 using System.Collections;
32 using System.Collections.Specialized;
36 using Microsoft.Build.Framework;
37 using Microsoft.Build.Utilities;
39 namespace Microsoft.Build.BuildEngine {
40 public class BuildItem {
42 BuildItemGroup childs;
43 XmlAttribute condition;
45 string evaluatedItemSpec;
46 Hashtable evaluatedMetadata;
50 XmlElement itemElement;
53 BuildItemGroup parentItemGroup;
55 Hashtable unevaluatedMetadata;
59 this.isImported = false;
60 unevaluatedMetadata = CollectionsUtil.CreateCaseInsensitiveHashtable ();
61 evaluatedMetadata = CollectionsUtil.CreateCaseInsensitiveHashtable ();
64 public BuildItem (string itemName, ITaskItem taskItem)
70 public BuildItem (string itemName, string itemInclude)
74 this.finalItemSpec = itemInclude;
75 this.evaluatedItemSpec = itemInclude;
78 public BuildItem (XmlDocument ownerDocument, string itemName,
83 this.finalItemSpec = itemInclude;
84 this.evaluatedItemSpec = itemInclude;
87 internal BuildItem (string name, BuildItemGroup parentItemGroup)
91 this.parentItemGroup = parentItemGroup;
94 internal BuildItem (BuildItem parent)
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;
106 internal BuildItem (string name, ITaskItem item,
107 BuildItemGroup parentItemGroup)
109 this.isImported = false;
111 this.finalItemSpec = item.ItemSpec;
112 this.evaluatedMetadata = (Hashtable) item.CloneCustomMetadata ();
113 this.unevaluatedMetadata = (Hashtable) item.CloneCustomMetadata ();
116 public void CopyCustomMetadataTo (BuildItem destinationItem)
118 foreach (DictionaryEntry de in unevaluatedMetadata)
119 destinationItem.SetMetadata ((string) de.Key, (string) de.Value);
122 public string GetEvaluatedMetadata (string metadataName)
124 if (evaluatedMetadata.Contains (metadataName))
125 return (string) evaluatedMetadata [metadataName];
130 public string GetMetadata (string metadataName)
132 if (evaluatedMetadata.Contains (metadataName) == true)
133 return (string) evaluatedMetadata [metadataName];
135 return CheckBuiltinMetadata (metadataName);
138 private string CheckBuiltinMetadata (string metadataName)
140 if (File.Exists (finalItemSpec)) {
141 switch (metadataName.ToLower ()) {
143 return Path.GetFullPath (finalItemSpec);
147 return Path.GetFileNameWithoutExtension (finalItemSpec);
149 return Path.GetExtension (finalItemSpec);
151 return Path.GetDirectoryName (finalItemSpec);
153 return Path.GetDirectoryName (Path.GetFullPath (finalItemSpec));
157 return Path.Combine (Path.GetDirectoryName (finalItemSpec), Path.GetFileName (finalItemSpec));
159 return File.GetLastWriteTime (finalItemSpec).ToString ();
161 return File.GetCreationTime (finalItemSpec).ToString ();
163 return File.GetLastAccessTime (finalItemSpec).ToString ();
171 public bool HasMetadata (string metadataName)
173 return evaluatedMetadata.Contains (metadataName);
176 public void RemoveMetadata (string metadataName)
178 if (evaluatedMetadata.Contains (metadataName))
179 evaluatedMetadata.Remove (metadataName);
180 if (unevaluatedMetadata.Contains (metadataName))
181 unevaluatedMetadata.Remove (metadataName);
184 public void SetMetadata (string metadataName,
185 string metadataValue)
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)));
193 internal void BindToXml (XmlElement xmlElement)
195 DirectoryScanner directoryScanner;
196 Expression includeExpr, excludeExpr;
197 string includes, excludes;
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");
206 throw new InvalidProjectFileException ("Item must have Include attribute.");
207 foreach (XmlElement xe in xmlElement.ChildNodes) {
208 this.SetMetadata (xe.Name, xe.InnerText);
211 includeExpr = new Expression (parentItemGroup.Project, Include);
212 excludeExpr = new Expression (parentItemGroup.Project, Exclude);
214 includes = (string) includeExpr.ToNonArray (typeof (string));
215 excludes = (string) excludeExpr.ToNonArray (typeof (string));
217 this.evaluatedItemSpec = includes;
218 this.finalItemSpec = includes;
220 directoryScanner = new DirectoryScanner ();
222 directoryScanner.Includes = includes;
223 directoryScanner.Excludes = excludes;
224 directoryScanner.BaseDirectory = new DirectoryInfo (Path.GetDirectoryName (parentItemGroup.Project.FullFileName));
226 directoryScanner.Scan ();
228 foreach (string matchedFile in directoryScanner.MatchedFilenames) {
229 AddChildItem (matchedFile);
233 private void AddChildItem (string itemSpec)
235 Project project = this.parentItemGroup.Project;
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);
248 ((BuildItemGroup) project.EvaluatedItemsByName [bi.name]).AddItem (bi);
252 internal string ToString (Expression transform)
254 return GetItemSpecFromTransform (transform);
257 internal ITaskItem ToITaskItem (Expression transform)
260 taskItem = new TaskItem (GetItemSpecFromTransform (transform), (IDictionary) evaluatedMetadata.Clone ());
264 private string GetItemSpecFromTransform (Expression transform)
268 if (transform == null)
269 return finalItemSpec;
271 sb = new StringBuilder ();
272 foreach (object o in transform) {
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));
283 return sb.ToString ();
287 public string Condition {
289 if (condition == null)
292 return condition.Value;
295 if (condition != null)
296 condition.Value = value;
300 public string Exclude {
305 return exclude.Value;
309 exclude.Value = value;
313 public string FinalItemSpec {
315 return finalItemSpec;
319 public string Include {
324 return include.Value;
328 include.Value = value;
332 public bool IsImported {