2010-04-06 Jb Evain <jbevain@novell.com>
[mcs.git] / class / Microsoft.Build.Engine / Microsoft.Build.BuildEngine / BuildPropertyGroup.cs
blobdd3259675c920b8bb89c01c44b980f1b58a6fe08
1 //
2 // BuildPropertyGroup.cs: Represents a group of properties
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:
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.
28 #if NET_2_0
30 using System;
31 using System.Collections;
32 using System.Collections.Generic;
33 using System.Reflection;
34 using System.Text;
35 using System.Xml;
37 namespace Microsoft.Build.BuildEngine {
38 public class BuildPropertyGroup : IEnumerable {
40 bool read_only;
41 ImportedProject importedProject;
42 XmlElement propertyGroup;
43 GroupingCollection parentCollection;
44 Project parentProject;
45 List <BuildProperty> properties;
46 Dictionary <string, BuildProperty> propertiesByName;
47 bool evaluated;
49 public BuildPropertyGroup ()
50 : this (null, null, null, false)
54 internal BuildPropertyGroup (XmlElement xmlElement, Project project, ImportedProject importedProject, bool readOnly)
56 this.importedProject = importedProject;
57 this.parentCollection = null;
58 this.parentProject = project;
59 this.propertyGroup = xmlElement;
60 this.read_only = readOnly;
62 if (FromXml) {
63 this.properties = new List <BuildProperty> ();
64 foreach (XmlNode xn in propertyGroup.ChildNodes) {
65 if (!(xn is XmlElement))
66 continue;
68 XmlElement xe = (XmlElement) xn;
69 BuildProperty bp = new BuildProperty (parentProject, xe);
70 AddProperty (bp);
72 } else
73 this.propertiesByName = new Dictionary <string, BuildProperty> (StringComparer.InvariantCultureIgnoreCase);
76 public BuildProperty AddNewProperty (string propertyName,
77 string propertyValue)
79 return AddNewProperty (propertyName, propertyValue, false);
82 public BuildProperty AddNewProperty (string propertyName,
83 string propertyValue,
84 bool treatPropertyValueAsLiteral)
86 if (!FromXml)
87 throw new InvalidOperationException ("This method is only valid for persisted property groups.");
89 if (treatPropertyValueAsLiteral)
90 propertyValue = Utilities.Escape (propertyValue);
92 XmlElement element = propertyGroup.OwnerDocument.CreateElement (propertyName, Project.XmlNamespace);
93 propertyGroup.AppendChild (element);
95 BuildProperty property = new BuildProperty (parentProject, element);
96 property.Value = propertyValue;
97 AddProperty (property);
99 parentProject.MarkProjectAsDirty ();
100 parentProject.NeedToReevaluate ();
102 return property;
105 internal void AddProperty (BuildProperty property)
107 if (FromXml)
108 properties.Add (property);
109 else {
110 if (propertiesByName.ContainsKey (property.Name)) {
111 BuildProperty existing = propertiesByName [property.Name];
112 if (property.PropertyType <= existing.PropertyType) {
113 propertiesByName.Remove (property.Name);
114 propertiesByName.Add (property.Name, property);
116 } else
117 propertiesByName.Add (property.Name, property);
121 public void Clear ()
123 if (FromXml) {
124 propertyGroup.RemoveAll ();
125 properties = new List <BuildProperty> ();
126 } else
127 propertiesByName = new Dictionary <string, BuildProperty> ();
130 [MonoTODO]
131 public BuildPropertyGroup Clone (bool deepClone)
133 BuildPropertyGroup bpg = new BuildPropertyGroup (propertyGroup, parentProject, importedProject, read_only);
134 if (FromXml) {
135 foreach (BuildProperty bp in properties) {
136 if (deepClone)
137 bpg.AddProperty (bp.Clone (true));
138 else
139 bpg.AddNewProperty (bp.Name, bp.FinalValue);
141 } else {
142 foreach (BuildProperty bp in propertiesByName.Values) {
143 if (deepClone)
144 bpg.AddProperty (bp.Clone (true));
145 else
146 bpg.AddNewProperty (bp.Name, bp.FinalValue);
150 return bpg;
153 public IEnumerator GetEnumerator ()
155 if (FromXml)
156 foreach (BuildProperty bp in properties)
157 yield return bp;
158 else
159 foreach (KeyValuePair <string, BuildProperty> kvp in propertiesByName)
160 yield return kvp.Value;
163 public void RemoveProperty (BuildProperty propertyToRemove)
165 if (propertyToRemove == null)
166 throw new ArgumentNullException ("propertyToRemove");
168 if (FromXml) {
169 if (!propertyToRemove.FromXml)
170 throw new InvalidOperationException ("The specified property does not belong to the current property group.");
172 propertyToRemove.XmlElement.ParentNode.RemoveChild (propertyToRemove.XmlElement);
173 properties.Remove (propertyToRemove);
174 } else
175 propertiesByName.Remove (propertyToRemove.Name);
178 public void RemoveProperty (string propertyName)
180 if (FromXml) {
181 foreach (BuildProperty bp in properties)
182 if (bp.Name == propertyName) {
183 RemoveProperty (bp);
184 break;
186 } else
187 propertiesByName.Remove (propertyName);
190 public void SetProperty (string propertyName,
191 string propertyValue)
193 SetProperty (propertyName, propertyValue, false);
196 public void SetProperty (string propertyName,
197 string propertyValue,
198 bool treatPropertyValueAsLiteral)
200 if (read_only)
201 return;
202 if (FromXml)
203 throw new InvalidOperationException (
204 "This method is only valid for virtual property groups, not <PropertyGroup> elements.");
206 if (treatPropertyValueAsLiteral)
207 propertyValue = Utilities.Escape (propertyValue);
209 if (propertiesByName.ContainsKey (propertyName))
210 propertiesByName.Remove (propertyName);
212 BuildProperty bp = new BuildProperty (propertyName, propertyValue);
213 if (Char.IsDigit (propertyName [0]))
214 throw new ArgumentException (String.Format (
215 "The name \"{0}\" contains an invalid character \"{1}\".", propertyName, propertyName [0]));
217 AddProperty (bp);
219 if (IsGlobal)
220 parentProject.NeedToReevaluate ();
223 internal void Evaluate ()
225 if (evaluated)
226 return;
228 foreach (BuildProperty bp in properties)
229 if (ConditionParser.ParseAndEvaluate (bp.Condition, parentProject))
230 bp.Evaluate ();
232 evaluated = true;
235 public string Condition {
236 get {
237 if (!FromXml)
238 return String.Empty;
239 return propertyGroup.GetAttribute ("Condition");
241 set {
242 if (!FromXml)
243 throw new InvalidOperationException (
244 "Cannot set a condition on an object not represented by an XML element in the project file.");
245 propertyGroup.SetAttribute ("Condition", value);
249 public int Count {
250 get {
251 if (FromXml)
252 return properties.Count;
253 else
254 return propertiesByName.Count;
258 public bool IsImported {
259 get {
260 return importedProject != null;
264 internal bool FromXml {
265 get {
266 return propertyGroup != null;
270 bool IsGlobal {
271 get {
272 return parentProject != null && propertyGroup == null;
276 public BuildProperty this [string propertyName] {
277 get {
278 if (FromXml)
279 throw new InvalidOperationException ("Properties in persisted property groups cannot be accessed by name.");
281 if (propertiesByName.ContainsKey (propertyName))
282 return propertiesByName [propertyName];
283 else
284 return null;
286 set {
287 propertiesByName [propertyName] = value;
291 internal GroupingCollection GroupingCollection {
292 get { return parentCollection; }
293 set { parentCollection = value; }
296 internal XmlElement XmlElement {
297 get { return propertyGroup; }
302 #endif