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;
47 BuildItemGroup parentItemGroup;
49 IDictionary evaluatedMetadata;
50 IDictionary unevaluatedMetadata;
56 public BuildItem (string itemName, ITaskItem taskItem)
59 this.finalItemSpec = taskItem.ItemSpec;
60 this.evaluatedMetadata = (Hashtable) taskItem.CloneCustomMetadata ();
61 this.unevaluatedMetadata = (Hashtable) taskItem.CloneCustomMetadata ();
64 public BuildItem (string itemName, string itemInclude)
67 this.finalItemSpec = itemInclude;
68 this.unevaluatedMetadata = CollectionsUtil.CreateCaseInsensitiveHashtable ();
69 this.evaluatedMetadata = CollectionsUtil.CreateCaseInsensitiveHashtable ();
72 internal BuildItem (XmlElement itemElement, BuildItemGroup parentItemGroup)
74 this.isImported = false;
75 this.unevaluatedMetadata = CollectionsUtil.CreateCaseInsensitiveHashtable ();
76 this.evaluatedMetadata = CollectionsUtil.CreateCaseInsensitiveHashtable ();
77 this.parentItemGroup = parentItemGroup;
78 BindToXml (itemElement);
81 private BuildItem (BuildItem parent)
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);
90 public void CopyCustomMetadataTo (BuildItem destinationItem)
92 foreach (DictionaryEntry de in unevaluatedMetadata)
93 destinationItem.SetMetadata ((string) de.Key, (string) de.Value);
97 public BuildItem Clone ()
99 return (BuildItem) this.MemberwiseClone ();
102 public string GetEvaluatedMetadata (string metadataName)
104 if (evaluatedMetadata.Contains (metadataName))
105 return (string) evaluatedMetadata [metadataName];
110 public string GetMetadata (string metadataName)
112 if (ReservedNameUtils.IsReservedMetadataName (metadataName))
113 return ReservedNameUtils.GetReservedMetadata (FinalItemSpec, metadataName);
114 else if (evaluatedMetadata.Contains (metadataName) == true)
115 return (string) evaluatedMetadata [metadataName];
120 public bool HasMetadata (string metadataName)
122 return evaluatedMetadata.Contains (metadataName);
125 public void RemoveMetadata (string metadataName)
127 if (metadataName == null)
128 throw new ArgumentNullException ("metadataName");
130 if (ReservedNameUtils.IsReservedMetadataName (metadataName))
131 throw new ArgumentException ("Can't remove reserved metadata.");
133 if (evaluatedMetadata.Contains (metadataName))
134 evaluatedMetadata.Remove (metadataName);
136 if (unevaluatedMetadata.Contains (metadataName))
137 unevaluatedMetadata.Remove (metadataName);
140 public void SetMetadata (string metadataName,
141 string metadataValue)
143 SetMetadata (metadataName, metadataValue, false);
146 // FIXME: don't use expression when we treat it as literal
148 public void SetMetadata (string metadataName,
149 string metadataValue,
150 bool treatMetadataValueAsLiteral)
152 if (metadataName == null)
153 throw new ArgumentNullException ("metadataName");
155 if (metadataValue == null)
156 throw new ArgumentNullException ("metadataValue");
158 if (ReservedNameUtils.IsReservedMetadataName (metadataName))
159 throw new ArgumentException ("Can't modify reserved metadata.");
161 RemoveMetadata (metadataName);
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)));
169 private void BindToXml (XmlElement xmlElement)
171 if (xmlElement == null)
172 throw new ArgumentNullException ("xmlElement");
174 this.itemElement = xmlElement;
175 this.name = xmlElement.Name;
177 if (Include == String.Empty)
178 throw new InvalidProjectFileException ("Item must have Include attribute.");
180 foreach (XmlElement xe in xmlElement.ChildNodes) {
181 this.SetMetadata (xe.Name, xe.InnerText);
185 internal void Evaluate ()
187 DirectoryScanner directoryScanner;
188 OldExpression includeExpr, excludeExpr;
189 string includes, excludes;
191 includeExpr = new OldExpression (parentItemGroup.Project);
192 includeExpr.ParseSource (Include);
193 excludeExpr = new OldExpression (parentItemGroup.Project);
194 excludeExpr.ParseSource (Exclude);
196 includes = (string) includeExpr.ConvertTo (typeof (string));
197 excludes = (string) excludeExpr.ConvertTo (typeof (string));
199 this.finalItemSpec = includes;
201 directoryScanner = new DirectoryScanner ();
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));
208 directoryScanner.BaseDirectory = new DirectoryInfo (Directory.GetCurrentDirectory ());
211 directoryScanner.Scan ();
213 foreach (string matchedFile in directoryScanner.MatchedFilenames) {
214 AddEvaluatedItem (matchedFile);
218 private void AddEvaluatedItem (string itemSpec)
220 Project project = this.parentItemGroup.Project;
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);
230 ((BuildItemGroup) project.EvaluatedItemsByName [bi.name]).AddItem (bi);
234 internal string ConvertToString (OldExpression transform)
236 return GetItemSpecFromTransform (transform);
239 internal ITaskItem ConvertToITaskItem (OldExpression transform)
242 taskItem = new TaskItem (GetItemSpecFromTransform (transform), evaluatedMetadata);
246 private string GetItemSpecFromTransform (OldExpression transform)
250 if (transform == null)
251 return finalItemSpec;
253 sb = new StringBuilder ();
254 foreach (object o in transform.Collection) {
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));
265 return sb.ToString ();
269 public string Condition {
270 get { return itemElement.GetAttribute ("Condition"); }
271 set { itemElement.SetAttribute ("Condition", value); }
274 public string Exclude {
275 get { return itemElement.GetAttribute ("Exclude"); }
276 set { itemElement.SetAttribute ("Exclude", value); }
279 public string FinalItemSpec {
280 get { return finalItemSpec; }
283 public string Include {
284 get { return itemElement.GetAttribute ("Include"); }
285 set { itemElement.SetAttribute ("Include", value); }
288 public bool IsImported {
289 get { return isImported; }
294 set { name = value; }
297 internal bool FromXml {
299 return itemElement != null;