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;
38 using Mono.XBuild.Utilities;
40 namespace Microsoft.Build.BuildEngine {
41 public class BuildItem {
43 XmlElement itemElement;
48 BuildItemGroup parentItemGroup;
50 IDictionary evaluatedMetadata;
51 IDictionary unevaluatedMetadata;
57 public BuildItem (string itemName, ITaskItem taskItem)
60 this.finalItemSpec = taskItem.ItemSpec;
61 this.itemInclude = Utilities.Escape (taskItem.ItemSpec);
62 this.evaluatedMetadata = (Hashtable) taskItem.CloneCustomMetadata ();
63 this.unevaluatedMetadata = (Hashtable) taskItem.CloneCustomMetadata ();
66 public BuildItem (string itemName, string itemInclude)
69 this.finalItemSpec = itemInclude;
70 this.unevaluatedMetadata = CollectionsUtil.CreateCaseInsensitiveHashtable ();
71 this.evaluatedMetadata = CollectionsUtil.CreateCaseInsensitiveHashtable ();
74 internal BuildItem (XmlElement itemElement, BuildItemGroup parentItemGroup)
76 this.isImported = false;
77 this.unevaluatedMetadata = CollectionsUtil.CreateCaseInsensitiveHashtable ();
78 this.evaluatedMetadata = CollectionsUtil.CreateCaseInsensitiveHashtable ();
79 this.parentItemGroup = parentItemGroup;
80 BindToXml (itemElement);
83 private BuildItem (BuildItem parent)
85 this.isImported = parent.isImported;
86 this.name = parent.name;
87 this.parentItemGroup = parent.parentItemGroup;
88 this.unevaluatedMetadata = CollectionsUtil.CreateCaseInsensitiveHashtable (parent.unevaluatedMetadata);
89 this.evaluatedMetadata = CollectionsUtil.CreateCaseInsensitiveHashtable (parent.evaluatedMetadata);
92 public void CopyCustomMetadataTo (BuildItem destinationItem)
94 foreach (DictionaryEntry de in unevaluatedMetadata)
95 destinationItem.SetMetadata ((string) de.Key, (string) de.Value);
99 public BuildItem Clone ()
101 return (BuildItem) this.MemberwiseClone ();
104 public string GetEvaluatedMetadata (string metadataName)
106 if (evaluatedMetadata.Contains (metadataName))
107 return (string) evaluatedMetadata [metadataName];
112 public string GetMetadata (string metadataName)
114 if (ReservedNameUtils.IsReservedMetadataName (metadataName))
115 return ReservedNameUtils.GetReservedMetadata (FinalItemSpec, metadataName);
116 else if (evaluatedMetadata.Contains (metadataName) == true)
117 return (string) evaluatedMetadata [metadataName];
122 public bool HasMetadata (string metadataName)
124 return evaluatedMetadata.Contains (metadataName);
127 public void RemoveMetadata (string metadataName)
129 if (metadataName == null)
130 throw new ArgumentNullException ("metadataName");
132 if (ReservedNameUtils.IsReservedMetadataName (metadataName))
133 throw new ArgumentException ("Can't remove reserved metadata.");
135 if (evaluatedMetadata.Contains (metadataName))
136 evaluatedMetadata.Remove (metadataName);
138 if (unevaluatedMetadata.Contains (metadataName))
139 unevaluatedMetadata.Remove (metadataName);
142 public void SetMetadata (string metadataName,
143 string metadataValue)
145 SetMetadata (metadataName, metadataValue, false);
148 // FIXME: don't use expression when we treat it as literal
150 public void SetMetadata (string metadataName,
151 string metadataValue,
152 bool treatMetadataValueAsLiteral)
154 if (metadataName == null)
155 throw new ArgumentNullException ("metadataName");
157 if (metadataValue == null)
158 throw new ArgumentNullException ("metadataValue");
160 if (ReservedNameUtils.IsReservedMetadataName (metadataName))
161 throw new ArgumentException ("Can't modify reserved metadata.");
163 RemoveMetadata (metadataName);
165 unevaluatedMetadata.Add (metadataName, metadataValue);
167 if (parentItemGroup != null && treatMetadataValueAsLiteral == false) {
168 OldExpression finalValue = new OldExpression (parentItemGroup.Project);
169 finalValue.ParseSource (metadataValue);
170 evaluatedMetadata.Add (metadataName, (string) finalValue.ConvertTo (typeof (string)));
172 evaluatedMetadata.Add (metadataName, metadataValue);
175 private void BindToXml (XmlElement xmlElement)
177 if (xmlElement == null)
178 throw new ArgumentNullException ("xmlElement");
180 this.itemElement = xmlElement;
181 this.name = xmlElement.Name;
183 if (Include == String.Empty)
184 throw new InvalidProjectFileException ("Item must have Include attribute.");
186 foreach (XmlElement xe in xmlElement.ChildNodes) {
187 this.SetMetadata (xe.Name, xe.InnerText);
191 internal void Evaluate ()
193 DirectoryScanner directoryScanner;
194 OldExpression includeExpr, excludeExpr;
195 string includes, excludes;
197 includeExpr = new OldExpression (parentItemGroup.Project);
198 includeExpr.ParseSource (Include);
199 excludeExpr = new OldExpression (parentItemGroup.Project);
200 excludeExpr.ParseSource (Exclude);
202 includes = (string) includeExpr.ConvertTo (typeof (string));
203 excludes = (string) excludeExpr.ConvertTo (typeof (string));
205 this.finalItemSpec = includes;
207 directoryScanner = new DirectoryScanner ();
209 directoryScanner.Includes = includes;
210 directoryScanner.Excludes = excludes;
211 if (parentItemGroup.Project.FullFileName != String.Empty) {
212 directoryScanner.BaseDirectory = new DirectoryInfo (Path.GetDirectoryName (parentItemGroup.Project.FullFileName));
214 directoryScanner.BaseDirectory = new DirectoryInfo (Directory.GetCurrentDirectory ());
217 directoryScanner.Scan ();
219 foreach (string matchedFile in directoryScanner.MatchedFilenames) {
220 AddEvaluatedItem (matchedFile);
224 private void AddEvaluatedItem (string itemSpec)
226 Project project = this.parentItemGroup.Project;
228 BuildItem bi = new BuildItem (this);
229 bi.finalItemSpec = itemSpec;
230 project.EvaluatedItems.AddItem (bi);
231 if (project.EvaluatedItemsByName.Contains (bi.name) == false) {
232 BuildItemGroup big = new BuildItemGroup (null, project);
233 project.EvaluatedItemsByName.Add (bi.name, big);
236 ((BuildItemGroup) project.EvaluatedItemsByName [bi.name]).AddItem (bi);
240 internal string ConvertToString (OldExpression transform)
242 return GetItemSpecFromTransform (transform);
245 internal ITaskItem ConvertToITaskItem (OldExpression transform)
248 taskItem = new TaskItem (GetItemSpecFromTransform (transform), evaluatedMetadata);
252 private string GetItemSpecFromTransform (OldExpression transform)
256 if (transform == null)
257 return finalItemSpec;
259 sb = new StringBuilder ();
260 foreach (object o in transform.Collection) {
262 sb.Append ((string)o);
263 } else if (o is PropertyReference) {
264 sb.Append (((PropertyReference)o).ConvertToString ());
265 } else if (o is ItemReference) {
266 sb.Append (((ItemReference)o).ConvertToString ());
267 } else if (o is MetadataReference) {
268 sb.Append (GetMetadata (((MetadataReference)o).MetadataName));
271 return sb.ToString ();
275 public string Condition {
278 return itemElement.GetAttribute ("Condition");
284 itemElement.SetAttribute ("Condition", value);
288 public string Exclude {
291 return itemElement.GetAttribute ("Exclude");
297 itemElement.SetAttribute ("Exclude", value);
301 public string FinalItemSpec {
302 get { return finalItemSpec; }
305 public string Include {
308 return itemElement.GetAttribute ("Include");
309 else if (itemInclude != null)
312 return finalItemSpec;
316 itemElement.SetAttribute ("Include", value);
320 public bool IsImported {
321 get { return isImported; }
326 set { name = value; }
329 internal bool FromXml {
331 return itemElement != null;